c# - 如何将 pinvoke 用于指向 C# 的 C 结构数组指针

标签 c# c arrays struct pinvoke

我正在尝试使用 pinvoke 将结构数组编码到另一个结构中,从 C 到 C#。据我所知,没办法。
因此,相反,在 C 结构中,我声明了指向我的数组的 ptr 和 malloc。问题: 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(); }
        }

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

最佳答案

要在 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# - 如何将 pinvoke 用于指向 C# 的 C 结构数组指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11968960/

相关文章:

c# - 用于实体更改跟踪的 Asp.net 事件

c++ - C 而不是 C++ 中的对象工厂

C - 反向转换器过程

javascript - 如何将在 for 循环中选中的复选框中的数组值推送到另一个数组?

php - 通过 PDO 准备语句从表中返回值数组

arrays - 修改大型元胞数组以在 MATLAB 中查找满足条件的某些行

c# - 为什么我在尝试将公共(public)方法的默认值设置为颜色时收到错误消息?

c# - 如何从另一个类引用在 MainWindow 中创建的类实例

c# - 如何在 C# Windows 窗体中停止加载窗体

c - 闰年问题,无法获取输入或.exe崩溃