在将 C 结构与 C# 代码联合封送时获取垃圾数据
Getting garbage data when marshalling C structure with union to C# code
我正在尝试在托管应用程序中使用以下 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 {
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);
}
该代码没有任何例外地工作,但我在大多数结构/联合字段中都得到了垃圾数据。
请指教,提前致谢
编辑:我也尝试了以下内容,但它有相同的结果
[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 MediaVariant media;
public uint i_bitrate;
public IntPtr psz_language;
public IntPtr psz_description;
}
[StructLayout(LayoutKind.Explicit)]
public struct MediaVariant
{
[FieldOffset(0)]
public libvlc_audio_track_t audio;
[FieldOffset(0)]
public libvlc_video_track_t video;
[FieldOffset(0)]
public libvlc_subtitle_track_t subtitle;
}
你翻译了错误的联合。我怀疑当你说:
你的意思是,数据在工会我在大多数结构/联合字段中获得垃圾数据。
之前很好,在工会之后是垃圾。让我们来看看工会。是的:
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;
};
所以,简单地用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;
}
顺便说一句,如果需要,很容易避免使用unsafe
。虽然,如果你没有缺点,那么能够使用指针将使代码更容易编写。
相关文章:
- C++ - 忽略并从其他文件获取数据
- 如何从网站获取数据并将其传输到数据库?
- 与多个 for 循环与单个 for 循环 wrt 相关的性能从多映射获取数据
- 如何从 CSV 获取数据并将其存储在 C++ 中的表对象中
- 获取 R 数据帧的内存地址
- C++ 如何从虚拟类的模板化子类中获取数据?
- 如何在C++中使用带有SFML的http reqest从节点.js服务器获取数据?
- 连接到远程存储库并获取数据
- 使用WiFi.h从WiFiClient ESP32获取数据
- CSV文件未从缓冲区获取数据
- C++从双指针获取数据
- C++ 从文件中获取数据时使用 strcpy 和 strcmp 按字母顺序对数组进行排序?
- 使用 Recvfrom 获取数据
- C 编程:在循环时运行 2 并从 loop1 获取数据的随机结果
- 复制构造函数并从方法中获取数据
- 如何在运行时从平面缓冲区获取数据值和数据类型
- 在C J2ME中读取Excel文件,并从ITQ获取数据
- 如何通过NodeMCU从Web获取数据
- 获取数据QFUTUREWATCHER
- 从文件中获取数据时如何放置换行符?