Marshal Union(C) 与包含 C# 中的数组的结构

Posted

技术标签:

【中文标题】Marshal Union(C) 与包含 C# 中的数组的结构【英文标题】:Marshal Union(C ) with a Struct which contains an Array in C# 【发布时间】:2012-06-29 21:13:52 【问题描述】:

我尝试在 c# 中编组一个非托管 c++ dll,但编组器在创建我的联合时失败。

为什么这段代码会失败?

    [StructLayout(LayoutKind.Sequential)]
    public struct StructWithArray
    
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
        public int[] MySimpleArray;
        //More Stuff
    

    [StructLayout(LayoutKind.Explicit)]
    public struct Union
    
        [FieldOffset(0)]
        public int Int; //Or anything else
        [FieldOffset(0), MarshalAs(UnmanagedType.Struct)]
        public StructWithArray MyStructWithArray;
        //More Structs
    

然后构建联合:

Union MyUnion = new Union();

如果我使用以下消息运行代码会失败:(已翻译)

“无法加载程序集 [...] 的类型“联合”,因为它在偏移量 0 处包含一个对象字段,该字段未正确对齐或被一个不是对象字段的字段重叠“:”联合"

有什么建议吗?

Ps:原始代码被大大简化,只显示问题。还有更多的 Struct,Union 也包含在另一个 Struct 中。

【问题讨论】:

可能是 Pack 问题。首先尝试将属性 Pack=4 添加到第一个结构。这些结构的头文件中是否有#pragma pack。 头文件中没有#pragma。在这段代码中,我什至没有加载 dll。这个例子足以得到错误。 Pack=1,Pack=4tested,Fixed Size Tested,将Array直接复制到union中tested,结果都一样。 看到这个***.com/questions/1190079/… 看来你的解决方案是用 [StructLayout(LayoutKind.Sequential)] public struct StructWithArray int a;int b; 替换第一个结构//更多内容 是的,我认为这是唯一的解决方法。或者对于原生结构,我可以使用“不安全”和“固定数组”,但正如我所说,这仅适用于 int、uint 等原生结构。 【参考方案1】:

MySimpleArray 声明为固定的不安全数组:

[StructLayout(LayoutKind.Sequential)]
public unsafe struct StructWithArray

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
    public fixed int MySimpleArray[2];
    //More Stuff


[StructLayout(LayoutKind.Explicit)]
public struct Union

    [FieldOffset(0)]
    public int Int; //Or anything else
    [FieldOffset(0), MarshalAs(UnmanagedType.Struct)]
    public StructWithArray MyStructWithArray;
    //More Structs

【讨论】:

遗憾的是,“fixed”关键字仅适用于整数、字节等值类型。假设我有一组其他结构,“fixed”关键字不再起作用。

以上是关于Marshal Union(C) 与包含 C# 中的数组的结构的主要内容,如果未能解决你的问题,请参考以下文章

c#/c++ 如何将结构的结构与 marshal.sizeof 联合

将包含结构的 c++ 函数传递给 C#,并使用 Marshal.PtrToStructure 将其转换为 c# 函数

C# Marshal / Pinvoke CBitmap?

C#引用c++DLL结构体数组注意事项(数据发送与接收时)

c# Marshal 以 null 结尾的字符串数组

Marshal 2 IntPtr 在同一个函数中?