【问题标题】:How to marshal a double pointer?如何编组一个双指针?
【发布时间】:2013-09-03 12:17:44
【问题描述】:

我正在尝试使用 pinvoke 将 C 结构编组为 C#。虽然我能够编组一个 intptr,但我找不到编组双指针的语法。在 C 端使用 int 指针和 double 指针来分配整数或双精度数组。

这是 C 结构体:

struct xyz
{
      int *np;  // an int pointer works fine
      double *foo;
};

这里是 c# 类:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class xyz
{
    Intptr np;  // works fine
            // double *foo   ?? 
   }

我找不到任何关于如何标记的说明

【问题讨论】:

  • IntPtr 只是一个指针:直到 void*;所以你可以尝试将“double* foo”编组为“IntPtr foo”;
  • IntPtr 并不意味着“指向整数的指针”。 MSDN:IntPtr 类型被设计为一个整数,其大小是特定于平台的。它可以指向任何数据。
  • 澄清:C 代码正在执行所有分配/释放内存的工作,因此 C# 端完全没有意识到这一切。

标签: c# c pointers pinvoke marshalling


【解决方案1】:

查看this description for what an IntPtr is。您是否尝试过使用:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class xyz
{
    IntPtr np;
    IntPtr foo;
}

【讨论】:

    【解决方案2】:

    您似乎认为IntPtr 是指向int 的指针。事实并非如此。 IntPtr 是一个与指针宽度相同的整数。所以IntPtr 在 x86 上是 32 位宽,在 x64 上是 64 位宽。 documentation 说明了这一切。

    IntPtr 最接近的等效原生类型是void*,一个无类型指针。

    所以你的 C# 类应该是:

    [StructLayout(LayoutKind.Sequential)]
    public class xyz
    {
        IntPtr np;
        IntPtr foo;
    }
    

    要读取np 引用的标量值,请调用Marshal.ReadInt32。并写它调用Marshal.WriteInt32。但更有可能的是,因为这是一个指针,所以指针指向一个数组。在这种情况下,您使用适当的Marshal.Copy 重载进行读写。

    对于指向 double 的指针,如果值是标量,则 Marshal 中没有读取或写入值的方法。但同样,它肯定是一个数组,在这种情况下使用Marshal.Copy 来访问内容。

    【讨论】:

    • 您将 IntPtr 与指针数组混淆了。我发现这样做的方法是:[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public IntPtr[] np;。您可能会发现此链接很有帮助:stackoverflow.com/questions/18647501/…
    • 我一点也不困惑。您的 ByValArray 与此问题中的任何内容都不匹配。
    • 让我们再读一遍我的答案。我说过“IntPtr 是一个与指针宽度相同的整数”。并且“与 IntPtr 最接近的等效本机类型是 void*,一个无类型指针。”由此可见,我对 IntPtr 的理解是扎实的。
    猜你喜欢
    • 1970-01-01
    • 2019-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多