将具有union的C结构编组为C#代码时获取垃圾数据
我试图在托管应用程序中使用以下C结构将具有union的C结构编组为C#代码时获取垃圾数据,c#,c++,pinvoke,C#,C++,Pinvoke,我试图在托管应用程序中使用以下C结构 typedef struct libvlc_media_track_t { uint32_t i_codec; uint32_t i_original_fourcc; int i_id; libvlc_track_type_t i_type; int i_profile; int i_level; union { libvl
typedef struct libvlc_media_track_t
{
uint32_t i_codec;
uint32_t i_original_fourcc;
int i_id;
libvlc_track_type_t i_type;
int i_profile;
int i_level;
union {
libvlc_audio_track_t *audio;
libvlc_video_track_t *video;
libvlc_subtitle_track_t *subtitle;
};
unsigned int i_bitrate;
char *psz_language;
char *psz_description;
} libvlc_media_track_t;
typedef struct libvlc_audio_track_t
{
unsigned i_channels;
unsigned i_rate;
} libvlc_audio_track_t;
typedef struct libvlc_video_track_t
{
unsigned i_height;
unsigned i_width;
unsigned i_sar_num;
unsigned i_sar_den;
unsigned i_frame_rate_num;
unsigned i_frame_rate_den;
} libvlc_video_track_t;
typedef struct libvlc_subtitle_track_t
{
char *psz_encoding;
} libvlc_subtitle_track_t;
unsigned libvlc_media_tracks_get( libvlc_media_t *p_md, libvlc_media_track_t ***tracks );
NET版本如下所示:
[StructLayout(LayoutKind.Explicit)]
public struct libvlc_media_track_t
{
[FieldOffset(0)]
public uint i_codec;
[FieldOffset(4)]
public uint i_original_fourcc;
[FieldOffset(8)]
public int i_id;
[FieldOffset(12)]
public libvlc_track_type_t i_type;
[FieldOffset(16)]
public int i_profile;
[FieldOffset(20)]
public int i_level;
[FieldOffset(24)]
public libvlc_audio_track_t audio;
[FieldOffset(24)]
public libvlc_video_track_t video;
[FieldOffset(24)]
public libvlc_subtitle_track_t subtitle;
[FieldOffset(48)]
public uint i_bitrate;
[FieldOffset(52)]
public IntPtr psz_language;
[FieldOffset(56)]
public IntPtr psz_description;
}
[StructLayout(LayoutKind.Sequential)]
public struct libvlc_audio_track_t
{
public uint i_channels;
public uint i_rate;
}
[StructLayout(LayoutKind.Sequential)]
public struct libvlc_video_track_t
{
public uint i_height;
public uint i_width;
public uint i_sar_num;
public uint i_sar_den;
public uint i_frame_rate_num;
public uint i_frame_rate_den;
}
[StructLayout(LayoutKind.Sequential)]
public struct libvlc_subtitle_track_t
{
public IntPtr psz_encoding;
}
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern int libvlc_media_tracks_get(IntPtr media, libvlc_media_track_t*** ppTracks);
unsafe
{
libvlc_media_track_t** ppTracks;
int num = LibVlcMethods.libvlc_media_tracks_get(m_hMedia, &ppTracks);
if (num == 0 || ppTracks == null)
{
throw new Exception();
}
for (int i = 0; i < num; i++)
{
libvlc_media_track_t* pTrackInfo = ppTracks[i];
}
LibVlcMethods.libvlc_media_tracks_release(ppTracks, num);
}
你把工会翻译错了。我怀疑当你说: 我在大多数结构/联合字段中获取垃圾数据 你的意思是,数据在联合之前是好的,在联合之后是垃圾。让我们来看看工会。它是:
union {
libvlc_audio_track_t *audio;
libvlc_video_track_t *video;
libvlc_subtitle_track_t *subtitle;
};
联合体包含指针。但是您已经通过将结构放在联合体中进行了转换。你的C#翻译相当于:
union {
libvlc_audio_track_t audio;
libvlc_video_track_t video;
libvlc_subtitle_track_t subtitle;
};
因此,只需将union替换为IntPtr
即可
[StructLayout(LayoutKind.Sequential)]
public struct libvlc_media_track_t
{
public uint i_codec;
public uint i_original_fourcc;
public int i_id;
public libvlc_track_type_t i_type;
public int i_profile;
public int i_level;
public IntPtr media;
public uint i_bitrate;
public IntPtr psz_language;
public IntPtr psz_description;
}
顺便说一句,如果您愿意,可以很容易地避免使用
不安全的。尽管如此,如果没有任何不利因素,那么能够使用指针将使代码更易于编写。您错误地翻译了union。我怀疑当你说:
我在大多数结构/联合字段中获取垃圾数据
你的意思是,数据在联合之前是好的,在联合之后是垃圾。让我们来看看工会。它是:
union {
libvlc_audio_track_t *audio;
libvlc_video_track_t *video;
libvlc_subtitle_track_t *subtitle;
};
联合体包含指针。但是您已经通过将结构放在联合体中进行了转换。你的C#翻译相当于:
union {
libvlc_audio_track_t audio;
libvlc_video_track_t video;
libvlc_subtitle_track_t subtitle;
};
因此,只需将union替换为IntPtr
即可
[StructLayout(LayoutKind.Sequential)]
public struct libvlc_media_track_t
{
public uint i_codec;
public uint i_original_fourcc;
public int i_id;
public libvlc_track_type_t i_type;
public int i_profile;
public int i_level;
public IntPtr media;
public uint i_bitrate;
public IntPtr psz_language;
public IntPtr psz_description;
}
顺便说一句,如果您愿意,可以很容易地避免使用不安全的。尽管如此,如果没有缺点,那么能够使用指针将使代码更易于编写。以不同的方式处理联合。使用显式布局为其声明专用类型。然后将所有成员放置在偏移量0处。然后对所有结构使用sequential。我不知道这是否能解决问题,但这是正确的方法。谢谢大卫的回答。不幸的是,它没有帮助,并且给出了相同的结果。如果您更新了问题,使版本按照我描述的方式实现,这将有所帮助。对我们来说,检查没有偏移的版本会容易得多。就目前的情况而言,我不会尝试这样计算。但是如果你按照我说的方式修改代码,我会很高兴地检查翻译。+1的出色结构的问题,以及你对我的建议的积极回应。要是这里的每一个问题都写得这么好就好了。很容易看出到底出了什么问题,但我只是被所有FieldOffset设置的原始版本吓坏了!我想,如果我克服了这种恐惧,我就会发现错误,但我就是无法面对它!;-)是的,这解决了问题。谢谢。我在这个问题上花了将近两天的时间…以不同的方式处理工会。使用显式布局为其声明专用类型。然后将所有成员放置在偏移量0处。然后对所有结构使用sequential。我不知道这是否能解决问题,但这是正确的方法。谢谢大卫的回答。不幸的是,它没有帮助,并且给出了相同的结果。如果您更新了问题,使版本按照我描述的方式实现,这将有所帮助。对我们来说,检查没有偏移的版本会容易得多。就目前的情况而言,我不会尝试这样计算。但是如果你按照我说的方式修改代码,我会很高兴地检查翻译。+1的出色结构的问题,以及你对我的建议的积极回应。要是这里的每一个问题都写得这么好就好了。很容易看出到底出了什么问题,但我只是被所有FieldOffset设置的原始版本吓坏了!我想,如果我克服了这种恐惧,我就会发现错误,但我就是无法面对它!;-)是的,这解决了问题。谢谢。我在这个问题上花了将近两天的时间。。。