简体   繁体   English

无法编组“参数#”:内部限制:结构太复杂或太大

[英]Cannot marshal 'parameter #': Internal limitation: structure is too complex or too large

I have a dll developed in C++. 我有一个用C ++开发的dll。 I need to use it with C#. 我需要在C#中使用它。

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

"myStruct" has of size 2050. I am calling the dll method as “ myStruct”的大小为2050。我将dll方法称为

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

I get an error when I call the dll method. 调用dll方法时出现错误。 "Cannot marshal 'parameter #1': Internal limitation: structure is too complex or too large." “无法编组'参数#1':内部限制:结构太复杂或太大。”

Do any one have a solution by not changing the C++ dll parts? 是否有人通过不更改C ++ dll部分而有解决方案?

As the error says, the structure is too large to be marshalled that way. 正如错误所言,该结构太大,无法以这种方式进行编组。 So you will have to find another approach. 因此,您将不得不寻找另一种方法。

It would make more sense, in my view, to return the structs one at a time. 我认为,一次返回一个结构会更有意义。 That will avoid you needing to hard code an upper limit of there being no more than 100 structs in the list. 这样可以避免您需要硬编码列表中不超过100个结构的上限。

So I would write it like this: 所以我会这样写:

C++ 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# 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
}

If you cannot change the DLL then you are faced with performing the marshalling by hand. 如果您无法更改DLL,那么您将面临手工执行编组的问题。 It would go like this: 它会像这样:

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

You might prefer to use Marshal.SizeOf rather than the magic constants. 您可能更喜欢使用Marshal.SizeOf而不是魔术常数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM