节点 FFI 包装函数在同步使用时失败,但异步工作
Node FFI wrapper function fails when used synchronously, but works asynchronously
我正在尝试使用 Node FFI 包装一个 Rust 库(公开一个 C API)。我有以下代码包装了两个函数。一个是"constructor"那个returns一个指针。另一个接受一个指针和 returns C 字符串。
var libcomm = ffi.Library('lib/c_api/target/debug/libcomm', {
'comm_address_for_content': ['pointer', ['string']],
'comm_address_to_str': ['string', ['pointer']]
});
当我使用 comm_address_to_str
的异步调用时,响应是正确的。但是,当我尝试使用同步样式调用该函数时,它 returns 垃圾,或者很少有正确的结果。下面的nodeunit测试演练场景:
const comm = require("../").libcomm;
exports.testAddressForContent = function (test) {
const ptr = comm.comm_address_for_content('test');
const result = comm.comm_address_to_str(ptr);
test.equal(result, 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'); // always fails
console.log('sync', result); // random garbage
comm.comm_address_to_str.async(ptr, function(err, result) {
test.equal(result, 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'); // always passes
console.log('async', result); // 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'
test.done();
});
}
我不知道是什么原因造成的,但我需要能够使用同步调用样式。我包装的 Rust 库的 C API 是 here.
恐怕问题来自 comm
库,特别是 comm_address_to_str
函数:
#[no_mangle]
pub extern "C" fn comm_address_to_str(address: *const Address) -> *const c_char {
let string = unsafe { *address }.to_str();
CString::new(string).unwrap().as_ptr()
}
documentation of CString::as_ptr
专门调出这个模式:
use std::ffi::{CString};
let ptr = CString::new("Hello").unwrap().as_ptr();
unsafe {
// `ptr` is dangling
*ptr;
}
在最后一行创建的 CString
在将指针放入其内部后立即被销毁,导致悬空指针。
您正在使用的 comm
库需要修复,其他功能也可能值得审核。
这里的修复方法是泄漏 CString
,然后提供另一个函数来调用泄漏的指针,该函数将负责释放它。
我正在尝试使用 Node FFI 包装一个 Rust 库(公开一个 C API)。我有以下代码包装了两个函数。一个是"constructor"那个returns一个指针。另一个接受一个指针和 returns C 字符串。
var libcomm = ffi.Library('lib/c_api/target/debug/libcomm', {
'comm_address_for_content': ['pointer', ['string']],
'comm_address_to_str': ['string', ['pointer']]
});
当我使用 comm_address_to_str
的异步调用时,响应是正确的。但是,当我尝试使用同步样式调用该函数时,它 returns 垃圾,或者很少有正确的结果。下面的nodeunit测试演练场景:
const comm = require("../").libcomm;
exports.testAddressForContent = function (test) {
const ptr = comm.comm_address_for_content('test');
const result = comm.comm_address_to_str(ptr);
test.equal(result, 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'); // always fails
console.log('sync', result); // random garbage
comm.comm_address_to_str.async(ptr, function(err, result) {
test.equal(result, 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'); // always passes
console.log('async', result); // 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'
test.done();
});
}
我不知道是什么原因造成的,但我需要能够使用同步调用样式。我包装的 Rust 库的 C API 是 here.
恐怕问题来自 comm
库,特别是 comm_address_to_str
函数:
#[no_mangle]
pub extern "C" fn comm_address_to_str(address: *const Address) -> *const c_char {
let string = unsafe { *address }.to_str();
CString::new(string).unwrap().as_ptr()
}
documentation of CString::as_ptr
专门调出这个模式:
use std::ffi::{CString};
let ptr = CString::new("Hello").unwrap().as_ptr();
unsafe {
// `ptr` is dangling
*ptr;
}
在最后一行创建的 CString
在将指针放入其内部后立即被销毁,导致悬空指针。
您正在使用的 comm
库需要修复,其他功能也可能值得审核。
这里的修复方法是泄漏 CString
,然后提供另一个函数来调用泄漏的指针,该函数将负责释放它。