ffi-napi如何正确接收C++回调中包含char数组的结构体参数
问题原因
你的问题核心是ffi-napi处理回调的结构体参数时的默认逻辑和C传参规则不匹配:
C向回调传递结构体值时,实际传递的是结构体的栈内存指针,但你在定义回调参数时直接指定了Info类型,ffi会直接对传入的指针地址做结构体解析,而非先解引用指针,导致chName字段的内存地址读取错误,出现全0数组或者越界段错误。ID字段因为是结构体的第一个成员,偏移量为0,刚好可以读到正确值,所以没有出现异常。
解决方案
按照以下步骤修改代码即可:
- 引入
ref-napi依赖用于指针解析 - 将回调的参数类型修改为
pointer,在回调内部手动解析为结构体实例 - 添加全局引用避免回调被JS GC回收
- 优化char数组转字符串的逻辑
修改后的完整代码
var ref = require('ref-napi'); var StructType = require('ref-struct-napi'); var ArrayType = require('ref-array-napi'); var ffi = require('ffi-napi'); var Info = StructType({ 'ID' : 'long', 'chName' : ArrayType('char', 128) }); var lib = ffi.DynamicLibrary('lib.so', ffi.DynamicLibrary.FLAGS.RTLD_LAZY); var SetCallback = ffi.ForeignFunction( lib.get('SetCallback'), 'void', ['pointer'] ); var callback = ffi.Callback('void', ['pointer'], (infoPtr) => { // 手动解引用指针得到结构体实例 const info = infoPtr.deref(); console.log(`ID: ${info.ID}`); // char数组转utf-8字符串,自动识别null终止符 console.log(`name: ${info.chName.toString('utf8')}`); }); // 挂载到全局避免被GC回收,防止C++调用空指针触发段错误 global.callback = callback; SetCallback(callback);
额外排查项
如果修改后仍有异常,可以调整结构体对齐配置匹配C++侧的对齐规则:
// 如果你C++侧使用了#pragma pack(1),添加packed参数 var Info = StructType({ 'ID' : 'long', 'chName' : ArrayType('char', 128) }, { packed: true });
内容的提问来源于stack exchange,提问作者DOM
相关产品推荐
相关产品推荐

