evpp接入到nodejs
一、使用yeoman 生成器 创建下一代 Node 原生模块的 N-API
1. 安装 Yeoman 和 generator-napi-module (我们假设已经预装了node.js)
npm install -g yo
npm install -g generator-napi-module
2. 创建工程目录
$ mkdir -p evpp_module && cd evpp_module
3. 创建工程(yo napi-module)
生成ts版本的: Would you like to generate TypeScript wrappers for your module? Yes
evpp_module$ yo napi-module
_-----_ ╭──────────────────────────╮
| | │ Welcome to the │
|--(o)--| │ bedazzling N-API module │
`---------´ │ generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
package name: (evpp_module)
version: (1.0.0)
description: evpp module
git repository:
keywords:
author:
license: (ISC)
About to write to /data/gocpplua/gocpplua_node/mylearn/proj/napi_demo_evpp/evpp_module/package.json:
{
"main": "lib/binding.js",
"dependencies": {
"node-addon-api": "^1.1.0"
},
"scripts": {
"test": "node --napi-modules ./test/test_binding.js"
},
"gypfile": true,
"name": "evpp_module",
"version": "1.0.0",
"description": "evpp module",
"author": "",
"license": "ISC"
}
Is this OK? (yes) yes
? Choose a template Object Wrap
? Would you like to generate TypeScript wrappers for your module? Yes
Updated package.json to support TypeScript
create binding.gyp
create lib/binding.ts
create src/evpp_module.cc
create src/evpp_module.h
create test/test_binding.js
create tsconfig.json
> evpp_module@1.0.0 install /data/gocpplua/gocpplua_node/mylearn/proj/napi_demo_evpp/evpp_module
> node-gyp rebuild
make: Entering directory '/data/gocpplua/gocpplua_node/mylearn/proj/napi_demo_evpp/evpp_module/build'
CC(target) Release/obj.target/nothing/node_modules/node-addon-api/src/nothing.o
AR(target) Release/obj.target/node_modules/node-addon-api/src/nothing.a
COPY Release/nothing.a
CXX(target) Release/obj.target/evpp_module-native/src/evpp_module.o
SOLINK_MODULE(target) Release/obj.target/evpp_module-native.node
COPY Release/evpp_module-native.node
make: Leaving directory '/data/gocpplua/gocpplua_node/mylearn/proj/napi_demo_evpp/evpp_module/build'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN evpp_module@1.0.0 No repository field.
added 3 packages from 54 contributors in 2.242s
4. 生成后的目录结构
.
├── binding.gyp
├── build // 通过 node-gyp configure 自动生成,可删
│ ├── binding.Makefile
│ ├── config.gypi
│ ├── evpp_module-native.target.mk
│ ├── Makefile
│ ├── node_modules
│ └── Release
├── lib
│ └── binding.ts
├── node_modules // 通过npm install 自动生成,可删
│ ├── node-addon-api
│ ├── @types
│ └── typescript
├── package.json
├── package-lock.json
├── src
│ ├── evpp_module.cc
│ └── evpp_module.h
├── test
│ └── test_binding.js
└── tsconfig.json
二、构建基础项目
$ npm test
> evpp_module@1.0.0 pretest /data/gocpplua/gocpplua_node/mylearn/proj/napi_demo_evpp/evpp_module
> tsc
node_modules/@types/node/index.d.ts:20:1 - error TS1084: Invalid 'reference' directive syntax.
20 /// <reference lib="es2016" />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! Test failed. See above for more details.
虽然出现error,但是不影响。 还是会生成 dist/binding.js。
如果想要修改,那么删除 node_modules,然后package.json中,将typescript修改如下后,再安装依赖包npm install:
"typescript": "^4.3.5"
三、 运行
$ node test/test_binding.js
Hello kermit
I am mr-yeoman
Tests passed- everything looks OK!
四、引入evpp(提前是已经编译好evpp,查看/usr/local/lib/libevpp.so)
1. 修改 evpp_module.cc
- 1.1 添加:
#include <evpp/event_loop.h>
void Print(){
evpp::EventLoop loop;
std::cout << "evpp" << std::endl;
}
- 1.2 EvppModule::Greet 中调用
printf("Hello %s\n", name.Utf8Value().c_str());
printf("I am %s\n", this->_greeterName.c_str());
Print(); // 加入的是这行
return Napi::String::New(env, this->_greeterName);
2.修改 binding.gyp( 如下注释点1,2,3 )
{
'targets': [
{
'target_name': 'evpp_module-native',
'sources': [ 'src/evpp_module.cc' ],
'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],
'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],
'link_settings': { # 1. 添加evpp动态库引用
'library_dirs': ["/usr/local/lib"],
'libraries': ['-levpp'],
},
'cflags!': [ '-fno-exceptions', '-fno-rtti' ], # 2. 添加:'-fno-rtti', 解决cannot use typeid with -fno-rtti
'cflags_cc!': [ '-fno-exceptions', '-fno-rtti' ], # 3. 添加:'-fno-rtti', 解决cannot use typeid with -fno-rtti
'xcode_settings': {
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
'CLANG_CXX_LIBRARY': 'libc++',
'MACOSX_DEPLOYMENT_TARGET': '10.7'
},
'msvs_settings': {
'VCCLCompilerTool': { 'ExceptionHandling': 1 },
}
}
]
}
3. 编译
$ node-gyp build
gyp info it worked if it ends with ok
gyp info using node-gyp@3.0.3
gyp info using node@4.2.6 | linux | x64
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
make: Entering directory '/data/gocpplua/gocpplua_node/mylearn/proj/napi_demo_evpp/evpp_module/build'
ACTION Regenerating Makefile
make: Nothing to be done for 'all'.
make: Leaving directory '/data/gocpplua/gocpplua_node/mylearn/proj/napi_demo_evpp/evpp_module/build'
gyp info ok
4. 运行
可以看到打印了我们加入的代码:evpp
$ node test/test_binding.js
WARNING: Logging before InitGoogleLogging() is written to STDERR
I0909 16:19:23.865659 3207 inner_pre.cc:27] ignore SIGPIPE
Hello kermit
I am mr-yeoman
I0909 16:19:23.867280 3207 event_loop.cc:11] evpp::EventLoop::EventLoop() this=0x7ffe46556ca0
I0909 16:19:23.867475 3207 event_loop.cc:56] void evpp::EventLoop::Init() this=0x7ffe46556ca0
evpp <------- 这个就是我加入的代码
I0909 16:19:23.867569 3207 event_loop.cc:43] evpp::EventLoop::~EventLoop() this=0x7ffe46556ca0
Tests passed- everything looks OK!
5. 在test_binding.js中添加定时器,脚本不退出:
setInterval(()=>{
const instance = new EvppModule("cc");
instance.greet("qqqqq") // 每个一段时间就打印
}, 5000)
五、源码
github -> mylearn/proj/napi_demo_evpp