我正在尝试在非托管 dll 中存储和检索一些数据。我试图通过尽可能简化结构来缩小我的问题范围,这就是我要解决的问题:
结构定义
[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 导入:
[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();
函数调用:
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));
我猜很简单。我知道字符集和打包是可以的,因为我只是将另一个结构定义中的结构布局属性粘贴到与我实际上对大多数代码所做的相同的 dll 中。
当读取 ms_out 的内容时,它充满了垃圾(随机大数)。
我终于通过反复试验找到了我的问题的答案,但我不太明白。这是工作版本:
[DllImport(MY_DLL, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
[return:MarshalAs(UnmanagedType.I1)]
public static extern bool SetData( [In, MarshalAs(UnmanagedType.LPStruct)] MyStruct ms);
用 [In, MarshalAs(UnmanagedType.LPStruct)] 替换 ref 成功了,但为什么呢?
感谢您的回答,祝您编码愉快。