在C#中将结构数组编组到指针

时间:2011-09-09 15:16:02

标签: c# interop pinvoke

我试图调用一个看起来像这样的非托管函数(DATA是我的C#结构):

[DllImport("data.dll")]
internal static unsafe extern int MyExternalFunction(DATA* pData, uint numElements);

这就是我从C#调用函数的方法:

DATA[] data = new DATA[64];
fixed (DATA* pData = data )
{
    MyExternalFunction(pData, 64);
}

[StructLayout(LayoutKind.Sequential)]
internal struct DATA
{
    internal uint a;
    internal uint b;
    internal uint c;
    internal POINT pos;
}

[StructLayout(LayoutKind.Sequential)]
internal struct POINT 
{
    internal int x;
    internal int y;
}

不幸的是我收到了这个错误:“无法封送'参数#1':指针无法引用封送结构。”

如果它有任何区别,我的DATA结构中有嵌套的结构。我无法控制外部方法的设计方式。调用此函数并接收结构数组的正确方法是什么?

2 个答案:

答案 0 :(得分:5)

你应该这样声明:

[DllImport("data.dll")]
public static extern int MyExternalFunction(
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]
    DATA[] Data, 
    uint numElements
);

并称之为:

MyExternalFunction(myArray, myArray.Length);

不需要不安全或固定。删除所有这些。

答案 1 :(得分:1)

试试这个:

[DllImport("data.dll")]
internal static unsafe extern int MyExternalFunction(DATA[] pData);

并完全省略C#指针。

编辑:  我没有测试,但是指针方式不起作用是有意义的,因为托管数组的内存布局与非托管数组的内存布局不同。编组人员必须有机会获取阵列并以原生格式转换它然后再返回。我不确定在这种情况下是否需要ref修饰符,但它可能是一个选项。