对结构进行编组,同时保持“非托管”

时间:2010-01-30 20:06:12

标签: c# c pinvoke

我正在调用一个DLL,它返回一个结构指针的void **列表,它们都是相同的类型。 From what I've read,为了从我的结构中强制转换结构,结构需要被视为不受管理。我试图编组的结构的主要元凶是C方面的以下两个字段:

char name[1024];
int crop[4];

大多数指南建议在托管端的相应结构上使用string或int [],但是具有这些字段的那些使得它成为托管结构,因此无法从void **列表中提取。

我可以用另一种方式编组这些字段,这些字段为我提供了一个非托管结构吗?

3 个答案:

答案 0 :(得分:1)

您可以使用fixed关键字在数据结构中创建具有固定大小数组的缓冲区:

unsafe struct Foo
{
    public fixed byte name[1024];
    public fixed int crop[4];
}

static unsafe void DumpCrops(void** ptr, int count)
{
    Foo** p = (Foo**)ptr;

    for (int i = 0; i < count; i++)
    {
        Foo* f = p[i];

        for (int j = 0; j < 4; j++)
        {
            Console.WriteLine(f->crop[j]);
        }
    }
}

答案 1 :(得分:1)

如果您声明如下所示,结构将在没有帮助或需要unsafe关键字的情况下编组:

using System.Runtime.InteropServices;
...
  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
  public struct Example {
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
    public string name;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    int[] crop;
  }

使用Marshal.PtrToStructure()将void *转换为结构。

答案 2 :(得分:0)

你需要在结构上的那一点添加一行,如图所示......


[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct _FOOBAR {
    [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 1024, ArraySubType = System.Runtime.InteropServices.UnmanagedType.I2)]
char name[1024];
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = System.Runtime.InteropServices.UnmanagedType.I4)]
int crop[4];
};

您需要仔细检查属性位中的最后一位,UnmanagedType ...

希望有所帮助, 最好的祝福, 汤姆。