当struct包含整数数组时,如何在PInvoke编组期间避免复制?

时间:2012-02-24 06:56:36

标签: c# .net pinvoke marshalling

我有一个“C”结构,定义为:

typedef unsigned char tUI8;

typedef struct
{
    tUI8 Mode;
    tUI8 Data[16];
} TestStruct;

一个函数,它接受一个指向这个结构的指针并填充数据:

void FillTest(tUI8 Mode, TestStruct *s);

为了PInvoke这个函数,我把C#代码编写为:

[StructLayout(LayoutKind.Sequential)]
struct TestStruct
{
    public byte Mode;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public byte[] Data;
}

static class NativeTest
{
    [DllImport("Native.dll")]
    public static extern void FillTest(byte mode, ref TestStruct s);
}

这有效但我怀疑在PInvoke marshaller期间在调用期间复制结构并返回而不是固定它。我可以这么说,因为即使我没有初始化结构,它也能正常工作。

TestStruct s;
//here s.Data == null!
NativeTest.FillTest(10, ref s); //<<< I expected an error here
//here s.Data points to a valid byte[] of length 16
Console.WriteLine(BitConverter.ToString(s.Data));

我的问题是如何使用struct或class定义PInvoke签名,以避免在编组期间复制数据?

2 个答案:

答案 0 :(得分:2)

我怀疑你想要一个fixed size buffer,它将内联你的结构中的数据:

[StructLayout(LayoutKind.Sequential)]
unsafe struct TestStruct
{
    public byte Mode;
    public fixed byte Data[16];
}

您现在应该可以通过引用将其直接传递给您的非托管代码。 (您还需要明确允许不安全的代码。)

我不知道你需要使用什么属性进行编组,如果有的话,但值得一试......

答案 1 :(得分:0)

这可以在不使用不安全代码的情况下完成。

通过编组作为ByValArray

[StructLayout(LayoutKind.Sequential)]
struct TestStruct
{
    public byte Mode;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public byte[] Data;
}