美文网首页
Node引入C++库文件

Node引入C++库文件

作者: 汨罗在北方 | 来源:发表于2017-09-04 20:12 被阅读119次

由于项目引入了一个通过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:

相关文章

  • Node引入C++库文件

    由于项目引入了一个通过C++语言实现的加密算法,需要在Node.js中调用相关端口实现加密,所以尝试实现了下载no...

  • 闲聊c/c++: 使用 visual c++ build too

    原因: 需要使用node.bcrypt.js库来进行文件加密。 但是该库使用c++实现。 在ubuntu中已有gc...

  • cmake 使用C++编译C

    在项目中遇到这样一种情况:项目代码是c语言写的,这时候引入了外部C++库。编译导致C++库找不到头文件。例如:#i...

  • angular如何引入第三方JavaScript类库

    如何引入第三方JavaScript类库,分几种情况: ❑如果类库的npm包中含有类型定义文件(查看node_mod...

  • 引入ffmpeg库

    引入ffmpeg库 将ffmpeg库文件及头文件拷贝到项目中 引入库文件和头文件 关闭沙箱 将ffmpeg库文件及...

  • IOS-引入库文件导致 unknown type name 'N

    引入静态库报错如下 原因: 第三方静态库可能是C OC C++文件混编,而pch里面自加的头文件是全局性的, 当在...

  • Angular开发经验总结(连载)

    引入第三方样式库文件无效(bootstrap) 尝试解决方案一 使用了cnpm安装,node_modules目录下...

  • 1.C++基础

    C++头文件 传统C头文件C++头文件hpp文件 命名空间 C++ 引入了新的概念,命名空间可以有效避免大型项目的...

  • node里面的c/c++模块

    准备工作 node使用c++插件时需要使用node-gyp包,node-gyp把c++源码编译为二进制文件,js在...

  • C/C++前向声明

    C/C++前向声明 头文件循环引用 避免引入头文件

网友评论

      本文标题:Node引入C++库文件

      本文链接:https://www.haomeiwen.com/subject/uovejxtx.html