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__
相关推荐
rjszcb6 分钟前
一文说完c++全部基础知识,IO流(二)
c++
小字节,大梦想1 小时前
【C++】二叉搜索树
数据结构·c++
吾名招财1 小时前
yolov5-7.0模型DNN加载函数及参数详解(重要)
c++·人工智能·yolo·dnn
我是哈哈hh1 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
憧憬成为原神糕手1 小时前
c++_ 多态
开发语言·c++
郭二哈1 小时前
C++——模板进阶、继承
java·服务器·c++
挥剑决浮云 -2 小时前
Linux 之 安装软件、GCC编译器、Linux 操作系统基础
linux·服务器·c语言·c++·经验分享·笔记
丶Darling.2 小时前
LeetCode Hot100 | Day1 | 二叉树:二叉树的直径
数据结构·c++·学习·算法·leetcode·二叉树
labuladuo5202 小时前
Codeforces Round 977 (Div. 2) C2 Adjust The Presentation (Hard Version)(思维,set)
数据结构·c++·算法
小柯J桑_2 小时前
C++:STL简介
c++·stl