1

我在 C++ 非托管代码中有以下简单的 DLL;

extern "C" __declspec(dllexport) void ArrayMultiplier(float (*pointerArray)[3], int scalar, int length); 

void ArrayMultiplier(float (*pointerArray)[3], int scalar, int length) 
{
    for (int i = 0 ; i < length ; length++)
    {
        for (int j = 0; j < 3; j++)
        { 
            pointerArray[i][j] = pointerArray[i][j] * scalar;
        }
    }
}

我曾尝试在 c# 中为上述内容编写以下包装函数:

    [DllImport("sample.dll")]
public static extern void ArrayMultiplier(ref float elements, int scalar, int length);

其中 elements 是一个二维 3x3 数组:

public float[][] elements = 
        {
            new float[]  {2,5,3},
            new float []  {4,8,6},
            new float []  {5,28,3}
        };

上面给出的代码可以编译,但是在调用包装函数时程序会崩溃:

Wrapper.ArrayMultiplier(ref elements, scalar, length);

请在这里帮助我,告诉我上面的代码有什么问题,或者如何为简单的 c++ 函数编写包装器:

void SimpleFunction(float (*pointerToArray)[3]);

谢谢大家

4

1 回答 1

1

有几种方法可以做到这一点。

不安全的路线,它适用于 2D 数组(你有):

    [DllImport("fastprocessing.dll", EntryPoint = "MyFunc")]
    public static extern void MyFuncViaDLL(int inPtr, int outPtr, int inSize1, int size2, int param);

通过调用

    private unsafe float[] MyFunc(float[] inData, int inSize1, int inSize2, int param1, int param2) {
        float[] theOutData = new float[inChannelData.Length];
        fixed (float* inBufferPtr = &inChannelData[0]) {
            fixed (float* outBufferPtr = &theOutData[0]) {
                MyFuncViaDLL((int)inBufferPtr, (int)outBufferPtr, inSize1, inSize2, param);
            }
        }
        return theOutData;
    }

这将以不安全的方式工作,但您需要将输入数组更改为一维数组。无论如何,我认为这是一个更好的主意,但这正是我的想法。

如果您想安全,请添加另一个参数,即数组本身的大小,然后进行一些编组。不过,您需要再次进入一维数组:

相反,您想做一些编组,如下所示:

    [DllImport("fastprocessing.dll", EntryPoint = "MyFunc")]
    public static extern void MyFuncViaDLL([MarshalAs(UnmanagedType.LPArray)]float[] inPtr, int size1, int size2, int totalSize, int param2);

然后直接调用函数:

    MyFuncViaDLL(array, size1, size2, size1*size2, param1, param2);

然后您的 C++ 将更改为:

void ArrayMultiplier(float *pointerArray, int inSize1, int inSize2, int inTotalSize, int scalar) 
{
    int i, j, index;
    for (i = 0 ; i < size1; i++)//note that length++ would be very very wrong here
    {
        for (j = 0; j < size2; j++)
        { 
            index = i*size2 + j;
            if(index >= inTotalSize) { return; } //avoid walking off the end
            pointerArray[i*size2 +  j] *= scalar;
        }
    }
}

如果你愿意,你可以添加对总长度的检查,以确保你不会跑到最后,但这将是一个相当大的速度打击(足以不想使用 C++),好像语句不是'免费。

然而,在完成所有这些之后,我不得不问 - 为什么不直接在 C# 中执行此操作,并为自己省去编组等互操作服务的麻烦?对于复杂的事情,C++ 往往更快,但对于快速数组遍历,我已经看到 C# 表现得非常好。一旦它是一维数组,它在 C# 中也可以非常快:

 int i;
 for (i = 0; i < array.length; i++){
    array[i] *= scalar;
 }
于 2010-04-26T15:03:26.870 回答