首页 > 解决方案 > 将带有联合的 C++ 结构编组到 C#

问题描述

我正在尝试围绕 Nikon DS-QI2 Camera SDK 实现一个 C# 包装器(只有 C++ dll 可用)。

我正在努力编组结构数据,因为大小不匹配。dll 正在使用指向结构数组的指针,因此让结构匹配以从我传递给 dll 方法的指针中检索数据非常重要。

在面对结构中的联合之前,一切都很好。举个例子:

如果我在 C++ 中定义以下结构

struct CAM_Variant
{
    ECamVariantRunType  eVarType;
    lx_int32                i32Value;
    lx_uint32               ui32Value;
    lx_int64                i64Value;
    lx_uint64               ui64Value;
    double                  dValue;
    bool                    bValue;
    void*                   pValue;
    lx_wchar                wszValue[CAM_FEA_VARIANT_MAX];
    CAM_Area                stArea;
    CAM_Position            stPosition;
    CAM_TriggerOption       stTriggerOption;
    CAM_MultiExposureTime   stMultiExposureTime;
    CAM_Format              stFormat;
}

C# 中的对应词是

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CAM_Variant
{
    public ECamVariantRunType eVarType;
    public Int32 i32Value;
    public UInt32 ui32Value;
    public Int64 i64Value;
    public UInt64 ui64Value;
    public double dValue;
    public byte bValue;
    public IntPtr pValue;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string wszValue;
    public CAM_Area stArea;
    public CAM_Position stPosition;
    public CAM_TriggerOption stTriggerOption;
    public CAM_MultiExposureTime stMultiExposureTime;
    public CAM_Format stFormat;
}

两者的大小均为 664 字节。

问题是实际的 C++ 结构实现了一个联合

struct CAM_Variant
{
    ECamVariantRunType  eVarType;
    union
    {
        lx_int32                i32Value;
        lx_uint32               ui32Value;
        lx_int64                i64Value;
        lx_uint64               ui64Value;
        double                  dValue;
        bool                    bValue;
        void*                   pValue;
        lx_wchar                wszValue[CAM_FEA_VARIANT_MAX];
        CAM_Area                stArea;
        CAM_Position            stPosition;
        CAM_TriggerOption       stTriggerOption;
        CAM_MultiExposureTime   stMultiExposureTime;
        CAM_Format              stFormat;
    };
}

并且 sizeof(CAM_Variant) 现在返回 520 字节。而如果我将 Pack = 1 添加到 StructLayout 属性,C# 结构只会缩小到 657 字节的大小。

我需要什么样的魔法才能使结构在内存和大小上匹配,以便我可以将它们转换为我的结构数组?谢谢!

编辑:额外相关的问题。为什么我的完整 C++ 结构的大小是 520 字节,而下面的大小是 516 字节。由于数组将更大尺寸的成员定义到联合中,它们不应该相等吗?由于 CAM_FEA_VARIANT_MAX = 512,下面的一个对我来说是正确的,而另一个不是。

struct CAM_Variant_BIS
{
    ECamVariantRunType  eVarType;
    union
    {
        lx_wchar    wszValue[CAM_FEA_VARIANT_MAX];
    };
};

编辑2:看起来它是双加4个随机字节,我不明白为什么......

标签: c#c++structmarshalling

解决方案


推荐阅读