我试图将一个结构从一个锈蚀函数返回到Node.js,这个结构是嵌套的,包含一个数组,因此它非常复杂,所以我想在Rust中执行分配,并让Node.JS接收一个完整的对象,简而言之,下面是Rust代码:
返回的State包含许多Config、消息(例如错误消息或一些警告)和一些信任。
use std::ffi::CStr;
use std::os::raw::c_char;
#[derive(Debug)]
#[repr(C)]
pub struct Config {
pub some_fields_here: String,
// pub ...
}
#[derive(Debug)]
#[repr(C)]
pub struct State {
pub message: String, // Even changing this to *mut c_char doesn't help the immediate problem
pub configs: *mut Config,
pub num_configs: usize,
}
#[no_mangle]
pub extern "C" fn config_from_file(_not_really_used_in_example: *const c_char) -> *mut Configuration {
let mut configs: Vec<Config> = vec![];
configs.push(Config {
some_fields_here: String::from("hello world"), // should maybe be CString::from(...).into_raw()
});
Box::into_raw(Box::new(State {
message: String::from("a message here"),
configs: Box::into_raw(configs.into_boxed_slice()) as *mut Config,
num_configs: 1,
}))
}从节点方面来说,我们发现的所有示例和文档都只是利用StructType来准备一些东西传递到FFI中,或者透明地传递,而不需要询问它。
我们想做的是:
var ffi = require("ffi-napi");
var ref = require("ref-napi");
var StructType = require("ref-struct-di")(ref);
var ArrayType = require("ref-array-di")(ref);
const Config = StructType({
some_fields_here: ref.types.CString,
});
const State = StructType({
message: ref.types.CString,
configs: ref.refType(ArrayType(Config)),
num_configs: ref.types.size_t,
});
const StatePtr = ref.refType(StatePtr);
var ourlib = ffi.Library("./target/debug/ourlib", {
config_from_file: [StatePtr, [ref.types.CString]],
});
const ffiResult = ourlib.config_from_file("a file path, in the real code");
console.log(ffiResult)
// => <Buffer@0x47ce560 20 e2 83 04 00 00 00 00 57 00 00 00 00 00 00 00 57 00 00 00 00 00 00 00,
type: { [Function: StructType] defineProperty: [Function: defineProperty], toString: [Function:
toString], fields: { message: [Object], configs: [Object], num_configs: [Object] }, size: 24,
alignment: 8, indirection: 1, isPacked: false, get: [Function: get], set: [Function: set] }>在这里,我们需要获得一个Javscript对象(类似于上面的struct ),访问任何字段,或者将它看作一个对象。我们没有在https://tootallnate.github.io/ref的测试或文档中找到适当的示例,也没有在https://github.com/node-ffi-napi/ref-struct-di中找到合适的示例
我不希望从Buffer()支持的C对象中清晰地传递到JavaScript,当然,我们必须解码和移动事物,但我无法从JavaScript访问包含在该结构中的信息。任何deref()、toObject()或获取单个字段的组合似乎都没有帮助。
我本以为这样的事情可能会起作用,但它可能会导致错误或打印垃圾,这取决于我所做的一些微小的调整:
console.log(ffiResult);
console.log(ref.deref().readCString(ffiResult, 0));我知道在某种程度上在库中进行分配,并且在宿主语言中解压缩这些结构是不统一的,但是由于数据的形状,而且我们不能更改库代码,我们没有太多的选择。
发布于 2021-04-26 07:56:20
,包含一个数组,所以我想在Rust中进行分配,并让Node.JS接收一个完整的对象,这是非常复杂的,
包含数组是棘手的/陷阱部分。C (ergo )中的数组趋向于为零结束,但不能保证对结构数组的工作方式是特殊的。
以下是我们必须做的事情:
into_boxed_slice()来忘记它,这给出了指向第一个的指针。上的length属性。
就像我们第一次发布的例子一样。
然而,在node.js中,它有一点不同,工作代码与我们所拥有的几乎完全相同,下面是类型:
const Config = StructType({
some_fields_here: ref.types.CString,
});
const State = StructType({
message: ref.types.CString,
configs: ArrayType(Config), // we had refType(ArrayType(Config))
num_configs: ref.types.size_t,
});
const StatePtr = ref.refType(StatePtr);
var ourlib = ffi.Library("./target/debug/ourlib", {
config_f...在进行了该更改之后,唯一的问题是,在初始化长度之前,数组是不可用的,因此,稍后我们只需这样做:
const ffiResult = ourlib.config_from_file("a file path, in the real code");
const ffiState = ffiResult.deref(); // it's a pointer, remember.
ffiState.configs.length = ffiState.num_configs; // see comment below在设置ArrayType的长度之后,可以或多或少地使用它,就像普通数组一样。
https://stackoverflow.com/questions/67028734
复制相似问题