结构VS班编组阵列 [英] Marshalling array of structs vs classes

查看:321
本文介绍了结构VS班编组阵列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想读的本机结构为利用编组C#类型。我的方法元帅结构是像这样:

I want to read a native struct into a C# type using Marshalling. My method to Marshal structs is like so:

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

注意这工作正常,如果附属数据是一个结构!但是,如果附属数据是一个类,它会导致Marshal.PtrToStructure抛出一个FatalExecutionEngineError。我想带班坚持,因为有时我的类型有默认值和结构不能有字段初始化,也没有默认的构造函数,而且其中的某些类型是相当大的。

Note that this works fine if SubData is a struct! But if SubData is a class, it causes Marshal.PtrToStructure to throw a 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.

感谢您的帮助。

编辑:。该错误信息是运行时遇到了致命的错误错误的地址在0x6af99aec,上线0x348错误code是0000005此错误可能是CLR中的错误或在用户code中的不安全或未经核实的部分。这种错误的常见来源包括COM的互操作或用户的PInvoke封送处理错误,这可能会损坏堆栈。

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."

推荐答案

一个类是引用类型,因此利用Marshal.PtrToStructure时,它会复制一个指针,并在子数据的位置没有值。
在声明子数据的结构,则子数据的实际值会做编组时被复制。
因此,你必须使用一个结构。你可能还有一类为好,这将采取结构版本在构造函数中。
例如你可以通过使用证明了这一点。

A class is a reference type, thus when using Marshal.PtrToStructure it will copy a pointer and no values at the position of Subdata.
When declaring Subdata as struct, then the actual values of subdata will be copied.
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.
You can for instance prove this by using

sizeof的

要看到的大小会有所不同。

to see that the sizes will differ.

这篇关于结构VS班编组阵列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆