无法编组'参数#':内部限制:结构过于复杂或过大

时间:2014-04-07 09:57:11

标签: c# pinvoke dllimport

我有一个用C ++开发的dll。我需要在C#中使用它。

[StructLayout(LayoutKind.Sequential, Size = 205004, Pack = 1)]
    private struct MyList
    {
        public UInt32 count;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
        public myStruct[] info;
    };

" MYSTRUCT"的尺码是2050。 我将dll方法称为

[DllImport("dllName.dll" CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 GetMyList(out MyList list);

调用dll方法时出错。 "无法编组'参数#1':内部限制:结构太复杂或太大。"

通过不更改C ++ dll部分,是否有人有解决方案?

1 个答案:

答案 0 :(得分:1)

正如错误所说,结构太大而无法通过这种方式进行编组。所以你必须找到另一种方法。

在我看来,一次一个地返回结构会更有意义。这将避免您需要硬编码列表中不超过100个结构的上限。

所以我会这样写:

<强> C ++

int GetListCount()
{
    return count;
}

int GetListItem(int index, myStruct* item)
{
    if (index < 0)
        return -1;
    if (index >= count)
        return -1;
    *item = items[index];
    return 0;
}

<强> C#

[DllImport("dllName.dll" CallingConvention = CallingConvention.Cdecl)]
private static extern int GetListCount();

[DllImport("dllName.dll" CallingConvention = CallingConvention.Cdecl)]
private static extern int GetListItem(int index, out myStruct item);

....

int count = GetListCount();
myStruct[] items = new myStruct[count];
for (int index = 0; index < count; index++)
{
    int retval = GetListItem(out items[index]);
    if (retval != 0)
        // handle error
}

如果您无法更改DLL,那么您将面临手动执行编组操作。它会是这样的:

[DllImport("dllName.dll" CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 GetMyList(IntPtr listPtr);

....

IntPtr listPtr = Marshal.AllocHGlobal(205004); // Argh! Magic constant alert
try
{
    int retval = GetMyList(listPtr);
    // presumably you are expected to do something with retval
    int count = Marshal.ReadInt32(listPtr);
    myStruct[] items = new myStruct[count];
    for (int index = 0; index < count; index++)
    {
        IntPtr itemPtr = listPtr + 4 + index*2050; // More magic constants!
        items[index] = (myStruct)Marshal.PtrToStructure(itemPtr, typeof(myStruct));
    } 
}
finally
{
    Marshal.FreeHGlobal(listPtr);
}

您可能更喜欢使用Marshal.SizeOf而不是魔术常量。