Выделение структуры C ++ с объединением в C # - PullRequest
1 голос
/ 06 ноября 2019

Я пытаюсь реализовать оболочку C # вокруг SDK камеры Nikon DS-QI2 (доступна только 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 байт.

Какое колдовство мне нужно, чтобы структуры соответствовали памяти и размеру,чтобы я мог привести их к моему массиву struct? Спасибо!

РЕДАКТИРОВАТЬ: Дополнительный связанный вопрос. Почему размер моей полной структуры C ++ составляет 520 байт, а размер следующего составляет 516 байт. Разве они не должны быть равными, так как массив определяет член с большим размером в объединении? А поскольку CAM_FEA_VARIANT_MAX = 512, то приведенное ниже выглядит мне корректно, а другое - нет.

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

РЕДАКТИРОВАТЬ 2: похоже, что это двойное добавление еще 4 случайных байтов, я не понимаю, почему...

...