使用N-API开发Node.js C扩展报错:RTMP_Ping符号未定义
Node.js C扩展:undefined symbol: RTMP_Ping 问题排查与解决
问题背景
开发Node.js C扩展时,调用自定义的RTMP_Ping函数出现运行时错误:
node: symbol lookup error: /home/x/Desktop/code/rtmp-ping/build/Release/ping.node: undefined symbol: RTMP_Ping
相关代码如下:
主扩展文件(ping.c)
#include <assert.h> #include "../node_modules/node-api-headers/include/node_api.h" #include "rtmpc.h" #include <stdlib.h> static napi_value Ping(napi_env env, napi_callback_info info) { //... double dping = RTMP_Ping(url); napi_value ping; status = napi_create_double(env, dping, &ping); assert(status == napi_ok); return ping; } #define DECLARE_NAPI_METHOD(name, func) { name, 0, func, 0, 0, 0, napi_default, 0 } napi_value Init(napi_env env, napi_value exports) { napi_status status; napi_property_descriptor addDescriptor = DECLARE_NAPI_METHOD("ping", Ping); status = napi_define_properties(env, exports, 1, &addDescriptor); assert(status == napi_ok); return exports; } NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
头文件(rtmpc.h)
#ifndef RTMP_CUSTOM_HEADER #define RTMP_CUSTOM_HEADER double RTMP_Ping(char* url); #endif
实现文件(rtmpc.c)
#include "../lib/librtmp/rtmp.h" double RTMP_Ping(char* url) { RTMP* r = RTMP_Alloc(); RTMP_SetupURL(r, url); RTMP_Init(r); RTMP_SendCtrl(r, 6, 0, 0); return 20; }
问题原因
核心原因是编译构建时未将rtmpc.c的目标文件链接到最终的.node动态库中,导致RTMP_Ping的符号没有被包含在扩展模块里,Node.js加载时无法找到该符号。
此外还有两种次要可能:
- C/C编译的名字修饰不匹配(如果用C编译器编译C代码)
- 函数声明与实现的签名不一致
解决方案
1. 修正binding.gyp配置
确保binding.gyp的sources数组包含所有需要编译的C文件,同时正确链接依赖的librtmp库。示例配置:
{ "targets": [ { "target_name": "ping", "sources": [ "ping.c", "rtmpc.c" ], "include_dirs": [ "<!(node -p \"require('node-api-headers').include_dir\")", "./lib/librtmp" ], "libraries": [ "-L./lib/librtmp -lrtmp" ] } ] }
sources:必须包含ping.c和rtmpc.c,缺任意一个都会导致对应符号缺失include_dirs:指定头文件路径,保证能找到node-api和librtmp的头文件libraries:链接librtmp静态/动态库,避免RTMP_Alloc等底层函数符号缺失
2. 重新编译扩展
修改配置后,清理旧构建产物并重新编译:
node-gyp clean node-gyp configure build
3. 处理C/C++名字修饰问题(可选)
如果你的扩展使用C编译器编译,需要在rtmpc.h中添加extern "C"声明,防止C对函数名进行修饰:
#ifndef RTMP_CUSTOM_HEADER #define RTMP_CUSTOM_HEADER #ifdef __cplusplus extern "C" { #endif double RTMP_Ping(char* url); #ifdef __cplusplus } #endif #endif
4. 校验函数签名一致性
确认rtmpc.h中的声明和rtmpc.c中的实现完全匹配,包括返回值类型、参数类型和数量,避免因签名不一致导致符号不匹配。
内容的提问来源于stack exchange,提问作者violetflare
相关产品推荐
相关产品推荐

