我正在尝试提出一个解决方案,以便我如何将C#中的数组数组传递给本机函数。我已经有了该函数的委托(Marshal.GetDelegateForFunctionPointer),但现在我正在尝试将多维数组(或者更确切地说是一个数组数组)传递给它。
当输入有2个子数组时,此代码示例有效,但我需要能够处理任意数量的子数组。您能想到的最简单的方法是什么?我不想在数组之间复制数据,因为这将在实时循环中发生(我正在与音频效果通信)
public void process(float[][] input)
{
unsafe
{
// If I know how many sub-arrays I have I can just fix them like this... but I need to handle n-many arrays
fixed (float* inp0 = input[0], inp1 = input[1] )
{
// Create the pointer array and put the pointers to input[0] and input[1] into it
float*[] inputArray = new float*[2];
inputArray[0] = inp0;
inputArray[1] = inp1;
fixed(float** inputPtr = inputArray)
{
// C function signature is someFuction(float** input, int numberOfChannels, int length)
functionDelegate(inputPtr, 2, input[0].length);
}
}
}
}
答案 0 :(得分:11)
您可以在不使用fixed
的情况下固定对象,而是获取相关对象的固定GCHandle
。当然,不用说通过这样做你负责确保指针不会超过取消固定对象的点。我们称之为“不安全”的代码是有原因的;你需要负责安全的内存管理,而不是运行时。
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle.aspx
答案 1 :(得分:0)
尝试锁定托管数组的引用数组是没有意义的。
那里的引用值可能并不指向第一个元素的地址,即使它们确实如此,也就是实现细节。它可能会在发布之间发生变化。
将指针数组复制到大量数据不应该那么慢,特别是与您调用的多媒体处理相比时不会。
如果它很重要,请在托管堆之外分配数据,然后没有固定或复制。但更多的簿记。
答案 2 :(得分:0)
我知道最简单的方法是使用一维数组。它降低了复杂性,内存碎片并且还具有更好的性能。我实际上是在我的项目中这样做的。您可以使用array[i][j] = oneDimArray[i *n + j]
之类的手动索引,并将n作为参数传递给函数。而且你只会像在你的例子中那样做一次修复:
public void process(float[] oneDimInput, int numberOfColumns)
{
unsafe
{
fixed (float* inputPtr = &oneDimInput[0])
{
// C function signature is someFuction(
// float* input,
// int number of columns in oneDimInput
// int numberOfChannels,
// int length)
functionDelegate(inputPtr, numberOfColumns, 2, oneDimInput[0].length);
}
}
}
另外我需要注意的是,在高性能计算库中很少使用的二维数组如英特尔MKL,英特尔IPP等等。甚至BLAS和Lapack接口只包含一个维度数组,并使用我提到的aproach模拟两个维度(出于性能原因)。