节点FFI包装函数在同步使用时失败,但asynchronous工作

我试图用Node FFI来包装一个Rust库(暴露一个C API)。 我有以下代码包装两个函数。 一个是返回指针的“构造函数”。 另一个需要一个指针并返回Cstring。

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的asynchronous调用时,响应是正确的。 但是,当我尝试使用同步样式调用该函数时,它将返回垃圾,或者非常非常less,正确的结果。 以下nodeunittesting将执行该场景:

 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在这里 。

这个问题恐怕来自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() } 

CString::as_ptr的文档具体调用了这种模式:

 use std::ffi::{CString}; let ptr = CString::new("Hello").unwrap().as_ptr(); unsafe { // `ptr` is dangling *ptr; } 

在最后一行创build的CString在将一个指针指向其内部之后立即被破坏,导致一个悬挂的指针。

您正在使用的comm库需要修复,也可能需要审计其他function。

这里的解决办法是泄漏CString ,然后提供另一个函数,用泄露的指针来调用,这将释放它。