I am trying to store and retrieve some data into/from an unmanaged dll. I have tried to narrow down my problem by simplifying the struct as much as possible and here is what I am getting down to:
Structure definition
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public class MyStruct
{
private UInt32 size;
public UInt16 SomeData;
public MyStruct()
{
size = (UInt32)Marshal.SizeOf(this);
this.SomeData = 66; //just put any non 0 value for test
}
}
DLL imports:
[DllImport(MY_DLL, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
[return:MarshalAs(UnmanagedType.U1)]
public static extern bool SetData(ref MyStruct ms);
[DllImport(MY_DLL, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr GetData();
Function calls:
MyStruct ms_in = new MyStruct();
bool b = Wrapper.SetData(ref ms_in);
IntPtr ptr = Wrapper.GetData();
MyStruct ms_out = (MyStruct)Marshal.PtrToStructure(ptr, typeof(MyStruct));
Simple enough I guess. I know that charset and packing are ok as I simply pasted the struct layout attributes from another struct definition for the same dll as I did for most of the code actually.
When reading the content of ms_out it is just full of garbage (random large numbers).
I finally found the answer to my question by trial and error but I can't understand it much. Here is the working version:
[DllImport(MY_DLL, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
[return:MarshalAs(UnmanagedType.I1)]
public static extern bool SetData( [In, MarshalAs(UnmanagedType.LPStruct)] MyStruct ms);
Replacing ref by [In, MarshalAs(UnmanagedType.LPStruct)] did the trick but why?
Thank you for your answers, happy coding.