LoginSignup
0
1

More than 1 year has passed since last update.

Node.js + TypeScript からC++のライブラリを呼び出す

Last updated at Posted at 2021-12-10

目的

  • 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`).
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1