Json 如何从NodeJS中的Rust FFI函数返回字符串值?
我想生成6个随机数,将它们推到一个向量上,然后使用Json 如何从NodeJS中的Rust FFI函数返回字符串值?,json,node.js,rust,node-ffi,Json,Node.js,Rust,Node Ffi,我想生成6个随机数,将它们推到一个向量上,然后使用rustc_serialize将该向量编码为一个JSON字符串,供NodeJ使用 extern板条箱兰德; 外部板条箱锈迹丛生; 使用rand::{OsRng,Rng}; 使用rustc_serialize::json::{self,json,ToJson}; #[没有损坏] pub extern“C”fn generate()->字符串{ 让我们选择:[u8;6]=[1,2,3,4,5,6]; 让mut rand_vec:vec=vec::ne
rustc_serialize
将该向量编码为一个JSON字符串,供NodeJ使用
extern板条箱兰德;
外部板条箱锈迹丛生;
使用rand::{OsRng,Rng};
使用rustc_serialize::json::{self,json,ToJson};
#[没有损坏]
pub extern“C”fn generate()->字符串{
让我们选择:[u8;6]=[1,2,3,4,5,6];
让mut rand_vec:vec=vec::new();
让mut rng=匹配OsRng::new(){
Ok(t)=>t,
Err(e)=>panic!(“未能创建OsRng!,{},e),
};
对于0..5中的uu{
随机向量推送(*rng.choose(&chooses.unwrap());
}
json::encode(&rand_vec).unwrap()
}
此代码编译为库generate_6_rand.dll
。我有一个单独的二进制文件,用来测试这段代码
如果我跑
println!(“{:?},&json::encode(&rand_vec).unwrap());
输出:
“[5,4,3,4,1,3]”//如预期
然后在NodeJS程序中使用我的.dll
:
var ffi = require('ffi');
var path = require('path');
var lib = ffi.Library(path.join(__dirname,
'./ffi/generate_6_rand.dll'), {
generate: [ 'string', [ ]]
});
console.log(lib.generate());
测验
console.log(lib.generate())
输出:
��.�
它是一个EcmaScriptArrayBuffer
?
console.log(新的ArrayBuffer(lib.generate())
输出:
ArrayBuffer{bytellength:0}
它的原链性质是什么?
console.log(lib.generate()。\uuuuu proto\uuuuuu)
输出:
[字符串:“”]
将代码更改为:
var ref = require('ref');
var ArrayType = require('ref-array');
var Int32Array = ArrayType(ref.types.int32);
var lib = ffi.Library(path.join(__dirname,
'../dice_lib/target/release/generate_6_rand.dll'), {
generate: [ Int32Array, [ ]]
});
console.log(new ArrayBuffer(lib.generate()));
输出:
ArrayBuffer{bytellength:0}
为什么FFI函数没有像我期望的那样返回JSON字符串?感谢Wesley Wiser为我提供了有关
CString
的重要线索。我在中找到了答案
无论是返回JSON字符串还是返回CString
,预期JSON字符串的内存都在NodeJS程序访问之前被释放
这是我基于那篇文章的解决方案。对于其他新手程序员,请记住我的解决方案可能是理想的,也可能不是理想的:
生锈
extern板条箱兰德;
外部板条箱锈迹丛生;
外部板条箱libc;
使用libc::c_char;
使用rand::{OsRng,Rng};
使用std::ffi::CString;
使用rustc_serialize::json;
#[没有损坏]
发布外部“C”fn generate()->*mut C_char{
让我们选择:[u8;6]=[1,2,3,4,5,6];
让mut rand_vec:vec=vec::new();
让mut rng=匹配OsRng::new(){
Ok(t)=>t,
Err(e)=>panic!(“未能创建OsRng!,{},e),
};
对于0..6中的uu{
随机向量推送(*rng.choose(&chooses.unwrap());
}
让json_string=CString::new(json::encode(&rand_vec).unwrap()).unwrap();
json_string.into_raw()
}
#[没有损坏]
发布外部“C”fn可用内存(指针:*mut C_char){
不安全{
如果指针.is_null(){
返回;
}
CString::from_raw(指针)
};
}
NodeJS
我设置了两个
控制台。log
s显示解除分配前后的输出。String
s在Rust中不是用来跨越FFI边界的。您可能想要的是让generate
函数返回CString
var ffi = require('ffi');
var path = require('path');
var lib = ffi.Library(path.join(__dirname,
'./ffi/generate_6_rand.dll'), {
generate: [ 'char *' , [ ]],
free_memory: ['void', ['char *']]
});
var json_string = lib.generate();
var save_json = JSON.parse(json_string.readCString());
console.log( json_string.readCString()); // Output: [6,1,6,4,1,4]
lib.free_memory(json_string);
console.log(json_string.readCString()); // Output: ��x�