【问题标题】:How use pinvoke for C struct array pointer to C#如何将 pinvoke 用于指向 C# 的 C 结构数组指针
【发布时间】:2012-08-15 12:06:21
【问题描述】:

我正在尝试使用 pinvoke 来编组从 C 到 C# 的另一个结构内的结构数组。 AFAIK,没办法。
因此,相反,在 C 结构中,我向我的数组和 malloc 声明了一个 ptr。问题:1)如何在 C# 端声明等价物? 2) 如何在 C# 端分配和使用等价物?

//The C code
typedef struct {
       int a;
       int b; } A;
typedef struct {
      int c;
      // A myStruct[100];    // can't do this, so:
      A *myStruct; } B;

//The c# code:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class A{
    int a;
    int b;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class B{
      int c;
      // can't declare array of [100] A structures...
     ?
 }

[编辑]:不知何故,我误解了我在其他地方读到的关于 c# 端的固定对象数组的内容。 而且我可以在C中修复数组大小所以编译好,但是在使用时我得到“对象引用未设置为对象的实例”:

data.B[3].a = 4567; 因此,在其他地方阅读有关此错误可能是什么的信息,我添加了此方法:

public void initA()
        {
          for (int i = 0; i < 100; i++) { B[i] = new A(); }
        }

再次,编译正常,但同样的错误消息。

【问题讨论】:

  • 你试过A[] myStruct吗?
  • 编译正常。但是我如何分配存储和使用它(我还在学习c#)。谢谢。
  • 只是好奇:为什么你不能在 C 语言中使用 A myStruct[100]; 吗?这将使 C# 方面的事情变得更容易......

标签: c# c arrays struct pinvoke


【解决方案1】:

要在 C 和 C# 之间编组这样的“复杂”结构,您有几个选择。

在这种情况下,我强烈建议您尝试将固定数组嵌入到 C 端结构中,因为它会大大简化 C# 端。您可以使用 MarshalAs 属性告诉 C# 在运行时它需要在数组中分配多少空间:

// In C:
typedef struct
{
 int a;
 int b;
} A;

typedef struct
{
 int c;
 A data[100];
} B;

// In C#:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct A 
{
  int a;
  int b;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct B
{
  int c;
  [MarshalAs(UnmanagedType.LPArray, SizeConst=100)]
  A[] data = new data[100];
}

如果您不知道或无法指定数组的固定大小,那么您需要执行您所做的操作并将其声明为 C 中的指针。在这种情况下,您无法告诉 C#数组在运行时将使用多少内存,因此您几乎无法手动完成所有编组。 This question 对它的工作原理有一个很好的概括,但基本思想是:

  1. 您应该在结构中添加一个包含数组元素计数的字段(这将使您的生活更轻松)
  2. 在 C# 中将字段声明为:IntPtr data;,不带任何属性。
  3. 使用Marshal.SizeOf(typeof(A)) 获取结构在非托管内存中的大小。
  4. 使用 Marshal.PtrToStructure 将单个非托管结构转换为 C#
  5. 使用IntPtr.Add(ptr, sizeofA) 移动到数组中的下一个结构
  6. 循环直到用完为止。

【讨论】:

  • 对象引用未设置为对象的实例
  • 在 C# 大小上,您仍然需要为字段分配一个数组,因为数组是引用类型。您应该可以内联执行此操作,我已经编辑了答案。
猜你喜欢
  • 2013-04-18
  • 1970-01-01
  • 1970-01-01
  • 2015-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-03
相关资源
最近更新 更多