使用并集从C#调用C++DLL

Calling a C++ DLL from C# with unions

本文关键字:调用 C++DLL      更新时间:2023-10-16

我正在接收来自C++DLL的回调,需要接受如下结构:

typedef struct {
  union {
    SXAnyDevice any_device;
    SXInternalDevice internal;
    SXExternalDevice external;
  }
  int device_type;
} SXDevice;

我已经创建了C#中引用的结构,并设置了显式布局,但我在设置device_type字段的FieldOffset时遇到了问题,因为并集中引用的结构化并不都是相同的大小。

[StructLayout(LayoutKind.Explicit, CharSet=CharSet.Ansi)]
public struct SXDevice {
    [FieldOffset(0)]
    public SXAnyDevice any_device;
    [FieldOffset(0)]
    public SXInternalDevice internal_device;
    [FieldOffset(0)]
    public SXExternalDevice external_device;
    [FieldOffset(**Not sure how to handle this**)]
    public int device_type;
} 

有什么最好的方法吗?

如何快速获取偏移量:使用C++中offsetof(SXDevice, device_type)返回的值。

偏移说明:

一个并集占用的空间与其最大的组成部分一样多。

maxSize=max(sizeof(SXAnyDevice), sizeof(SXInternalDevice), sizeof(SXExternalDevice))

现在一切都取决于它在C++端的配置方式:

  • 如果没有填充(#pragma pack(1)),则device_type的偏移量将简单地等于maxSize
  • 如果有填充,请将maxSize与下一个包边界对齐

来自#pragma pack文档:

指定要用于打包的值(以字节为单位)。如果没有为模块设置编译器选项/Zp,则n的默认值为8。有效值为1、2、4、8和16。构件的对齐将位于n的倍数或构件大小的倍数(以较小者为准)的边界上。