You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 18:23:11