C# 当结构包含整数数组时,如何避免在PInvoke封送期间复制?

C# 当结构包含整数数组时,如何避免在PInvoke封送期间复制?,c#,.net,pinvoke,marshalling,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代码编写为: 这是可行的,但我怀疑在PInvoke过程中,封送拆收器是在调用和返回过程中复制结构,而不是固定它

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

typedef unsigned char tUI8;

typedef struct
{
    tUI8 Mode;
    tUI8 Data[16];
} TestStruct;
以及一个函数,它获取指向此结构的指针并填充数据:

void FillTest(tUI8 Mode, TestStruct *s);
为了PInvoke调用此函数,我将C代码编写为:

这是可行的,但我怀疑在PInvoke过程中,封送拆收器是在调用和返回过程中复制结构,而不是固定它。我可以这么说,因为即使我不初始化结构,它也可以正常工作

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));
TestStruct;
//这里是s.Data==null!
本地测试。填充测试(10,参考s)// 我怀疑您需要一个,它将在结构中内联数据:

[StructLayout(LayoutKind.Sequential)]
unsafe struct TestStruct
{
    public byte Mode;
    public fixed byte Data[16];
}
现在,您应该能够通过引用将其直接传递给非托管代码。(您还需要明确允许不安全代码。)


我不知道在编组时需要使用哪些属性(如果有的话),但值得一试…

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

通过将编组为ByValArray

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

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

请注意,它是不安全的,请将结构标记为不安全的,并在项目属性中,选中允许不安全代码。是的。我试过了,效果很好,但我不得不多次声明我是一个坏人(标记为不安全)。我也不确定marshaller是否会在调用过程中自动锁定结构,或者我必须显式执行该操作。@Hemant如果要避免复制,则必须使用不安全的。如果要避免不安全,则必须让封送拆收器进行复制。复制数据有什么不好?不需要固定,结构体位于堆栈上,不可移动。把C代码弄错会使堆栈崩溃。这是臭名昭著的缓冲区溢出攻击向量。因此,不安全的关键字。每秒数百个数据包。这听起来不是很苛刻。在决定瓶颈所在之前,最好先分析一下。
[StructLayout(LayoutKind.Sequential)]
struct TestStruct
{
    public byte Mode;

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