Reputation: 11
I think there might be a bug in the C# method
Marshal.PtrToStructure<T>(IntPtr ptr, T structure)
I wrongly assumed T structure
means you can pass in your structure you want to fill but when I do this as in the example below an exception is thrown:
[System.ArgumentException: The structure must not be a value class. Parameter name: structure]
To give you a simple example:
using System;
using System.Runtime.InteropServices;
public class Program
{
public static void Main()
{
MyStruct s = new MyStruct();
var buffer = new Byte[]{1,2,3};
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
Marshal.PtrToStructure<MyStruct>(handle.AddrOfPinnedObject(), s);
handle.Free();
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct MyStruct
{
public Byte a;
public Byte b;
public Byte c;
}
}
Am I reading the method decleration wrong? Or is there a bug?
Upvotes: 1
Views: 1340
Reputation: 171
Instead of converting your struct to a class (or record, I presume), there is a new overload in 4.5.1 and newer (and .NET core), which did work for me using a struct.
var msgReceived = new FixedLengthStruct();
unsafe
{
fixed(byte* buffer = memoryAccessor.Bytes)
{
msgReceived = Marshal.PtrToStructure<FixedLengthStruct>((IntPtr)buffer);
}
}
// Process msgReceived
My struct here used LayoutKind.Explicit.
Upvotes: 0
Reputation: 5530
The parameter name structure
is misleading here. The documentation calls out twice that it must be a class.
The type of structure. This must be a formatted class.
You cannot use this method overload with value types.
However, it also self-contradicts itself when it says
Structure layout is not sequential or explicit.
Looking at the actual source, you don't find a where T : class
constraint either which I guess given the docs should be present.
Upvotes: 1
Reputation: 1
[StructLayout(LayoutKind.Sequential, Pack = 1)]
class MyStruct
{
public Byte a;
public Byte b;
public Byte c;
}
Had this problem myself and found that changing the structure to a class (ref type) over comes the problem.
Upvotes: 0