无法封送包含union的结构

slk*_*ndy 5 c# c++ struct marshalling unions

我有一个C++结构,如下所示:

struct unmanagedstruct
{
    int             flags;
    union
    {
        int             offset[6];
        struct
        {
            float           pos[3];
            float           q[4];
        } posedesc;
    } u;
};
Run Code Online (Sandbox Code Playgroud)

而我正试图在C#中将其编组为:

[StructLayout(LayoutKind.Explicit)]
public class managedstruct {
    [FieldOffset(0)]
    public int flags;

    [FieldOffset(4), MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6)]
    public int[] offset;

    [StructLayout(LayoutKind.Explicit)]
    public struct posedesc {
        [FieldOffset(0), MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3)]
        public float[] pos;

        [FieldOffset(12), MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
        public float[] q;
    }

    [FieldOffset(4)]
    public posedesc pose;
}
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试将数据加载到我的结构中时,只有偏移数组的前3个元素存在(数组的长度为3).我可以确认它们的值是正确的 - 但我仍然需要其他3个元素.我做错了什么吗?

我正在使用这些函数来加载结构:

private static IntPtr addOffset(IntPtr baseAddress, int byteOffset) {
    switch (IntPtr.Size) {
        case 4:
            return new IntPtr(baseAddress.ToInt32() + byteOffset);
        case 8:
            return new IntPtr(baseAddress.ToInt64() + byteOffset);
        default:
            throw new NotImplementedException();
    }
}

public static T loadStructData<T>(byte[] data, int byteOffset) {
    GCHandle pinnedData = GCHandle.Alloc(data, GCHandleType.Pinned);
    T output = (T)Marshal.PtrToStructure(addOffset(pinnedData.AddrOfPinnedObject(), byteOffset), typeof(T));
    pinnedData.Free();
    return output;
}
Run Code Online (Sandbox Code Playgroud)

加载示例:

managedstruct mystruct = loadStructData<managedstruct>(buffer, 9000);
Run Code Online (Sandbox Code Playgroud)

如果您需要更多信息,请与我们联系.

jus*_*ase 1

我对此不是 100% 确定,但我相信联盟意味着两个成员使用相同的内存。对于 C++ 结构,为 int[] 或 posedesc 结构。所以结构体的大小将是 sizeof(int) + sizeof(posedisc)。意思是,Union 并不意味着您将同时拥有 int[] 和 posedisc,您将拥有共享内存,这些内存可以是 C++ 领域中的任何一种类型,但在托管领域中只能是其中一种类型。

所以我认为你可能需要两种托管结构,一种具有偏移量,一种具有posedisc。您可以在调用 LoadStruct 时选择其中之一。您可以选择创建一个 byte[] 字段并具有将这些字节转换为所需类型的计算属性。