【问题标题】:How to convert an IntPtr to array of structs如何将 IntPtr 转换为结构数组
【发布时间】:2021-12-30 14:20:18
【问题描述】:

我有一个 IntPtr,它是一个指向结构数组的指针,我正在尝试将它转换为数组。

我试过了

Marshal.Copy(srcIntPtr, destIntPtrArray, 0, destIntPtrArray.Length);

但是在进行复制之后,我无法将目标数组中的 IntPtr 转换为所需的结构,而我可以将 srcIntPtr 转换为结构,这当然只会给我第一个索引的数据. 看起来在复制之后,目标数组包含一堆损坏的 IntPtr

我也试过

    var size = Marshal.SizeOf(Marshal.ReadIntPtr(myIntPtr));

    for (int i = 0; i < length; i++)
    {
        IntPtr iP = new IntPtr(myIntPtr.ToInt64() + i * size);
    
        MyStruct ms =
            (MyStruct ) Marshal.PtrToStructure(iP, typeof(MyStruct ));
    }

这不会引发任何错误,但是我从源 IntPtr 中获取的结构数组的数据不准确。

这是我要转换的结构

struct MyStruct
{
    public Categories categories;  
    public Dimensions dimensions;
}



public struct Categories {
    public double d;
    public double c;
    public double b;
    public double a;
}



struct Dimensions {
    public double v;
    public double e;
}

我在结构顶部有[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)],但删除它不会破坏我的代码。

提前致谢

【问题讨论】:

  • 你能显示结构的声明吗?
  • 亲爱的@Sean 我刚刚编辑了我的问题。 c++ 库中结构的声明与 c# 中的相同。可以毫无问题地将 IntPtr 转换为单个结构
  • 澄清一下:您已尝试将 Marshall.Copy 复制到 IntPtr[] 数组,然后循环到 Marshal.Copy 该 IntPtr[] 中的每个项目并且结构已损坏/不完整?
  • @JacobShanley 不,我将IntPtr 复制到IntPtr[],然后循环通过IntPtr[] 并尝试Marshal.PtrToStructure 他们每个人。但它在循环开始时抛出一个异常,并说Object reference is not set to an object (unknown wrapper) 基本上是一个空异常。我应该更新问题吗?
  • Marshal.ReadIntPtr(myIntPtr) 读取数组大小不太可能是正确的。问题中没有任何提示告诉我们如何获取数组大小。 C 数组声明从来都不是问题,我们看不到任何读取相同数组的示例 C 代码。

标签: c# .net marshalling intptr unmanaged-memory


【解决方案1】:

这...

Marshal.ReadIntPtr(myIntPtr)

...返回IntPtr,顾名思义。当传递给Marshal.SizeOf()...

var size = Marshal.SizeOf(Marshal.ReadIntPtr(myIntPtr));

...它确实返回它指向的MyStruct 的大小,但返回当前进程的IntPtr 的大小(4 或8 个字节)。要获得MyStruct 的非托管大小,您需要像这样调用SizeOf()...

var size = Marshal.SizeOf<MyStruct>();

...或者这个...

var size = Marshal.SizeOf(typeof(MyStruct));

此外,IntPtr 的全部意义在于它与地址宽度无关,但您将其显式检索为 long...

IntPtr iP = new IntPtr(myIntPtr.ToInt64() + i * size);

我认为这不会对任何事情产生负面影响(如果您在 64 位进程中调用 ToInt32(),这可能会抛出 OverflowException),但最好让 @ 987654336@ 处理计算指向每个MyStruct 元素的指针,您可以这样做...

IntPtr iP = IntPtr.Add(myIntPtr, i * size);

...或者只是这个...

IntPtr iP = myIntPtr + i * size;

【讨论】:

  • 非常感谢亲爱的 lance。我非常感谢这个答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-07
  • 1970-01-01
  • 2015-09-29
  • 2012-03-19
  • 1970-01-01
  • 2013-07-22
相关资源
最近更新 更多