【发布时间】:2012-11-05 12:43:58
【问题描述】:
我正在尝试在非托管 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);
将 ref 替换为 [In, MarshalAs(UnmanagedType.LPStruct)] 可以解决问题,但为什么?
感谢您的回答,祝您编码愉快。
【问题讨论】:
-
通过将名为“MyStruct”的类型声明为类来有点自作自受。类对象已经通过引用传递。您的原始声明传递了 MyStruct** 而不是 MyStruct*。
-
感谢您的回答。我编辑了帖子的原始代码,因为该类应该反映非托管结构...但我同意这是错误的命名。
-
@HansPassant 我正在尝试向类添加一个属性,例如:
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MY_STRING_SIZE)] public string SomeString;我将构造函数中的属性设置为某个字符串,但返回时该字符串充满了垃圾,其他道具也是如此.你知道原因吗?谢谢——
标签: c# struct marshalling ref