将数组传递给非托管代码,并在不复制的情况下返回

本文关键字:复制 返回 情况下 数组 非托管代码 | 更新日期: 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);
}