C# 固定语句与锯齿数组

C# 固定语句与锯齿数组,c#,pointers,pinvoke,fixed,jagged-arrays,C#,Pointers,Pinvoke,Fixed,Jagged Arrays,我有一个锯齿状数组,需要传递给外部方法 [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]) {

我有一个锯齿状数组,需要传递给外部方法

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

您的问题在于,您需要修复数组,因为这就是您正在使用的数组。您可以固定阵列,以便GC不会收集它:

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


正如您已经正确指出的,数组中的每个数组也需要钉扎。

< P>我已经能够通过一个外部的PNECKE方法将一个C锯齿数组传递给C++,而不使用下面代码示例中的不安全C代码。但我仍然担心GC在非调试模式下会产生副作用。下面是一段测试代码(在调试模式下工作):

[测试,忽略]
公共无效测试_JaggedArrayPInvoke()
{
var jaggedArray=新整数[3][];
jaggedArray[0]=新整数[1]{9};
jaggedArray[1]=新整数[4]{1,2,3,8};
jaggedArray[2]=新整数[2]{1,2};
//GCHandle mainHandle=GCHandle.Alloc(jaggedArray,GCHandleType.pinted);//这不起作用
var pinnedHandles=新的GCHandle[3];
var jaggedArrayPtrs=新IntPtr[3];
对于(int i=0;i<3;i++)
{
pinnedHandles[i]=GCHandle.Alloc(jaggedArray[i],GCHandleType.pinted);
jaggedArrayPtrs[i]=pinnedHandles[i].AddrOfPinnedObject();
}
var结果=JaggedArrayPInvoke_检验(jaggedArrayPtrs);
Console.WriteLine(result);//按其应返回的值返回8。
//mainHandle.Free();
对于(int i=0;i<3;i++)
{
pinnedHandles[i].Free();
}
}
/C++测试方法:
外部“C”uu declspec(dllexport)int_uuustdcall JaggedArrayPInvoke_u测试(int**jaggedArray);
__declspec(dllexport)内部标准呼叫JaggedArrayPInvoke测试(内部**jaggedArray)
{ 
返回jaggedArray[1][3];
}

如果我取消对mainHandle部分的注释,我会得到一个参数异常“objectcontainsinnon-primitive或non-blittable data”那么是否有可能锁定jaggedArray,它真的需要吗?(我隐约记得,如果不再使用,处于释放模式的GC可能会重新收集方法中已经存在的内存。)我认为,如果将JAGEDARDATA转换成类字段变量,反而会使它从GC角度安全。

你的本机方法看起来是什么样的实际参数?更新-添加C++代码。C++声明不是针对锯齿数组,这需要int **参数。很难帮助你,当然不是。我需要一些转换。你是对的,我正在寻找Pinned,但找不到它。现在你只需要将h.AddrOfPinnedObject()传递给本机方法。谢谢!你的想法很有帮助。我唯一想补充的是,您的代码将产生异常,因为数组是数组的数组,而不是基本类型的数组。您应该锁定(然后是.Free()!)每个数组[i],而不是数组本身。您是对的,为了完整起见,我将添加此注释
 GCHandle h = GCHandle.Alloc(array, GCHandleType.Pinned);
[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];
}