evpp接入到nodejs
发布于 12 天前 作者 gocpplua 776 次浏览 来自 分享

一、使用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

2 回复
回到顶部