用C#修复数组数组(不安全的代码)

时间:2011-11-14 19:59:30

标签: c# interop fixed unsafe

我正在尝试提出一个解决方案,以便我如何将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);
            }
        }
    }
}

3 个答案:

答案 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模拟两个维度(出于性能原因)。