You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ffi-napi如何正确接收C++回调中包含char数组的结构体参数

问题原因

你的问题核心是ffi-napi处理回调的结构体参数时的默认逻辑和C传参规则不匹配:
C
向回调传递结构体值时,实际传递的是结构体的栈内存指针,但你在定义回调参数时直接指定了Info类型,ffi会直接对传入的指针地址做结构体解析,而非先解引用指针,导致chName字段的内存地址读取错误,出现全0数组或者越界段错误。ID字段因为是结构体的第一个成员,偏移量为0,刚好可以读到正确值,所以没有出现异常。

解决方案

按照以下步骤修改代码即可:

  1. 引入ref-napi依赖用于指针解析
  2. 将回调的参数类型修改为pointer,在回调内部手动解析为结构体实例
  3. 添加全局引用避免回调被JS GC回收
  4. 优化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 05:42:04