简介
插件使用 C++ 编写的动态链接共享对象。 require()
函数可以将插件加载为普通的 Node.js 模块。 插件提供了 JavaScript 和 C/C++ 库之间的接口。
与在此之前主流的ffi,nan,V8,libuv 不一样的是 Node-API 具有超强的兼容性(在node8.0以上) ,可以无需重新编译就能在electron
上运行,有优势就必有劣势 由于NAPI与node内部使用的C++函数支持是一致的,因此编写时候便需要使用严格的类型进行编写;
起步
- 工欲善其事必先利其器
安装必要的支持
- Visual Studio
- 安装node-gyp
npm install -g node-gyp
- 配置头文件位置包含路径 (不设置也能编译 只是为了让IDE可检查)
2.创建你的NAPI项目
mkdir helloNapi & cd helloNapi
npm init -f
3.设置插件编译目标和模块入口文件
- 创建以下文件
-
- binding.gyp
-
- index.js
-
- mian.cpp (C语言:
mian.c
, C++:mian.cpp
,mian.cc
)
- mian.cpp (C语言:
- binding.gyp 内容
"targets": [
{
"target_name": "helloNapi",
"conditions": [
['OS=="win"', {
"sources": ["mian.cpp" ],
'msvs_settings': {
'VCCLCompilerTool': {
'AdditionalOptions': [
'/W3',
'/Qspectre',
'/guard:cf'
]
},
'VCLinkerTool': {
'AdditionalOptions': [
'/guard:cf'
]
}
},
}]
]
}
]
}
- index.js 内容
module.exports = require("./build/Release/helloNapi.node");
- mian.cpp
#include <node_api.h>
// 实际暴露的方法,这里只是简单返回一个字符串
napi_value HelloMethod(napi_env env, napi_callback_info info)
{
napi_value world;
napi_create_string_utf8(env, "hello world!", 12, &world);
return world;
}
// 开始暴露模块
static napi_value Init(napi_env env, napi_value exports)
{
napi_property_descriptor BIND_NAPI_METHOD[] = {
{"HelloMethod", 0, HelloMethod , 0, 0, 0, napi_default, 0}
};
napi_define_properties(env, exports, sizeof(BIND_NAPI_METHOD) / sizeof(BIND_NAPI_METHOD[0]), BIND_NAPI_METHOD);
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init);
编译你的c++模块
node-gyp rebuild
-
编译命令
-
开始编译
-
编译成功
使用你的c++模块
// 导入模块
let hello = require("./helloNapi");
console.log(hello.HelloMethod());
让代码更好写的模块进阶
- 导出简化
//原来 导出函数时候需要使用json提交 重复度过高并不友好
napi_property_descriptor BIND_NAPI_METHOD[] = {
{"HelloMethod", 0, HelloMethod , 0, 0, 0, napi_default, 0}
};
//优化(使用宏)
// 导出类型是一个函数
#define DECLARE_NAPI_METHOD(name, func) \
{ \
name, 0, func, 0, 0, 0, napi_default, 0 \
}
//暴露方式
napi_property_descriptor BIND_NAPI_METHOD[] = {
DECLARE_NAPI_METHOD("HelloMethod", HelloMethod),
};
- 简化 文本转node文本 过程
- 添加头声明
#include <string>
#include <stdio.h>
#include <windows.h>
using namespace std;
// 配置 win-api字符自适应
#ifdef UNICODE
typedef LPWSTR LPTSTR;
typedef LPCWSTR LPCTSTR;
#else
typedef LPSTR LPTSTR;
typedef LPCSTR LPCTSTR;
#endif
- 变更文本转node文本函数
/**
* @brief 将文本变成node支持的utf8文本类型
*
* @param env
* @param SetString
* @return napi_value
*/
napi_value _create_String(napi_env env, string SetString)
{
napi_value Results;
napi_create_string_utf8(env, SetString.c_str(), NAPI_AUTO_LENGTH, &Results);
return Results;
}
// 原来返回文本编写:
napi_value HelloMethod(napi_env env, napi_callback_info info)
{
napi_value world;
napi_create_string_utf8(env, "world", 5, &world);
return world;
}
// 新的返回方式返回
napi_value HelloMethod(napi_env env, napi_callback_info info)
{
return _create_String(env,"world");
}
-
支持中文 文本返回
-
导出一个文本类型的内容
// 导出类型是一个文本类型
#define ADD_NAPI_METHOD_Str_VALUE(name, value) \
{ \
name, 0, 0, 0, 0, _create_String(env, value), napi_default, 0 \
}
//使用:
// ADD_NAPI_METHOD_Str_VALUE ("version", "helloNapi@1.0.00")
napi_property_descriptor BIND_NAPI_METHOD[] = {
ADD_NAPI_METHOD_Str_VALUE("version", "helloNapi@1.0.00"),
DECLARE_NAPI_METHOD("HelloMethod", HelloMethod),
};
看看效果