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

Node-API函数遇arm64架构未定义符号错误(napi-inl.h相关)

问题诊断与解决

你的编译错误核心原因有两个:

  1. 编译目标类型错误:Node-API扩展需要编译为共享动态库,但你用add_executable生成了可执行文件,不符合Node加载扩展的要求。
  2. 未链接Node.js核心库:NAPI的符号(如napi_create_function)属于Node.js运行时库,你的CMake配置未将其链接到目标文件,导致链接器无法解析这些符号。

另外,你的C++代码中napi_get_value_string_utf8的使用方式存在内存越界风险,需要一并修正。


第一步:修正CMakeLists.txt配置

修改后的完整配置如下:

cmake_minimum_required(VERSION 3.13)

set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "" FORCE)
set(CMAKE_CXX_COMPILER "/usr/bin/clang++" CACHE STRING "C++ compiler" FORCE)
set(CMAKE_CXX_STANDARD 20)

project(BCKND)

# 仅保留编译阶段的选项,链接选项移至后续配置
add_compile_options(-std=c++20 -fcolor-diagnostics -Wall)

# 关键:将目标改为共享库,Node扩展必须是SHARED类型
add_library(${PROJECT_NAME} SHARED main.cpp)

# 设置Node扩展的命名规则:移除默认前缀,后缀改为.node
set_target_properties(${PROJECT_NAME} PROPERTIES
    PREFIX ""
    SUFFIX ".node"
)

# 指定依赖库的链接目录
target_link_directories(${PROJECT_NAME} PRIVATE 
    /opt/homebrew/Cellar/libpq/15.1/lib
    /opt/homebrew/Cellar/libpqxx/7.7.4/lib
)

# 指定头文件目录
target_include_directories(${PROJECT_NAME} PRIVATE 
    /opt/homebrew/Cellar/libpq/15.1/include
    /opt/homebrew/Cellar/libpqxx/7.7.4/include
    /Users/name/project/Frontend/node_modules/node-addon-api
    /usr/local/include/node
)

# 链接依赖库(包括Node.js核心库,路径需根据实际安装位置调整)
target_link_libraries(${PROJECT_NAME} 
    pq
    pqxx
    /opt/homebrew/lib/libnode.dylib  # M1 Mac Homebrew安装Node的默认路径
)

配置说明:

  • add_library(${PROJECT_NAME} SHARED main.cpp):将编译目标改为共享库,这是Node扩展的强制要求。
  • set_target_properties:生成符合Node规范的扩展文件(如BCKND.node)。
  • 移除了add_compile_options中的-L/-l选项,这类链接阶段的配置应放在target_link_libraries或target_link_directories中。
  • 新增Node核心库链接:如果你的Node不是通过Homebrew安装,需自行调整libnode.dylib的路径。

第二步:修正main.cpp代码错误

原代码中napi_get_value_string_utf8的使用方式会导致内存越界,修正后的代码如下:

#include <iostream>
#include <string>

#include <napi.h>

napi_value retrieveData(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1];
    std::string date;
    napi_value output;
    napi_status status;

    // 获取回调参数
    status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
    if (status != napi_ok) {
        napi_throw_error(env, NULL, "Failed to get callback info");
        return NULL;
    }

    // 先获取输入字符串的长度
    size_t str_len = 0;
    status = napi_get_value_string_utf8(env, args[0], NULL, 0, &str_len);
    if (status != napi_ok) {
        napi_throw_error(env, NULL, "Failed to get string length");
        return NULL;
    }

    // 分配足够的缓冲区并读取字符串
    date.resize(str_len);
    status = napi_get_value_string_utf8(env, args[0], &date[0], str_len + 1, NULL);
    if (status != napi_ok) {
        napi_throw_error(env, NULL, "Failed to get string value");
        return NULL;
    }

    // 创建返回的字符串
    status = napi_create_string_utf8(env, date.c_str(), date.length(), &output);
    if (status != napi_ok) {
        napi_throw_error(env, NULL, "Failed to create string");
        return NULL;
    }

    return output;
}

napi_value init(napi_env env, napi_value exports) {
    napi_value retrieve;
    napi_status status = napi_create_function(env, nullptr, 0, retrieveData, nullptr, &retrieve);
    if (status != napi_ok) {
        napi_throw_error(env, NULL, "Failed to create function");
        return NULL;
    }

    // 将函数挂载到exports对象,Node才能通过require访问
    napi_set_named_property(env, exports, "retrieveData", retrieve);
    return exports;
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, init);

代码说明:

  • 增加了napi_status错误检查,便于调试问题。
  • 修正napi_get_value_string_utf8的用法:先获取字符串长度,再分配对应大小的缓冲区,避免内存越界。
  • 调整init函数逻辑:将创建的函数挂载到exports对象上,确保Node加载扩展后能访问到目标函数。

第三步:编译与测试

  1. 创建构建目录并进入:
mkdir build && cd build
  1. 生成构建文件:
cmake ..
  1. 编译:
make
  1. 在Node.js中测试扩展:
const addon = require('./build/BCKND.node');
console.log(addon.retrieveData('202405')); // 输出:202405

内容的提问来源于stack exchange,提问作者ygngzln

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 06:55:55