我在C#项目中使用了一些C ++包装器。问题是我有一个指针hd
(类型为IntPtr
)到C ++类型Head
,它有一个名为xlong
的属性。我怎么能得到那个属性?我知道两种方式:
var l = ((Head)Marshal.PtrToStructure(hd, typeof(Head))).xlong;
和
var l = ((Head*)hd.ToPointer())->xlong;
但有没有办法直接使用Marshal?我没有发现任何相关信息。如果没有,我应该使用哪种方式?
Head
定义为
[StructLayout(LayoutKind.Sequential)]
public struct Head
{
public int w;
public int h;
public double wmod;
public double hmod;
public IntPtr xlong;
public IntPtr ylong;
public int pitch;
public uint flags;
}
答案 0 :(得分:1)
一般情况下,您的两种方法可能会产生不同的结果,但不是这样:您的Head
结构是blittable,意味着它代表非托管代码和托管代码完全相同。
因此,您可以使用最适合您的方法。你的第一种方法:
var l = ((Head)Marshal.PtrToStructure(hd, typeof(Head))).xlong;
的优点是不要求您自己编写任何不安全的代码,但让系统库负责处理。
你的第二种方法:
var l = ((Head*)hd.ToPointer())->xlong;
的优点是在提取xlong
字段之前不会创建不必要的数据副本。
正如Hans Passant所指出的,使用Marshal.ReadIntPtr
可以直接通过Marshal
课程阅读该字段。这不是直接合适的:它要求您首先计算偏移量。但是,Marshal
类已经包含了为您执行此操作的方法:Marshal.OffsetOf
。
如果采用这种方法,您可能希望将Marshal.OffsetOf
的结果缓存在static readonly
字段中,因为它永远不会更改,并且无需为每次访问再次计算它。