Rust调用Miniaudio库返回MA_INVALID_OPERATION(-3)错误的原因排查及相关疑问
Rust调用Miniaudio库返回MA_INVALID_OPERATION(-3)错误的原因排查及相关疑问
我在尝试用Rust实现音乐播放功能,之前在C/C++开发中一直用Miniaudio来处理音频和播放音乐,下面是我之前能用的C语言示例代码:
ma_engine engine; ma_result result = ma_engine_init(NULL, &engine); if (result != MA_SUCCESS) { // 初始化失败处理 } ma_engine_play_sound(&engine, "test.mp3", NULL); sleep(60);
但我自己编写的Rust绑定代码却无法正常工作,运行时会触发panic,返回的错误码是-3,这个值在miniaudio.h中被定义为MA_INVALID_OPERATION:
// Generated by bindgen include!(concat!(env!("OUT_DIR"), "/bindings.rs")); pub struct Engine { inner: ma_engine, } impl Engine { pub fn new() -> Result<Self, i32> { unsafe { let mut engine = std::mem::MaybeUninit::<ma_engine>::uninit(); let result = ma_engine_init(std::ptr::null(), engine.as_mut_ptr()); if result != 0 { Err(result) } else { Ok(Self { inner: engine.assume_init(), }) } } } pub fn play_sound(&mut self, path: &str) -> Result<(), i32> { let c_path = CString::new(path).unwrap(); let result = unsafe { ma_engine_play_sound(&mut self.inner, c_path.as_ptr(), std::ptr::null_mut()) }; if result != 0 { Err(result) } else { Ok(()) } } } impl Drop for Engine { fn drop(&mut self) { unsafe { ma_engine_uninit(&mut self.inner); } } } fn main() { let mut engine = Engine::new().unwrap(); // 这一行会panic,返回值是-3,对应miniaudio.h中的MA_INVALID_OPERATION engine.play_sound("./test.mp3").unwrap(); thread::sleep(Duration::from_mins(1)); }
我找不到任何关于MA_INVALID_OPERATION错误触发场景的官方说明,而且我确认ma_engine指针和转换后的C风格路径指针都不是NULL。我还尝试过把所有逻辑直接内联到main函数的unsafe代码块中,但问题依然存在。
我是不是在绑定过程中遗漏了什么细节?另外,Miniaudio的错误码详细说明在哪里可以找到?
编辑:
我修改了自己的miniaudio.c文件,封装了几个简单的C函数并创建了对应的头文件:
#define MINIAUDIO_IMPLEMENTATION #include "miniaudio.h" ma_engine engine = {0}; ma_result init() { return ma_engine_init(NULL, &engine); } ma_result play_sound(const char *path) { return ma_engine_play_sound(&engine, path, NULL); } void uninit() { ma_engine_uninit(&engine); }
然后用Rust直接调用这些封装后的C函数,这个版本却可以正常工作:
fn main() { unsafe { if init() != 0 { // 初始化失败panic } let path = "test.mp3"; let c_path = CString::new(path).unwrap(); if play_sound(c_path.as_ptr()) != 0 { // 播放失败panic } thread::sleep(Duration::from_mins(1)); uninit(); } }
为什么第一个版本的Rust绑定代码无法正常运行,而通过封装C函数间接调用的版本却能正常工作?
备注:内容来源于stack exchange,提问作者WanGuang
相关产品推荐
相关产品推荐

