目的
- Node.jsからC++のライブラリをコールしたい
- node-gypを使えばできるっぽいが、どのサンプルも動かない・・・(当方intel Mac / Big Sur)
- v8のAPIが色々変更してるっぽい。最新環境で動作確認できるサンプルが欲しい
成果物
とりあえず作ってみたサンプル一式は以下です。
https://github.com/swmokyun/sample-node-gyp
環境
- intel Mac
- macOS Big Sur (11.6)
- Node.js 14
Cまわりのセットアップ
以下を参考にCをビルドできる環境を作っておく
https://github.com/nodejs/node-gyp#installation
nodeまわりのセットアップ
- Node.js 14 を動作できるようにする。自分はnodebrewを使って切り替えています。
- 以下をyarnで追加
"@types/node": "^16.11.12",
"node-gyp": "^8.4.1",
"ts-node-dev": "^1.1.8",
"typescript": "^4.5.3"
Cのサンプルコードとgypの設定を用意
binding.gyp
{
"targets": [
{
"target_name": "native_ext",
"sources": ["native_ext.cc"]
}
]
}
native_ext.cc
#include <node/v8.h> // 自分の環境だとこのパスじゃないと動かなかった
#include <node/node.h>
using namespace node;
using namespace v8;
void Method(const v8::FunctionCallbackInfo<v8::Value> &args)
{
v8::Isolate *isolate = args.GetIsolate();
v8::HandleScope scope(isolate);
v8::Local<v8::String> result;
v8::MaybeLocal<v8::String> temp = String::NewFromUtf8(isolate, "Hello World");
temp.ToLocal(&result);
args.GetReturnValue().Set(result);
}
void Method2(const v8::FunctionCallbackInfo<v8::Value> &args)
{
if (args.Length() != 2)
{
args.GetReturnValue().Set(-1);
return;
}
v8::Isolate *isolate = args.GetIsolate();
v8::HandleScope scope(isolate);
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
double p1 = args[0]->NumberValue(context).FromJust();
double p2 = args[1]->NumberValue(context).FromJust();
args.GetReturnValue().Set(p1 + p2);
}
void init(v8::Local<v8::Object> target)
{
NODE_SET_METHOD(target, "hello", Method);
NODE_SET_METHOD(target, "add", Method2);
}
NODE_MODULE(binding, init);
ビルド
npx node-gyp configure
npx node-gyp build
これで build/Release/native_ext.node が作成される
呼び出し側
上記で作成したnative_ext.nodeを呼び出す
test.ts
var addon = require("./build/Release/native_ext.node")
const ret: string = addon.hello()
console.log(ret) // Hello World!
const ret2_1: number = addon.add()
console.log(ret2_1) // -1
const ret2_2: number = addon.add(1.1, 1.2)
console.log(ret2_2) // 2.3
実行
$ npx ts-node-dev test.ts
[INFO] 10:57:24 ts-node-dev ver. 1.1.8 (using ts-node ver. 9.1.1, typescript ver. 4.5.3)
Hello World
-1
2.3
おおおお、動きました。
補足
以下のようなエラーがでたらNode.jsのバージョンが合っていない。
おとなしくnodebrewなどでNode.jsのバージョンを切り替える。
Node.jsのバージョン一覧はこちら https://nodejs.org/ja/download/releases/
[ERROR] 11:21:01 Error: The module '/xxx/xxx/sample-node-gyp/src/build/Release/native_ext.node'
was compiled against a different Node.js version using
NODE_MODULE_VERSION 83. This version of Node.js requires
NODE_MODULE_VERSION 93. Please try re-compiling or re-installing
the module (for instance, using `npm rebuild` or `npm install`).