Marshalling an array of structures and classes

I want to read the native structure into a C # type using Marshalling. My method for Marshall structures looks like this:

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 it works fine, the problem occurs 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 great if SubData is a structure ! But if SubData is a class, it causes Marshal.PtrToStructure to raise FatalExecutionEngineError. I would like to stick with classes because sometimes my types have default values, and structures cannot have field initializers and default constructors, and also some of these types are quite large.

Thanks for the help.

Edit: error message: "The runtime encountered a fatal error. The error address was at 0x6af99aec, in the stream 0x348. Error code: 0xc0000005. This error may be an error in the CLR or in the unsafe or unverifiable portions of the user code. Main sources this error includes user marshaling errors for COM-interop or PInvoke, which can damage the stack. "

+4
source share
1 answer

The class is a reference type, so when using Marshal.PtrToStructure it will copy the pointer and there will be no values ​​at the Subdata position.
When subdata is declared as a structure, then the actual values ​​of the subjects will be copied.
Thus, when doing marshalling you should use a structure. You may also have a class that takes up the design structure in the constructor.
You can, for example, prove this using

Sizeof

to see what sizes will vary.

+1
source

Source: https://habr.com/ru/post/1403582/


All Articles