3

外部メソッドに渡す必要のあるジャグ配列があります。

[DllImport(...)]
private static extern int NativeMethod(IntPtr[] ptrArray);

...

fixed (ulong* ptr = array[0])
{
    for (int i = 0; i < array.Length; i++)
    {
        fixed (ulong* p = &array[i][0])
        {
            ptrArray[i] = new IntPtr(p);
        }
    }

    NativeMethod(ptrArray);
}

問題は、ptrが使用されておらず、コンパイルによって削除されることです。それによると、固定されたステートメントよりも削除されます。したがって、配列は、ptrArray要素が無効になるようにGCによって移動されます。

ジャグ配列をネイティブメソッドへのポインタの1次元配列として渡すための最良の方法は何ですか?

アップデート:

NativeMethodのC++コードは次のとおりです。

NativeClass::NativeMethod(const int* array)
4

2 に答える 2

3

問題は、使用している配列であるため、配列を修正する必要があるという事実にあります。GCがアレイを収集しないように、アレイを固定できます。

 GCHandle h = GCHandle.Alloc(array, GCHandleType.Pinned);

アップデート

正しく指摘したように、アレイ内の各アレイにもピン留めが必要です。

于 2010-10-27T12:25:53.260 に答える
0

以下のコードサンプルのように、安全でないC#コードを使用せずに、外部のPinvokeメソッドを介してC#ジャグ配列をC++に渡すことができました。しかし、デバッグモード以外のGCが望ましくない副作用を引き起こすことについては、まだ懸念があります。これがテストコードの一部です(デバッグモードで動作します):

[Test, Ignore]
public void Test_JaggedArrayPInvoke()
{
    var jaggedArray = new int[3][];
    jaggedArray[0] = new int[1] { 9 };
    jaggedArray[1] = new int[4] { 1, 2, 3, 8 };
    jaggedArray[2] = new int[2] { 1, 2 };

    //GCHandle mainHandle = GCHandle.Alloc(jaggedArray, GCHandleType.Pinned);   //This does not work

    var pinnedHandles = new GCHandle[3];                    
    var jaggedArrayPtrs = new IntPtr[3];
    for (int i = 0; i < 3; i++)
    {
        pinnedHandles[i] = GCHandle.Alloc(jaggedArray[i], GCHandleType.Pinned);
        jaggedArrayPtrs[i] = pinnedHandles[i].AddrOfPinnedObject();
    }

    var result = JaggedArrayPInvoke_TEST(jaggedArrayPtrs);

    Console.WriteLine(result);  //returns 8 as it should.

    //mainHandle.Free();
    for (int i = 0; i < 3; i++)
    {
        pinnedHandles[i].Free();
    }
}

//The C++ test method:

extern "C" __declspec(dllexport) int __stdcall JaggedArrayPInvoke_TEST(int** jaggedArray);
__declspec(dllexport) int __stdcall JaggedArrayPInvoke_TEST(int** jaggedArray) 
{ 
   return jaggedArray[1][3];
}

mainHandle部分のコメントを解除すると、「オブジェクトに非プリミティブまたは非ブリット可能なデータが含まれています」という引数例外が発生します。では、jaggedArrayを固定することは可能ですか?それは本当に必要ですか?(リリースモードのGCは、もう使用されていない場合、メソッド内のメモリを再収集する可能性があることを漠然と思い出します。)代わりに、jaggedArrayをクラスフィールド変数に変換すると、GCの観点から安全になると思います。

于 2011-10-14T09:05:39.670 に答える