将结构数组从 C# 封送到 VC++

Marshalling array of struct from C# to VC++

本文关键字:VC++ 结构 数组      更新时间:2023-10-16

我正在尝试将结构数组从 C# 封送到 VC++。

C++函数如下所示:

void myFunc(tFileListEntry* fileList);

tFileListEntry定义为:

typedef struct FILE_LIST
{
    uint16_t FileGroupCounter;
    uint32_t FileID;
    uint16_t NumbSamples;
} tFileListEntry;

在 C# 中,我像这样声明了函数:

[DllImport("MyLib", EntryPoint = "myFunc", CallingConvention = CallingConvention.Cdecl)]
public static extern void myFunc( [In, MarshalAs(UnmanagedType.LPArray)] tFileListEntry[] fileList);

tFileListEntry定义为:

[StructLayout(LayoutKind.Sequential)]
public class tFileListEntry
{
    public tFileListEntry(UInt16 fileGroupCounter, UInt32 fileId, UInt16 numbSamples)
    {
        FileGroupCounter = fileGroupCounter;
        FileID = fileId;
        NumbSamples = numbSamples;
    }
    public UInt16 FileGroupCounter;
    public UInt32 FileID;
    public UInt16 NumbSamples;
}

我可以在 C# 代码以及C++库中设置断点。在托管端,值看起来是正确的,但在非托管端,我只得到垃圾。

我用Marshal.SizeOf()(在 C# 中)和sizeof()(在 C++ 中)验证了结构的大小两侧都是 12 个字节,所以我认为填充/打包在这里不是问题。

我做错了什么?

我认为

这里的问题是在 C# 方面,您将其声明为类,而不是结构。

这意味着,当您在 C# 端创建数组时,数组的每个元素都是一个引用(4 或 8 个字节,具体取决于架构),而不是结构(12 个字节),以及你所看到的结果。

尝试将 C# 类更改为结构。

看起来问题是我在 C# 端将tFileListEntry定义为class。当我将其更改为struct时,一切正常。

有趣的是,我在同一库中还有另一个接受单个struct(不是数组)的C++函数,我可以成功地封送 C# class(使用 MarshalAs(UnmanagedType.LPStruct))。