Rust FFI:具有多个字符串指针的函数;第一个参数具有来自后续字符串指针的聚合值

Rust FFI: function with multiple string pointers; first parameter has aggregated value from subsequent string pointers

下面,我有一个带有两个字符串指针参数的简单函数。第一个参数是表达式(即 value = "foo"),第二个参数是 json(即 value = {"foo":{"bar":{"baz":true}}})。当我执行测试时,我得到以下信息:

结果:

expression foo{"foo":{"bar":{"baz":true}}}
json {"foo":{"bar":{"baz":true}}} 

预计:

expression foo
json {"foo":{"bar":{"baz":true}}} 

函数代码

use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::panic::catch_unwind;
use std::str;

#[no_mangle]

pub extern "C" fn execute(expression: *const c_char, json: *const c_char) {
    let result = catch_unwind(|| {
        let expression_cstr = unsafe {
            assert!(!expression.is_null());
            CStr::from_ptr(expression)
        };
        let json_cstr = unsafe {
            assert!(!json.is_null());
            CStr::from_ptr(json)
        };
        let expression_str =
            str::from_utf8(expression_cstr.to_bytes()).map(|e| println!("expression {}", e));
        let json_str = str::from_utf8(json_cstr.to_bytes()).map(|j| println!("json {}", j));
    });
}

#[cfg(test)]
mod tests {
    use std::os::raw::c_char;

    #[test]
    fn it_works() {
        let expression = "foo".as_ptr() as *const c_char;
        super::execute(
            expression,
            "{\"foo\":{\"bar\":{\"baz\":true}}}".as_ptr() as *const c_char,
        );
    }
}

你的 execute 函数需要以 null 结尾的 C 字符串,但是 Rust 字符串不使用以 null 结尾的表示,所以 "foo".as_ptr() as *const c_char 不会给你一个有效的 C 字符串(你通常当您尝试将其视为一个数据时获取额外数据,尽管这在技术上是未定义的行为)。

正确的方法是在调用您的函数之前转换为 CString,以确保您的输入具有正确的表示形式:

#[test]
pub fn it_works() {
    let expression = CString::new("foo").unwrap();
    let json = CString::new("{\"foo\":{\"bar\":{\"baz\":true}}}").unwrap();

    super::execute(
        expression.as_ptr(),
        json.as_ptr(),
    );
}