从 C# 到通过 PInvoke C++的简单结构中的垃圾数据

Garbage data in simple struct from C# to C++ via PInvoke

本文关键字:结构 简单 数据 C++ PInvoke      更新时间:2023-10-16

>我有一个简单的Size结构,定义为

#pragma pack(push, 8)
struct Size final
{
public:
  std::int32_t Width = 0;
  std::int32_t Height = 0;
};
#pragma pack(pop)

在C++和作为

[StructLayout(LayoutKind.Sequential, Pack = 8)]
public class Size
{
    public System.Int32 Width { get; set; }
    public System.Int32 Height { get; set; }
}

在 C# 中。

现在,我正在尝试创建一个 C# Size 对象并将其发送到C++代码,为此我在C++

extern "C" {
__declspec(dllexport) auto Test(Common::Size size) -> void;
}
auto Test(const Common::Size size) -> void
{
    // Do something
}

以及一个 PInvoke C# 函数,以将其调用为:

[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Test")]
public static extern void Test(Common.Size size);

为了总结它,我确实使用以下代码调用 Test 函数:

var outputSize = new Common.Size() { Width = 100, Height = 200 };
PluginApi.Test(outputSize);

现在,我期望的是 C++ 函数中的参数大小分别具有宽度和高度的值 100 和 200,但我得到的是垃圾数,更准确地说,132313736宽度和 0 高度。

在这种情况下,我做错了什么?

与 C# 中的public class Size有关,它可能会为每个包含类型信息的对象引入一个"标头"(如果需要,可以称为"vtable 指针")。因此,c# 中对象的内存布局和 C++ 中结构的实例可能不匹配。

在 C# 中使用结构而不是类应该可以解决问题。