我正在尝试从byte []编组结构。除了编组一个字符串外,每个部分都有效。它看起来像一个BSTR:
06 00 00 00 48 00 65 00 6c 00 6c 00 6f 00 21 00 00 00
那么,这是一个4字节的长度,然后是“你好!”在unicode中使用双null终止符。这是我玩过的编组码:
string auto = Marshal.PtrToStringAuto(nextSchedulePtr); // returns "Hello!"
string ansi = Marshal.PtrToStringAnsi(nextSchedulePtr); // returns "H"
string uni = Marshal.PtrToStringUni(nextSchedulePtr); // returns "Hello!"
string bstr = Marshal.PtrToStringBSTR(nextSchedulePtr); // returns "Hel"
Schedule schedule = (Schedule)Marshal.PtrToStructure(nextSchedulePtr, typeof(Schedule)); // returns "" with UnmanagedType.BStr and UnmanagedType.LPWStr
方法1无论如何都要调用方法3,所以这是有道理的。但是,我无法在[MarshalAs(UnmanagedType.X)]属性中指定任何类型,以允许结构返回任何有意义的内容。
我已经将结构削减到了这个:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Schedule
{
[MarshalAs(UnmanagedType.BStr)]
public string Name;
}
我已经尝试了UnmanagedType.X的所有有效值,他们要么抛出AccessViolationExceptions,要么返回空字符串或返回垃圾。无返回“你好!”。我无法将此数据加载到结构中吗?
注意:我无法更改数据,它是一成不变的。但是,我可以更改我的代码。我还固定了字节[],因此它不是GC。
答案 0 :(得分:2)
问题是你定义的Schedule
结构符合这种C结构:
struct Schedule {
BSTR *Name;
};
虽然您正在修改的IntPtr
内存中存在的结构具有布局:
struct Schedule {
BSTR Name;
};
如果在Marshal.StructureToPtr()
的实例上使用Schedule
然后检查内存,您将看到只有前四个字节被设置,因为它们是一个指针。
不幸的是,在.NET中没有优雅的解决方法。您不能在结构中使用非指针字符串,因为结构将具有可变长度。
如果是一个选项,请完全放弃结构并坚持使用Marshal.PtrToStringAuto()
。