如何在c#中使用带有union的struct

时间:2011-11-04 09:08:47

标签: c# c++ pinvoke marshalling

您好我在c#中写了一个包装器,我有一些问题。我在c ++中有这个结构。

typedef struct pjmedia_format
{
    pj_uint32_t id;
    pjmedia_type type;
    pjmedia_format_detail_type detail_type;
    union
    {
    pjmedia_audio_format_detail aud;
    pjmedia_video_format_detail vid;
    char user[PJMEDIA_FORMAT_DETAIL_USER_SIZE];
    } det;
} pjmedia_format;

这是此结构pjmedia_format

的链接 在c#中我有这个:

[StructLayout(LayoutKind.Sequential)]
public struct pjmedia_format
{
    public uint id;
    public pjmedia_type type;
    public pjmedia_format_detail_type detail_type;
    public det_t det;
}

[StructLayout(LayoutKind.Explicit)]
public struct det_t
{
    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.Struct)]
    public pjmedia_audio_format_detail aud;
    [FieldOffset(36)]
    [MarshalAs(UnmanagedType.Struct)]
    public pjmedia_video_format_detail vid;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
    [FieldOffset(60)]
    public char[] user;
}

[StructLayout(LayoutKind.Sequential)]
public struct pjmedia_audio_format_detail
{
    public uint clock_rate;
    public uint channel_count;
    public uint frame_time_usec;
    public uint bits_per_sample;
    public int avg_bps;
    public int max_bps;
}

[StructLayout(LayoutKind.Sequential)]
public struct pjmedia_video_format_detail
{
    public pjmedia_rect_size size;
    public pjmedia_ratio fps;
    public int avg_bps;
    public int max_bps;
}

当我想使用这个结构时,我得到了这个错误

  

System.Runtime.InteropServices.MarshalDirectiveException未处理。   Message =“方法签名与PInvoke不兼容。”

我尝试使用一些属性,如大小或包,但它没有帮助(可能我用错了)。我单独测试了其他结构,例如pjmedia_video_format_detail它们运行良好。有什么建议吗?

祝你好运 安杰伊

2 个答案:

答案 0 :(得分:2)

由于这是一个联盟,不应该是:

[StructLayout(LayoutKind.Explicit)]
public struct det_t
{
    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.Struct)]
    public pjmedia_audio_format_detail aud;
    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.Struct)]
    public pjmedia_video_format_detail vid;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
    [FieldOffset(0)]
    public char[] user;
}

即。重叠? 此外,您可能需要user成为固定缓冲区而不是数组。

答案 1 :(得分:1)

在C ++代码中,detunion。这意味着所有字段的偏移量为零,它们被重叠。只需使用[FieldOffset(0)] det_t中的所有字段,即可更改您的C#声明。