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(),
);
}
下面,我有一个带有两个字符串指针参数的简单函数。第一个参数是表达式(即 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(),
);
}