简体   繁体   English

编组结构与类的数组

[英]Marshalling array of structs vs classes

I want to read a native struct into a C# type using Marshalling. 我想使用编组将本机结构读入C#类型。 My method to Marshal structs is like so: 我对Marshal结构的方法是这样的:

T ReadObject<T>(BinaryReader br) {
    var bytes = br.ReadBytes(Marshal.SizeOf(typeof(T)));
    var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    try {
        return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
    }
    finally {
        handle.Free();
    }
}

Now this works fine in general, the problem arises with the following type: 现在这一般工作正常,问题出现在以下类型:

[StructLayout(LayoutKind.Sequential, Pack=1)]
class SubData {
    public short A1;
    public short A2;
}

[StructLayout(LayoutKind.Sequential, Pack=1)]
class Data {
    public short Id;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
    public SubData[] SubDatas;
}

Note that this works fine if SubData is a struct ! 请注意, 如果SubData是一个结构这可以正常工作 But if SubData is a class, it causes Marshal.PtrToStructure to throw a FatalExecutionEngineError. 但是如果SubData是一个类,它会导致Marshal.PtrToStructure抛出FatalExecutionEngineError。 I'd like to stick with classes because sometimes my types have default values and structs cannot have field initializers nor default constructors, and also some of these types are rather large. 我想坚持使用类,因为有时候我的类型有默认值,结构不能有字段初始化器和默认构造函数,而且其中一些类型相当大。

Thanks for the help. 谢谢您的帮助。

Edit: the error message is "The runtime has encountered a fatal error. The address of the error was at 0x6af99aec, on thread 0x348. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack." 编辑:错误消息是“运行时遇到致命错误。错误的地址是0x6af99aec,在线程0x348。错误代码是0xc0000005。此错误可能是CLR中的错误或不安全或非错误用户代码的可验证部分。此错误的常见来源包括COM-interop或PInvoke的用户封送错误,这可能会破坏堆栈。“

A class is a reference type, thus when using Marshal.PtrToStructure it will copy a pointer and no values at the position of Subdata. 类是引用类型,因此当使用Marshal.PtrToStructure时,它将复制指针,而Subdata的位置则没有值。
When declaring Subdata as struct, then the actual values of subdata will be copied. 将Subdata声明为struct时,将复制子数据的实际值。
Thus when doing the Marshalling, you must use a struct. 因此,在进行编组时,必须使用结构。 You might still have a class as well, which will take the struct version in a constructor. 您可能仍然有一个类,它将在构造函数中使用struct版本。
You can for instance prove this by using 你可以通过使用来证明这一点

sizeof 的sizeof

to see that the sizes will differ. 看到尺寸会有所不同。

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

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