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

Ruby通过FFI调用Rust函数时serde解析JSON报trailing characters错误

哈哈,这个问题我太熟了!你看错误信息里那个末尾的�(空终止符)就是问题所在——咱们一步步拆解:

问题根源

Ruby的FFI在传递字符串到Rust时,会遵循C语言的字符串规范,自动在字符串末尾追加一个\0(空终止符)来标记字符串结束。但你用to_json生成的JSON本身已经是完整的有效字符串了,这个额外的\0就变成了JSON末尾的无效字符,serde_json严格遵循JSON规范,自然会判定为“trailing characters(末尾多余字符)”并抛出错误。

修复方案

你可以从Rust侧或者Ruby侧入手解决,优先推荐Rust侧的处理方式,更可靠:

方法一:Rust侧用CStr自动去除空终止符

这是最规范的处理方式,因为Rust通过FFI接收的字符串本质是C风格字符串,用std::ffi::CStr来转换会自动识别并截断末尾的\0。

比如你的Rust函数可以改成这样:

use serde::Deserialize;
use std::ffi::CStr;
use std::os::raw::c_char;

#[derive(Debug, Deserialize)]
struct NetworkParams {
    network: Network,
}

#[derive(Debug, Deserialize)]
struct Network {
    server_address: String,
}

#[no_mangle]
pub extern "C" fn send_it_to_rust(raw: *const c_char) -> /* 你的返回类型 */ {
    // 把C风格字符串转成Rust字符串,自动去掉末尾空终止符
    let c_str = unsafe { CStr::from_ptr(raw) };
    let json_str = match c_str.to_str() {
        Ok(s) => s,
        Err(e) => {
            eprintln!("Failed to parse string: {}", e);
            return /* 返回错误结果 */;
        }
    };

    // 现在解析就不会有问题了
    match serde_json::from_str::<NetworkParams>(json_str) {
        Ok(params) => {
            // 处理你的业务逻辑
            /* 返回成功结果 */
        }
        Err(e) => {
            eprintln!("Invalid parameters: {}", e);
            return /* 返回错误结果 */;
        }
    }
}

方法二:Ruby侧手动截断空字符(应急用)

如果你暂时不想改动Rust代码,也可以在Ruby侧传递前手动去掉可能的空字符:

my_json_raw_str = { network: { server_address: "my_server.com" } }
clean_json = my_json_raw_str.to_json.delete("\0")
res = send_it_to_rust(clean_json)

不过这个方法不如Rust侧处理可靠,因为FFI的空终止符是Ruby自动添加的,极端场景下可能出现位置异常,所以只推荐临时应急使用。

额外提醒

serde_json对JSON格式的校验非常严格,哪怕是末尾一个不起眼的空字符,也不符合JSON规范,所以才会触发错误。用C风格字符串的方式处理FFI传递的字符串,是Rust和Ruby/其他语言交互的标准做法,能避免很多类似的编码或字符串边界问题。

内容的提问来源于stack exchange,提问作者Korasatavvaku

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 16:42:27