node-addon-api + CMake
概述
node-addon-api 独立于V8,上手简单了。作为官方API的存在,质量有保证。同时版本适配问题比较友好。
本文参考了Node.js Addon Examples中的以下2个例子
- build_with_cmake
- 6_object_wrap
环境
Window 10
nodejs 16.14.2 (Currently using 64-bit executable)
依赖
node-addon-api 4.3.0
cmake-js 6.3.0
栗子
修改 package.json ,在script中添加以下内容
"scripts": {
"install": "cmake-js compile"
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.9)
cmake_policy(SET CMP0042 NEW)
set (CMAKE_CXX_STANDARD 11)
project (test_project)
set(VERSION 1.0.0.0)
SET(CMAKE_CXX_FLAGS "-D_GLIBCXX_USE_CXX11_ABI=0")
if (MSVC)
set(CMAKE_DEBUG_POSTFIX _d)
endif ()
find_package(JThread REQUIRED)
find_package(JRTPLIB REQUIRED)
set(NODE_LINK_LIBS "")
set(NODE_EXTERNAL_INCLUDES "")
include_directories(${CMAKE_JS_INC})
include_directories(${JTHREAD_INCLUDE_DIRS} ${JRTPLIB_INCLUDE_DIRS})
file(GLOB HEADER_FILES
"src/index.h")
file(GLOB SOURCE_FILES
"src/index.cc"
"src/export.cc")
add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES} ${CMAKE_JS_SRC})
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB} ${JTHREAD_LIBRARIES} ${JRTPLIB_LIBRARIES})
# Include Node-API wrappers
execute_process(COMMAND node -p "require('node-addon-api').include"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE NODE_ADDON_API_DIR
)
string(REGEX REPLACE "[\r\n\"]" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})
# define NPI_VERSION
add_definitions(-DNAPI_VERSION=8)
add_definitions(-DNAPI_DISABLE_CPP_EXCEPTIONS)
index.h
#ifndef INDEX_H
#define INDEX_H
#include <napi.h>
class IndexM : public Napi::ObjectWrap<IndexM>{
public:
//导出函数
static Napi::Object Init(Napi::Env env, Napi::Object exports);
static Napi::FunctionReference constructor;
IndexM(const Napi::CallbackInfo& info);
Napi::Value getValue(const Napi::CallbackInfo& info);
void setValue(const Napi::CallbackInfo& info);
private:
int m_value = 0;
};
#endif
index.cc
#include "index.h"
Napi::FunctionReference IndexM::constructor;
Napi::Object IndexM::Init(Napi::Env env, Napi::Object exports)
{
Napi::HandleScope scope(env);
Napi::Function func =
DefineClass(env,
"IndexM",
{
InstanceMethod("getValue", &IndexM::getValue),
InstanceMethod("setValue", &IndexM::setValue),
});
constructor = Napi::Persistent(func);
constructor.SuppressDestruct();
exports.Set("IndexM", func);
return exports;
}
IndexM::IndexM(const Napi::CallbackInfo& info) : Napi::ObjectWrap<IndexM>(info)
{
}
Napi::Value IndexM::getValue(const Napi::CallbackInfo& info)
{
return Napi::Number::New(info.Env(),m_value);
}
void IndexM::setValue(const Napi::CallbackInfo& info)
{
int len = info.Length();
Napi::Env env = info.Env();
if (len <= 0 || !info[0].IsNumber()) {
Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
}
Napi::Number value = info[0].As<Napi::Number>();
m_value = value.Int32Value();
}
export.cc
#include "index.h"
//导出接口
Napi::Object InitAll(Napi::Env env, Napi::Object exports) {
return IndexM::Init(env, exports);
}
NODE_API_MODULE(IndexM, InitAll)
温馨提示:
对了有个例子是线程中,调用JS回调的 typed_threadsafe_function