Node.js Addon编译调试教程(一次成功版)

Node.js Addon编译调试教程(一次成功版)

环境配置

nodejs headers和lib下载

shell 复制代码
node-gyp configure --nodedir=D:\\nodejs && node-gyp build --debug

binding.gyp配置

js 复制代码
{
  # 构建目标集合
  "targets": [
    {
      # 模块最终生成的二进制文件名
      "target_name": "add",
      # 要编译的源文件
      "sources": [
        "./src/main.cpp",
        "./src/DemoAsyncWorker.cpp"
      ],
      # 头文件包含目录,!是执行shell命令取输出值,@是在列表中展开输出的每一项
      "include_dirs": ["<!@(node -p \"require('node-addon-api').include\")"],
      # 外部依赖项
      "dependencies": ["<!(node -p \"require('node-addon-api').gyp\")"],
      # 以下是编译器选项,启用node-addon-api的集成C++和JavaScript的异常处理
      "cflags!": [ "-fno-exceptions" ],
      "cflags_cc!": [ "-fno-exceptions" ],
      "xcode_settings": {
        "GCC_ENABLE_CPP_EXCEPTIONS": "YES",
        "CLANG_CXX_LIBRARY": "libc++",
        "MACOSX_DEPLOYMENT_TARGET": "10.7"
      },
      "msvs_settings": {
        "VCCLCompilerTool": {
          "ExceptionHandling": 1
        }
      },
      # 预定义宏,禁用NAPI的C++异常处理和node-addon-api废弃的API
      "defines": ["NAPI_DISABLE_CPP_EXCEPTIONS", "NODE_ADDON_API_DISABLE_DEPRECATED"]
    }
  ]
}

vscode debug配置

js 复制代码
// launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "JS Debug Build",
            "console": "integratedTerminal",
            "program": "${workspaceFolder}/index.js", // 测试js
            "preLaunchTask": "npm: build:debug"
        },
        {
            "name": "Windows Attach",
            "type": "cppvsdbg",
            "request": "attach",
            "processId": "${command:pickProcess}" // 启动的时候选择一个进程进行debug
        }
    ]
}
// task.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "npm",
            "script": "build:release",
            "problemMatcher": [],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}

python3

安装python3,并配置环境变量 PYTHON = python3安装目录

示例: C:\Programs\Python\Python311\python.exe

package.json配置

js 复制代码
"scripts": {
    "build:debug": "node-gyp configure && node-gyp build --debug",
    "build:release": "node-gyp configure && node-gyp build",
    "clean": "node-gyp clean"
},
"devDependencies": {
    "node-gyp": "^9.3.1" // 支持 python3,不要用 3.8.0 这个不支持pyton3
},

MSBuild 和 VC++工具集140/141

示例代码

  • index.js
js 复制代码
const Add = require('./build/Debug/add.node');

Add(1,2, result => {
    console.log('1 + 2 =',result)
})
  • ./src/main.cpp
c++ 复制代码
#include "./DemoAyncWorker.h"

using namespace Napi;

static Value _asyncDemo(const CallbackInfo& info) {
    Env env = info.Env();

    if (info.Length() != 3)
    {
        Error::New(env, "arguments.length !== 3").ThrowAsJavaScriptException();
        return env.Undefined();
    }

    if (!info[2].IsFunction())
    {
        Error::New(env, "typeof arguments[2] !== 'function'").ThrowAsJavaScriptException();
        return env.Undefined();
    }

    Function cb = info[2].As<Function>(); // Napi::Value -> Napi::Function

    DemoAsyncWorker *worker = new DemoAsyncWorker(cb);
    worker->Queue();

    return env.Undefined();
}

Object init(Env env, Object exports) {
    Object global = env.Global();
    Object console = global.Get("console").As<Object>();
    Function log = console.Get("log").As<Function>();
    log.Call(console, { String::New(env, "[C++] Call console.log()") });
    Function module = Function::New(env, _asyncDemo);
    return module;
}

NODE_API_MODULE(NODE_GYP_MODULE_NAME, init)
  • ./src/DemoAyncWorker.cpp
c++ 复制代码
#include "./DemoAyncWorker.h"
#include <thread>
#include <chrono>

using namespace Napi;

// 构造函数中把JS回调传给基类构造函数
DemoAsyncWorker::DemoAsyncWorker(Function& callback): AsyncWorker(callback) {}
// 析构函数啥也不干
DemoAsyncWorker::~DemoAsyncWorker() {}
// 子线程中等待1秒
void DemoAsyncWorker::Execute() {
  std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 打断点
}
// 异步操作完成,执行JS回调,传入'callback.'字符串,JS中将接收到这个字符串
void DemoAsyncWorker::OnOK() {
  Callback().Call({ String::New(Env(), "callback.") }); // 打断点
}
  • ./src/DemoAyncWorker.h
c++ 复制代码
#ifndef __DEMO_ASYNC_WORKER_H__
#define __DEMO_ASYNC_WORKER_H__

// 包含node-addon-api的头文件
#include <napi.h>

// 要实现异步必须继承Napi::AsyncWorker类,该类的内部会调用NAPI开启子线程
class DemoAsyncWorker : public Napi::AsyncWorker {
  public:
    // 构造函数传入JS的回调函数
    DemoAsyncWorker(Napi::Function&);
    // 析构函数
    ~DemoAsyncWorker();
    // 子线程下执行异步操作
    void Execute();
    // 异步操作执行完成的回调
    void OnOK();
};

#endif // ! __DEMO_ASYNC_WORKER_H__
相关推荐
‘’林花谢了春红‘’3 小时前
C++ list (链表)容器
c++·链表·list
机器视觉知识推荐、就业指导5 小时前
C++设计模式:建造者模式(Builder) 房屋建造案例
c++
Yang.996 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
熬夜学编程的小王7 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
zz40_7 小时前
C++自己写类 和 运算符重载函数
c++
前端李易安7 小时前
Webpack 热更新(HMR)详解:原理与实现
前端·webpack·node.js
六月的翅膀7 小时前
C++:实例访问静态成员函数和类访问静态成员函数有什么区别
开发语言·c++
liujjjiyun7 小时前
小R的随机播放顺序
数据结构·c++·算法
¥ 多多¥7 小时前
c++中mystring运算符重载
开发语言·c++·算法