你是不是写nodejs应用的时候,有过属于自己的业务需求,但这个需求你又找不到合适的类库,或者你这个业务需求独一无,根本不可能找到已经写好的类库
比如,你要调用一个自己写的DLL里的函数
这时候,你就需要用C++写个nodejs扩展了,但是c++又需要编译,这就需要个编译工具了
标题Nodejs扩展基本开发
按照Nodejs官方文档,编译扩展,两种方式
- node-gyp
- cmake-js
现在,分别简单介绍一下以上两种编译方式
1.node-gyp:这个gyp应该都比较熟悉,他是google的一个跨平台编译工具,比如编译chromium就需要用gyp,node-gyp就是用于nodejs扩展编译的gyp,基本上和gyp没有区别,node-gyp在写nodejs时候比较常用,比如你写sass时候如果安装了node-sass,就需要node-gyp编译
2.cmake-js:看名字也能知道,这东西大概率和cmake有关系。对,它是基于CMake来构建系统的,也能跨平台编译
以上两种方式都能编译nodejs扩展,但是从安装和使用上来讲,cmake-js比node-gyp要简单的多。
下面我来介绍一下cmake-js
cmake-js具体安装
测试环境,windows10,nodejs 12.6.3 , vs2015
1.首先你要有个nodejs环境,编译nodejs扩展没有nodejs环境,这就没法干了
2.安装cmake-js,安装很简单,npm直接安装,这有可能时间比较长,多等等
npm install -g cmake-js
3.安装cmake,如果你的用的cmake安装包的话,正常安装就行,啥都不用管,如果你用的压缩包的话,把他解压以后,打开这个文件夹
里面差不多就这些东西,要是你的文件和我的不一样,也无所谓,可能是版本差异,把这个路径复制一下,然后选中
我的电脑右键->属性->高级系统设置->环境变量->系统变量,然后点开path这个选项
然后点新建
把cmake那个bin目录路径写进去就行了
这个弄完,打开cmd,输入cmake,回车,输出如下
如果你看不见上面的输出,要么就是你的环境变量路径没有配对,要么就是环境变量没有生效,如果是环境变量没有生效的话,可能需要重启电脑
4.vs编译器,具体什么版本,要看看你安装的 cmake支持什么版本,理论上你能下载到的VS版本他应该都支持,如果要确认的话,打开cmake的bin目录,点击cmake-gui.exe,然后点击generate,再选下拉列表看看
以上,准备工作完成
camke-js具体使用
先创建package.json
npm init
创建好文件后,打开package.json,把下面代码复制到里面
"dependencies": {
"node-addon-api": "^3.0.0"
},
"cmake-js": {
"runtime": "node",
"runtimeVersion": "12.16.3",
"arch": "x64"//64位
}
这两个段很重要
修改好以后,然后用npm安装node-addon-api
npm i
这个下载很快,一下就好了
然后编写个CMakeLists.txt,你要是写过Cmake的话就很简单,下面是一个最简单的CMakeLists,直接复制出来用就可以
project (aaaa)
cmake_minimum_required(VERSION 3.16)
include_directories(${CMAKE_JS_INC})
file(GLOB SOURCE_FILES "*.cc")
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})
# Include N-API wrappers
execute_process(COMMAND node -p "require('node-addon-api').include"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE NODE_ADDON_API_DIR
)
string(REPLACE "\n" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
string(REPLACE "\"" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})
target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})
# Define NAPI_VERSION
add_definitions(-DNAPI_VERSION=3)
project (aaaa)是我随便起了个项目名称aaaa,你随便改
然后就是重点了,要写c++代码了,创建a.cc文件,内容如下
#include <assert.h>
#include <node_api.h>
#include <vector>
#include <Windows.h>
using namespace std;
static napi_value MyFun(napi_env env, napi_callback_info info) {
napi_status status;
napi_value str;
status = napi_create_string_utf8(env, "mytest", 6, &str);
assert(status == napi_ok);
return str;
}
static napi_value YouFun(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc = 2;
napi_value args[2];
status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
size_t strleng;
napi_get_value_string_utf8(env, args[0], 0, 0, &strleng);
string p1;
p1.reserve(strleng + 1);
p1.resize(strleng);
status = napi_get_value_string_utf8(env, args[0], &p1[0], p1.capacity(), nullptr);
napi_get_value_string_utf8(env, args[1], 0, 0, &strleng);
string p2;
p2.reserve(strleng + 1);
p2.resize(strleng);
status = napi_get_value_string_utf8(env, args[1], &p2[0], p2.capacity(), nullptr);
napi_value v;
string dest = "p1:"+ p1 + "p2:" + p2;
napi_create_string_utf8(env,dest.c_str(), strlen(dest.c_str()+1), &v);
return v;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, 0, func, 0, 0, 0, napi_default, 0 }
static napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_property_descriptor mytest = DECLARE_NAPI_METHOD("mytest", MyFun);
status = napi_define_properties(env, exports, 1, &mytest);
napi_property_descriptor youtest = DECLARE_NAPI_METHOD("youtest", YouFun);
status = napi_define_properties(env, exports, 1, &youtest);
assert(status == napi_ok);
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
上面代码很简单,就是创建了两个函数,第一个函数名叫mytest,第二个函数名叫youtest,
第一个函数的功能就是输出字符串“mytest”,
第二个函数的功能就是输入两个字符串参数,然后输出p1:xxx,p2:xxx
都完事以后,就是执行编译了,执行cmd,进入你的工作目录,输入
cmake-js build
等他执行完,如果执行正确的话,你会发现工作目录中多了一个build文件夹,里面是VS项目,同时build/Release文件夹中有了aaaa.node文件,这就是你编译的nodejs扩展了
然后就是调用了,写个JS 文件,取名a.js,内容如下
var addon = require("./build/Release/aaaa.node");
console.log(addon.mytest());
console.log(addon.youtest('aaa','bbb'));
然后执行node调用它
node a.js
正确输出,应该可以看到如下
关于调试
程序肯定需要调试,怎么调试呢?
打开Build文件夹,用VS把项目文件打开,就是一个普通的VS项目,你也可以在这里改代码,然后编译
然后把aaaa项目,设为启动项目,在右键点击项目->属性->调试
按上面这么填写,然后F5就可以调试了
结束语
nodejs扩展,不仅可以用于nodejs服务器环境,还可以用于electron桌面开发,用法都一样
nodejs扩展开发也不太难,但是它API也不少,要写扩展还是要多看看API才行