如何在 C# 中获取 IntPtr 指针的属性

本文关键字:IntPtr 指针 属性 获取 | 更新日期: 2023-09-27 18:35:59

我在C#项目中使用了一些C++包装器。问题是我有一个指针hd(类型IntPtr)指向C++类型Head,它具有一个名为xlong的属性。我怎样才能得到那个属性?我知道两种方法:

var l = ((Head)Marshal.PtrToStructure(hd, typeof(Head))).xlong;

var l = ((Head*)hd.ToPointer())->xlong;

但是有没有办法直接使用元帅获得它?我没有找到任何关于它的信息。如果没有,我应该使用哪种方式?

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;
}

如何在 C# 中获取 IntPtr 指针的属性

通常,这两种方法可能会给出不同的结果,但事实并非如此:您的 Head 结构是可 blitable 的,这意味着它对非托管代码和托管代码的表示形式完全相同。

因此,您可以使用最适合您的方法。您的第一种方法:

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字段中,因为它永远不会更改,并且无需为每次访问再次计算它。