フェルマータ

個人用のメモ。ソフトウェアの導入とかが多くなる予定。ライセンスの気になる方はこのブログに載せたコードは修正 BSD に準ずるものと考えてください。

Nodejs から C++ のコードを使うために CMake-js を使ってみた

ポエム

CMake 使ったプロジェクトでいい感じに WORLD のラッパー実装を作ってみたが、 GUI を作ろうとするとはたして C++GUI 作るのがいまでもいいのかどうか悩んでしまった。 Twitter を通して知人友人に色々聞いてみたのだが、下記の選択肢が挙がってきた。

ちょっと今回はいろいろ考えた結果 C++ で完結するよりは、目下興味のある Electron 側に舵を切ってみることにした。これをやるには nodejs から C/C++ のコードを読み出さなければならいので、さらに下記のような選択肢が出てきた。

んで、 WebAssembly は下記のような実装する必要があるよ、と教えてもらったのだが業務ならともかく私の余暇の時間ではちょっとしんどそうだったので諦めた。

t.co

本当は nodejs に依存しすぎるのも嫌だったので WebAssembly 使えたら良かったんだけれど、いかんせん C/C++ を使っていくには先人の知見が少なかったので今回は CMake-js を使ってみることにした。とりあえず書き残さないと先に進まなさそうだったので備忘録がてら記事にしておく。

実装

tutorial 通りなのでそのまま書いただけ。コアの部分は C/C++ に依存しているだけあって、結構シンプルにいけるっぽい。

  • index.js
#include <node_api.h>
#include <cassert>
#include <thread>

namespace {
    napi_value hello(napi_env env, napi_callback_info info)
    {
    napi_status status;
    napi_value js_value;
    status = napi_create_string_utf8(env, "Hello, cmake-js!", NAPI_AUTO_LENGTH, &js_value);
    assert(status == napi_ok);
    return js_value;
    }

    void export_func(napi_env env, napi_value exports, const char *name, napi_callback f)
    {
    napi_status status;
    napi_value func;
    status = napi_create_function(env, name, NAPI_AUTO_LENGTH, f, nullptr, &func);
    assert(status == napi_ok);
    napi_set_named_property(env, exports, name, func);
    }

    napi_value Init(napi_env env, napi_value exports)
    {
    export_func(env, exports, "hello", hello);
    return exports;
    }

    NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
}
var hello = require('./build/Release/hello.node');

console.log(hello.hello());
  • CMakeLists.txt
# From https://github.com/cmake-js/cmake-js/wiki/TUTORIAL-01-Creating-a-native-module-by-using-CMake.js-and-NAN

cmake_minimum_required(VERSION 3.0)

# Name of the project (will be the name of the plugin)
project(hello)

# Build a shared library named after the project from the files in `src/`
file(GLOB SOURCE_FILES "*.cc" "*.hh")
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES})

# Gives our library file a .node extension without any "lib" prefix
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")

# Essential include files to build a node addon,
# You should add this line in every CMake.js based project
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_JS_INC})

# Essential library files to link to a node addon
# You should add this line in every CMake.js based project
target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})

レポジトリ

github.com