我已经能够通过外部 Pinvoke 方法将 C# 锯齿状数组传递给 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 部分,我会得到一个参数异常“对象包含非原始或非 blittable 数据”。那么是否可以固定 jaggedArray 并且真的需要它吗?(我隐约记得,如果不再使用,释放模式下的 GC 可能会在方法中重新收集内存。)我认为,尽管将 jaggedArray 转换为类字段变量,但从 GC 的角度来看会使其安全。