ジャグ付き配列を使用した固定ステートメント
-
26-09-2019 - |
質問
外部メソッドに渡す必要があるギザギザの配列があります。
[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が使用されておらず、編集による削除されていることです。それに基づく固定声明よりも削除されています。そのため、ArrayはGCによって移動され、Ptrarray要素が無効になります。
ネイティブメソッドへのポインターの単一次元アレイとして、ジャグアレイを渡すための最良の方法は何ですか?
アップデート:
NativeMethodのC ++コードは次のとおりです。
NativeClass::NativeMethod(const int* array)
解決
あなたの問題は、それがあなたが使用しているものであるため、アレイを修正する必要があるという事実にあります。 GCが収集されないように、配列をピン留めすることができます。
GCHandle h = GCHandle.Alloc(array, GCHandleType.Pinned);
アップデート
正しく指摘したように、配列内の各配列もピン留めする必要があります。
他のヒント
以下のコードサンプルのように、安全でないC#コードを使用せずに、外部Pinvokeメソッドを介してC#Jagged配列を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 Partsを除外する場合、「オブジェクトには非微小または非宣言性のデータが含まれている」という引数例外が取得されます。 それで、ジャグゲアレイをピン留めすることは可能ですか?本当に必要ですか? (リリースモードのGCは、もはや使用されていない場合、メソッド内でメモリを既に記憶する可能性があることを漠然と思い出します。)ただし、JaggedArrayをクラスフィールド変数に変えると、GCの観点から安全になると思います。
所属していません StackOverflow