node.js调用C++函数

c/c++

浏览数:283

2019-3-28

新手写的不好勿喷
要想node.js调用C++的函数等,须先将C++代码编译成二进制的.node文件。node.js官方文档https://nodejs.org/dist/lates… 中的C++ addons介绍了如何将C++的代码编译为二进制的.node文件。
一、步骤:
1.首先在项目目录进行npm install -g node-gyp下载node-gyp模块,配置环境参考https://github.com/nodejs/nod…
2.这是node官方文档中的例子

// addon.cc
#include <node.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;// This is the implementation of the "add" method// Input arguments are passed using the// const FunctionCallbackInfo<Value>& args struct
void Add(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  // Check the number of arguments passed.
  if (args.Length() < 2) {
    // Throw an Error that is passed back to JavaScript
    isolate->ThrowException(Exception::TypeError(
        String::NewFromUtf8(isolate, "Wrong number of arguments")));
    return;
  }
  // Check the argument types
  if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
    isolate->ThrowException(Exception::TypeError(
        String::NewFromUtf8(isolate, "Wrong arguments")));
    return;
  }
  // Perform the operation
  double value = args[0]->NumberValue() + args[1]->NumberValue();
  Local<Number> num = Number::New(isolate, value);
  // Set the return value (using the passed in
  // FunctionCallbackInfo<Value>&)
  args.GetReturnValue().Set(num);}
void Init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "add", Add);}NODE_MODULE(NODE_GYP_MODULE_NAME, Init)
}  // namespace demo

3.然后在项目目录下使用类似JSON的格式创建在项目顶层调用的文件binding.gyp文件,内容为

{
  "targets": [
    {
      "target_name": "addon",
      "sources": [ "addon.cc" ]
    }
  ]
}

4.在终端输入node-gyp configure命令生成一个build文件夹,然后输入node-gyp build命令生成编译addon.node文件
5.在node文件比如test.js文件中const addon=require(‘./build/Release/addon’)调用生成的模块

// test.js
const addon = require('./build/Release/addon');
console.log('This should be eight:', addon.add(3, 5));//结果为8

二、实例

最近公司让我研究node调用C++,C++的代码是调用了GDAL库开发的功能。要在tile.cc文件中调用头文件


这里#include调用的gdal_priv.h和ogrsf_frmts.h头文件在gdal/include文件夹中,所以要在binding.gyp文件中source后面添加

      "include_dirs": [
        "./gdal/include"
      ],

然后如果现在就运行node-gyp configure build命令会报“无法解析的外部符号”的错误,这是因为还需要加入调用的链接库,需要在binding.gyp文件中加入

      'libraries': [
         "../gdal/lib/gdal_i.lib",
      ],

这时的binding.gyp文件为

{
  "targets": [
    {
      "target_name": "addon",
      "sources": [
        "./C++_02/tile.cc"
      ],
      "include_dirs": [
        "./gdal/include"
      ],
      'libraries': [
         "../gdal/lib/gdal_i.lib",
      ],
    }
  ]
}

这时再进行node-gyp configure build命令就不会报错生成addon.node文件,但是当我运行test.js文件

const addon=require(‘./build/Release/addon’)
var imagefile = "/vsicurl/http://sasmac.oss-cn-beijing.aliyuncs.com/cog.tif";
var x = 160;
var y = 83;
var l = 9;
console.log(addon.tileload(imagefile, x, y, l));

会报错’找不到指定的模块’,但是我们在build/Release文件中能找到addon.node文件,这是因为缺少依赖也就是缺少.dll。下载 Dependency Walker,这个软件可以帮你确定一下缺少什么.dll,下载地址:http://www.dependencywalker.com/。我将addon.node文件添加到Dependency Walker发现缺少gdal/bin中的.dll。我将gdal/bin中的.dll文件复制到addon.node目录下,这时运行test.js文件就可以正常使用了。