问题
如何以最佳方式接受C风格的数组作为参数,将其修改为D风格的数组(包括更改长度),并将其作为C风格的数组返回?
背景
我正在编写一个D库,它编译成带有C接口的DLL(我将从C++中调用我的D DLL,因此需要C接口)。
它接受byte
数组并修改其内容,有时会更改数组长度。
由于我正在使用C接口,我的函数必须以C风格接受数组。理想情况下,如果给定的缓冲区太小,我希望能够分配更多内存(即扩展bufferMaxSize
)。
这是我的D DLL目前接受参数的方式:
// D library code; compiles to DLL with C interface.
// bufferSize is the data length, and is a pointer because I may modify the data length.
// bufferMaxSize is the total allocated buffer size.
export extern(C) void patchData(const size_t bufferMaxSize, size_t * bufferSize, byte * buffer) { ... }
在我的D库中,已经存在接受D风格数组的代码。在某个地方,需要将C风格数组转换为D风格数组。
我目前是这样进行转换的(简化示例):
// D library code; compiles to DLL with C interface.
export extern(C) void patchData(const size_t bufferMaxSize, size_t * bufferSize, byte * buffer) {
// Convert from C-style array to D-style.
byte[] dStyleArray = buffer[0 .. *bufferSize];
// Modify data.
dStyleArray[0] = cast(byte) 0xab;
dStyleArray[1] = cast(byte) 0xbc;
dStyleArray.length = dStyleArray.length + 16;
// Return modified data as C-style array.
buffer[0 .. dStyleArray.length] = dStyleArray[0 .. dStyleArray.length];
*bufferSize = dStyleArray.length;
}
代码能正常运行,但是我不确定到底发生了什么。我的主要关注点是速度,如果我在循环中使用这个函数,我不希望不断地分配新的内存并来回复制它的内容。
当我执行 byte[] dStyleArray = buffer[0 .. *bufferSize]
时,D语言是否会分配一个新的内存块并将所有内容复制到D风格的数组中,还是只是指向已经分配的C风格数组?
当我执行 dStyleArray.length = dStyleArray.length + 16
时会发生什么?由于 dStyleArray
是从 buffer
切片而来的,我现在是在分配新的内存或者复制内存吗?还是扩展到了 buffer
中?
当我执行 buffer[0 .. dStyleArray.length] = dStyleArray[0 .. dStyleArray.length];
时,我正在复制内存,对吗?
是否可以将D风格的数组与C风格的数组"绑定",通过D风格数组的接口访问预先分配的内存?
byte[] dStyleArray = buffer[0 .. bufferMaxSize]
,然后像这样缩小它:dStyleArray.length = *bufferSize
,会怎么样呢?完整的切片将允许我在不分配新内存的情况下更改dSyleArray.length
(在bufferMaxSize
范围内)吗? - midrare*bufferSize <= bufferMaxSize
,它不会分配内存,因为它等价于dStyleArray = dStyleArray[0 .. *bufferSize];
。 您可能更喜欢切片语法,因为如果*bufferSize > bufferMaxSize
,它将抛出ArrayOutOfBoundException
,因此您无法使用此语法重新分配(并且这使函数成为@nogc
)。 - Geod24