Node引入C++库文件

由于项目引入了一个通过C++语言实现的加密算法,需要在Node.js中调用相关端口实现加密,所以尝试实现了下载node.js中引入C++库文件。
此项目中使用的引入方法是直接使用node-gym模块编译一个基于C++的node.js模块,然后在主程序中引入这个模块。

node-gym

node-gyp 是基于 GYP( 全称 Generate Your Projects,是谷歌开发的一套构建系统) 的。它会识别包或者项目中的 binding.gyp文件,这个里面是JSON的文件对工程依赖的各种文件进行了描述(可以理解为一个node版的CMakeList),然后根据该配置文件生成各系统下能进行编译的项目,如 Windows 下生成 Visual Studio 项目文件(*.sln 等),Unix 下生成 Makefile。在生成这些项目文件之后,node-gyp 还能调用各系统的编译工具(如 GCC)来将项目进行编译,得到最后的动态链接库 *.node 文件。

cpp接口文件与gym编写

插件通常都会暴漏某些对象和函数给 Node.js 中的 JavaScript 调用。当 JavaScript 调用函数时,也必须将将传入的参数映射给 C/C++ 代码,在函数调用完成后,还要映射 C/C++ 传回的返回值。
下面代码演示了如何读取 JavaScript 传递来的函数以及如何传输返回值:
C++文件如下:

// AESencrypt.cpp
#include <node.h>
//此处引入要调用的头文件
#include <aes_encrypt.h>
namespace demo {

using v8::Exception;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;

// 此处是encrypt方法的执行函数,在js中调用的参数通过args传入
void Encrypt(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  // 检查参数个数
  if (args.Length() < 3) {
    // 如果个数不正确便扔回错误到JavaScript
    isolate->ThrowException(Exception::TypeError(
        String::NewFromUtf8(isolate, "Wrong number of arguments")));
    return;
  }

  // 检查参数类型
  if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
    isolate->ThrowException(Exception::TypeError(
        String::NewFromUtf8(isolate, "Wrong arguments")));
    return;
  }
//当需要参数为string类型时的示例
     v8::String::Utf8Value param(args[2]->ToString());
     std::string inputstr= std::string(*param);

char buffer[60];
  // 执行主函数
aes_encrypt((char *)inputstr.c_str(),args[0],args[1],buffer);

  // 设定返回值 (using the passed in
  // FunctionCallbackInfo<Value>&)(返回一个字符串)
  args.GetReturnValue().Set(String::NewFromUtf8(isolate, buffer));
}

void Init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "encrypt", Encrypt);
}

NODE_MODULE(AESencrypt, Init)

}  // namespace demo

值得注意的是,开发 Node.js 插件的开发时,必须输出一个初始化函数,模式如下:

void Initialize(Local<Object> exports);
NODE_MODULE(module_name, Initialize)

在 NODE_MODULE 的行末没有分号,因为它并不是一次函数调用(详见 node.h)。module_name 必须二进制文件名相匹配(不包含文件名的 .node 后缀)。通过上述代码,我们在 AESencrypt.cpp 文件中声明了初始化函数是 Init,插件名称是 encrypt

接下来编写gym文件

{
     "targets": [
     {
         "target_name": "AESencrypt",
             "sources": [ "AESencrypt.cpp" ],
             "include_dirs": ["include"],
             "libraries": [ "<(module_root_dir)/obj/lib/libencrypt.a" ],
             "cflags!": [ "-fno-exceptions" ],
             "cflags": [ "-std=c++11","-D_FILE_OFFSET_BITS=64"],
             "cflags_cc!": [ "-fno-exceptions" ]
    }
  ]
}

其中libraries中引用库文件就好,其中一些关于跨系统的兼容可以参考官方文档

接下来执行

node-gyp configure  
node-gyp build  

编译文件生成一个.node文件

在js代码中

const AES = require('./build/Release/AESencrypt.node');

引用,然后使用AES.encrypt()调用即可

一些问题总结

  • 编译中引用静态库造成的问题
    由于编译生成的是动态库,引用的是静态库,在编译时可能弹出
make: Entering directory '/home/work/work/testAES/build'
  ACTION Regenerating Makefile
  SOLINK_MODULE(target) Release/obj.target/testAES.node
/usr/bin/ld: /home/work/work/testAES/obj/lib/libaes.a(test_aes.c.o): relocation R_X86_64_32S against `.rodata.cst16' can not be used when making a shared object; recompile with -fPIC
/home/work/work/testAES/obj/lib/libaes.a: error adding symbols: Bad value
collect2: error: ld returned 1 exit status

报错。此时需要重新加"-fPic"参数编译一遍库文件。
在cmake中需要写:

set(CMAKE_POSITION_INDEPENDENT_CODE ON)
  • 自动生成
    由于最终需要提供给用户使用,模块在不同环境下都需要重新编译一遍,而每次部署都让用户执行一次node-gyp configure build明显不现实。直接在package.json里面加上一句
gypfile": true

让每次执行npm install的时候自动编译一遍,让问题能方便很多

还可以考察的一些模块

  • node-ffi: 这个模块可以直接引入C++的库,实现不用操作任何C++代码的C++库文件引入
  • node-pre-gym:
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,527评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,314评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,535评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,006评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,961评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,220评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,664评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,351评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,481评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,397评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,443评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,123评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,713评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,801评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,010评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,494评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,075评论 2 341

推荐阅读更多精彩内容