2012-08-15 38 views
4

我想使用的PInvoke马歇尔结构数组另一个结构内从C到C#。 AFAIK,不行。
所以取而代之,在C结构,我宣布一个PTR我的数组,malloc的。问题:1)如何在C#端声明等价物? 2)如何分配和使用C#端的等价物?如何使用的PInvoke为C结构数组的指针,以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(); } 
     } 

再次,编译好了,但是同样的错误信息。

+0

你试过了A [] myStruct吗? – 2012-08-15 12:13:03

+0

编译好。但我该如何分配存储空间并使用它(我仍在学习c#)。谢谢。 – PaeneInsula 2012-08-15 12:20:14

+0

只是好奇:*为什么*你不能在C中使用'A myStruct [100];'?那会让C#的侧面容易得多... – 2012-08-15 13:21:13

回答

5

为了像这样在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. 环路英寸
+0

对象引用不设置为一个objec的实例 – PaeneInsula 2012-08-15 15:36:17

+0

见我的编辑以上我如何试图修复错误味精。 – PaeneInsula 2012-08-15 15:47:20

+0

在C#大小上,您仍然需要为该字段分配一个数组,因为数组是引用类型。你应该可以做到这一点,我已经编辑了我的答案。 – 2012-08-15 17:15:09