将数组传递给非托管代码并返回而不复制

时间:2016-02-23 21:13:43

标签: c# arrays multidimensional-array c++-cli parameter-passing

我有一个C ++库,我正在编写C#包装器。 我坚持将数组传递给unmanaged并在.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-&gt; 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参数?

1 个答案:

答案 0 :(得分:2)

是的,您无需复制即可完成此操作。使用pin_ptr获取指向您的托管数据的普通float*,然后将该指针放入您需要的任何结构中。

请注意,通过将托管数组传递给非托管代码,您最终将更改为Process方法传递的参数:非托管代码正在修改传递给它的数组,并且因为您和#39;将托管数组传递给非托管代码,这是您在托管代码中最终得到的内容。 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);
}