如何在 C# 中获取 IntPtr 指针的属性
How to get a property of an IntPtr pointer in C#
我在我的 C# 项目中使用了一些 C++ 包装器。问题是我有一个指向 C++ 类型 Head
的指针 hd
(类型 IntPtr
),它有一个名为 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;
}
一般来说,您的两种方法可能会产生不同的结果,但它不在这里:您的 Head
结构是 blittable,这意味着它对非托管代码和托管代码的表示是一模一样
因此,您可以使用最适合您的方法。你的第一个方法:
var l = ((Head)Marshal.PtrToStructure(hd, typeof(Head))).xlong;
优点是不需要您自己编写任何不安全的代码,而是由系统库来处理。
你的第二种方法:
var l = ((Head*)hd.ToPointer())->xlong;
的优点是在提取 xlong
字段之前不会制作不必要的数据副本。
直接通过 Marshal
class 读取字段是可能的,正如 Hans Passant 指出的那样,通过使用 Marshal.ReadIntPtr
. This is not directly suitable: it requires you to first calculate the offset. However, the Marshal
class already contains a method that does that for you: Marshal.OffsetOf
.
如果采用这种方法,您可能希望将 Marshal.OffsetOf
的结果缓存在 static readonly
字段中,因为它永远不会改变,并且无需为每个都重新计算访问。
我在我的 C# 项目中使用了一些 C++ 包装器。问题是我有一个指向 C++ 类型 Head
的指针 hd
(类型 IntPtr
),它有一个名为 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;
}
一般来说,您的两种方法可能会产生不同的结果,但它不在这里:您的 Head
结构是 blittable,这意味着它对非托管代码和托管代码的表示是一模一样
因此,您可以使用最适合您的方法。你的第一个方法:
var l = ((Head)Marshal.PtrToStructure(hd, typeof(Head))).xlong;
优点是不需要您自己编写任何不安全的代码,而是由系统库来处理。
你的第二种方法:
var l = ((Head*)hd.ToPointer())->xlong;
的优点是在提取 xlong
字段之前不会制作不必要的数据副本。
直接通过 Marshal
class 读取字段是可能的,正如 Hans Passant 指出的那样,通过使用 Marshal.ReadIntPtr
. This is not directly suitable: it requires you to first calculate the offset. However, the Marshal
class already contains a method that does that for you: Marshal.OffsetOf
.
如果采用这种方法,您可能希望将 Marshal.OffsetOf
的结果缓存在 static readonly
字段中,因为它永远不会改变,并且无需为每个都重新计算访问。