现在electron应用是越来越多,有时需要在electron中使用c++代码,这种情况怎么办呢?据我知道的方法就有以下几种
1、webassembly
2、ffi-napi
3、addons
这几种方式,我都算是尝试过了,各有优劣,webassembly的api限制比较多,反正是无法调用操作系统的api,这点比较遗憾,不过标准的c++还是支持的,ffi-napi直接调用dll或者so库,封装的其实挺不错的,算是很好用的了,对于c/c++和nodejs分工开发尤其适用,而addons则是通过node-gyp编译c/c++生成系统先关的xxx.node文件以供js调用,这篇文章就来说说addons方式的实现。
1、项目组成
生成addons的项目一般只是由一个xx.cc的c++源文件以及一个binding.gyp的node-gyp编译文件组成,比如在我的addons-demo中项目结构如下
- demo
- a.js
- src
- init.cc
- binding.gyp
- index.js
- package.json
其中要用来编译生成sum.node的两个核心文件只需要init.cc以及binding.gyp两个文件就行了,其中binding.gyp文件内容如下
{
'targets': [
{
'target_name': 'sum',
'include_dirs': [
"<!(node -e \"require('nan')\")"
],
'sources': [
'src/init.cc'
]
}
]
}
这里的target_name指的是生成sum.node的node文件,而sources中指定要编译的源文件,也就是init.cc
2、编译生成sun.node文件
要编译生成node文件,只需要执行yarn install命令,而这个命令在package.json中定义
{
"name": "sum-addon",
"version": "1.0.1",
"description": "",
"main": "index.js",
"scripts": {
"install": "node-gyp rebuild",
"rebuild": "node-gyp rebuild",
"rebuild:dev": "node-gyp rebuild --debug",
"clean": "node-gyp clean",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"nodejs",
"c++",
"addon"
],
"author": "dingwenjiang",
"license": "ISC",
"dependencies": {
"nan": "^2.12.1"
}
}
从package.json源码可见,实际执行的是node-gyp rebuild命令,node-gyp会根据当前目录下的binding.gyp去编译源码,生成对应的sum.node,而这里的nan依赖包,它的全称为Native Abstraction for Node.js, 其表现上是一个Node.js包。安装后,就得到一堆C++头文件,里面是一堆宏。它主要为Node.js和V8跨版本提供了封装的宏,使得开发者不用关心各个版本之间的API的差异,关于nan可以参考用 NAN 写一个 nodejs 的 C++ 扩展这篇文章,写的很好了,实际上我这边博文也是在这个文章基础上进行扩展的。
编译后会在./build/Release/sum.node路径下找到对应node,而要使用只需要./demo目录下执行如下命令即可调用sum.node
node a.js
3、init.cc的说明
为了说明addons支持对系统api的调用,我在init.cc中添加了一个copy函数,就是往系统剪贴板中写入一个"helloworld"的字符串,其代码如下
NAN_METHOD(copy)
{
Nan::HandleScope scope;
HWND hWnd = NULL;
HANDLE hHandle;
OpenClipboard(hWnd);
struct stat buffer;
EmptyClipboard();
hHandle = GlobalAlloc(GMEM_FIXED, 1000);
char *pData = (char *)GlobalLock(hHandle);
char* hello = "helloworld";
strcpy(pData, hello);
SetClipboardData(CF_TEXT, hHandle);
GlobalUnlock(hHandle);
CloseClipboard();
}
经测试,的确可用,这说明了addons的确是支持操作系统api调用的,这一点很大程度上提升了我们再选则electron作为桌面应用开发框架的信心,实际上ffi-napi本质上也是通过addons的实现,只不过作者把addons的实现给我封装好了,我们只需要通过ffi-napi的接口调用动态链接库就行了,不过通过addons的实现,可以加深我们对nodejs中调用c/c++过程的理解
4、 参考文件
1、用 NAN 写一个 nodejs 的 C++ 扩展
2、Node.js v12.20.1 Documentation addons