将数组传递给非托管代码,并在不复制的情况下返回
本文关键字:复制 返回 情况下 数组 非托管代码 | 更新日期: 2023-09-27 18:36:04
我有一个C++库,我正在上面编写C#包装器。我坚持将数组传递给非托管并在 .NET 中读回它。
我想要的是一个包装函数,它将获取浮点数组作为参数(托管),在非托管函数中处理它并将其作为托管数组返回。
现在,我正在通过创建数组C++将值从托管复制到非托管,然后将其作为参数传递给本机函数调用来执行此操作。之后,我必须将结果复制回以将其发送回托管代码。
这是我目前的方法:
array<float>^ Process(int samplesCount, array<float>^ audiodata){
float* audioData[1];
//copying to unmanaged
audioData[0] = new float[samplesCount];
for (int i = 0; i < samplesCount; ++i){
audioData[0][i] = audiodata[i];
}
//process unmanaged
//int numSamples //float *const *arrayOfChannels
_filter->process(samplesCount, audioData);
//copying back from unmanaged
array<float> ^result = gcnew array<float>(samplesCount);
for (int i = 0; i < samplesCount; ++i){
result[i] = audioData[0][i];
}
return result;
}
问题是,_filter->process() 函数将 float *const *arrayOfChannels 作为第二个参数,这对我来说是最困难的。所以它会接受这样的东西:
// create a two channel audio buffer
int numSamples = 2000;
float* audioData[2];
audioData[0] = new float[numSamples];
audioData[1] = new float[numSamples];
// and somewhere after:
_filter->process (numSamples, audioData);
是否可以在不复制数组的情况下从托管环境传递float *const *arrayOfChannels
参数?
是的,您可以在不复制的情况下执行此操作。使用 pin_ptr 获取指向托管数据的普通float*
,然后将该指针放入所需的任何结构中。
请注意,通过将托管数组传递给非托管代码,您最终将更改 Process
方法的参数传递:非托管代码正在修改传递给它的数组,并且由于您将托管数组传递给非托管代码,因此您最终会在托管代码中得到这样的结果。 Process
将更改为返回void
,并修改输入数组的内容。
另请注意,如果在固定数组时发生垃圾回收,则垃圾回收器必须执行额外的工作,因为它不再允许移动内存。因此,您希望将数组固定的时间尽可能短,刚好足够长的时间以调用非托管方法。
void Process(array<float>^ channel1, array<float>^ channel2)
{
pin_ptr<float> pinned1 = &channel1[0];
float* asPointer1 = pinned1;
pin_ptr<float> pinned2 = &channel2[0];
float* asPointer2 = pinned2;
float* audioData[2];
audioData[0] = asPointer1;
audioData[1] = asPointer2;
_filter->process(channel1->Length, audioData);
}