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);

ここで、要素は 2 次元の 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;
    }

これは安全ではない方法で機能しますが、入力配列を1D配列に変更する必要があります。とにかくそれは良い考えだと思いますが、それは私が思う方法です。

安全を確保したい場合は、配列自体のサイズである別のパラメーターを追加してから、マーシャリングを実行します。ただし、繰り返しになりますが、1D配列に入る必要があります。

代わりに、次のようにマーシャリングを実行します。

    [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 ++を使用したくないので十分です)。 t無料。

ただし、これらすべてを実行した後は、質問する必要があります。これをC#で直接実行して、マーシャリングなどの相互運用サービスの手間を省いてはどうでしょうか。C ++は複雑なものの方が高速になる傾向がありますが、配列をすばやく歩くために、C#がかなりうまく動作することを確認しました。1D配列になると、C#でもかなり高速になります。

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