nodejs调用c++程序测试代码

本文介绍如何使用 Node.js 和 C++ 开发插件,包括环境搭建、编写 C++ 源文件、构建模块及调用示例。演示了不同版本 Node.js 下的实现差异,并提供了类型判断和转换的方法。

运行环境:

Ubuntu 12.04

node-gyp v3.3.1

Python 2.7.3 

gcc 4.6.3

make 3.81

node v0.10.37

binding.gyp(注意:不是building)

{
  "targets": [
    {
      "target_name": "add",
      "sources": [ "add.cc" ]
    }
  ]
}
add.cc
#define BUILDING_NODE_EXTENSION
#include <node.h>

using namespace v8;

Handle<Value> hello(const Arguments& args) {
  HandleScope scope;
  return scope.Close(String::New("hello,world"));
}

Handle<Value> myConcat(const Arguments& args) {
  HandleScope scope;

  if (args.Length() < 2 || !args[0]->IsString()) {
    return ThrowException(Exception::TypeError(
      String::New("Wrong arguments")));
  }

  Local<Function> cb = Local<Function>::Cast(args[1]);
  const unsigned argc = 1;
  Local<Value> argv[argc] = {
    String::Concat(Local<String>::Cast(args[0]), String::New(" myConcat"))
  };

  cb->Call(Context::GetCurrent()->Global(), argc, argv);

  return scope.Close(Undefined());
}

Handle<Value> add(const Arguments& args) {
  HandleScope scope;
  if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber()) {
    return ThrowException(Exception::TypeError(
      String::New("Wrong arguments")));
  }
  
  int32_t sum = args[0]->ToInteger()->Value() + args[1]->ToInteger()->Value();

  return scope.Close(Integer::New(sum));
}

void RegModule(Handle<Object> target){

  target->Set(String::NewSymbol("hello"),
      FunctionTemplate::New(hello)->GetFunction());

  target->Set(String::NewSymbol("myConcat"),
      FunctionTemplate::New(myConcat)->GetFunction());

  target->Set(String::NewSymbol("myAdd"),
      FunctionTemplate::New(add)->GetFunction());
}

//moduleName, RegisterModuleFunctionName
NODE_MODULE(add, RegModule);
test.js

var test = require('./build/Release/add');

var str = test.hello();
console.log(str);

test.myConcat('nodejs', function(data) {
  console.log(data);
});

console.log("2+3="+test.myAdd(2,3));

编译运行:

node-gyp configure build

node test.js

结果:

hello,world
nodejs myConcat
2+3=5

注意有些版本代码则是这样的:

下面代码则在如下环境运行成功

Ubuntu 14.04.1 LTS

node-gyp v3.3.1

Python 2.7.6

gcc 4.8.2

make 3.81

node v5.2.0

#include <node.h>
#include <v8.h>

using namespace v8;

// 传入了两个参数,args[0] 字符串,args[1] 回调函数
void hello(const FunctionCallbackInfo<Value>& args) {
  // 使用 HandleScope 来管理生命周期
  Isolate* isolate = Isolate::GetCurrent();
  HandleScope scope(isolate);

  // 判断参数格式和格式
  if (args.Length() < 2 || !args[0]->IsString()) {
    isolate->ThrowException(Exception::TypeError(
      String::NewFromUtf8(isolate, "Wrong arguments")));
    return;
  }

  // callback, 使用Cast方法来转换
  Local<Function> callback = Local<Function>::Cast(args[1]);
  Local<Value> argv[1] = {
    // 拼接String
    String::Concat(Local<String>::Cast(args[0]), String::NewFromUtf8(isolate, " world"))
  };
  // 调用回调, 参数: 当前上下文,参数个数,参数列表
  callback->Call(isolate->GetCurrentContext()->Global(), 1, argv);
}

// 相当于在 exports 对象中添加 { hello: hello }
void init(Handle<Object> exports) {
  NODE_SET_METHOD(exports, "hello", hello);
}

// 将 export 对象暴露出去
// 原型 `NODE_MODULE(module_name, Initialize)`
NODE_MODULE(test, init);

类型判断
Local<Value> arg = args[0];
bool isArray = arg->IsArray();
bool isBoolean = arg->IsBoolean();
bool isNumber = arg->IsNumber();
bool isInt32 = arg->IsInt32();
类型转换
Local<Value> arg = args[0];
Local<Object> = arg->ToObject();
Local<Boolean> = arg->ToBoolean();
Local<Number> = arg->ToNumber();
Local<Int32> = arg->ToInt32 ();
Local<Function> callback = Local<Function>::Cast(args)

### 如何在 Node.js 中加载并使用 C++ 编写的 DLL 文件 #### 使用 `node-ffi` 加载和调用动态链接库 (DLL) 为了能够在 Node.js 应用程序中加载并使用由 C++ 编写而成的 DLL 文件,可以采用名为 `node-ffi` 的工具包来完成这项工作。此工具使得利用纯 JavaScript 调用本地函数成为可能,并且简化了与外部二进制接口交互的过程[^1]。 安装必要的 npm 包: ```bash npm install ffi-napi ref-napi ``` 下面是一份简单的例子,展示了怎样通过 `node-ffi` 来访问一个假设存在的 C++ 函数 `addNumbers(int, int)` 并执行加法操作: ```javascript const ffi = require('ffi-napi'); const ref = require('ref-napi'); // 定义参数类型映射表以便正确传递给C++ let typesMapping = { 'int': ref.types.int, }; // 创建指向dll文件的对象实例 let myDll = new ffi.Library('./path/to/your/cpp_dll', { "addNumbers": ['int', [typesMapping['int'], typesMapping['int']]] }); console.log(myDll.addNumbers(5, 7)); // 输出应为:12 ``` 这段代码片段说明了几个要点: - 需要引入两个主要依赖项——`ffi-napi` 和 `ref-napi`;前者提供了 FFI 功能而后者帮助管理数据类型的转换。 - 当创建一个新的 Library 实例时,第一个参数是要加载的目标 dll 文件路径,第二个则是对象字面量形式的方法签名列表,其中键名对应于导出方法名称,值则表示返回值及其接受输入参数的数据类型数组。 - 对于每种预期传入或传出的数据类型,在定义这些方法之前都应当先准备好相应的映射关系。 #### 注意事项 当尝试集成现有的 C++ DLL 到基于 Node.js 构建的应用当中去时,请注意以下几点建议: - **确保 ABI 兼容性**:确认所使用的平台架构(比如 Windows 上 x86 或者 x64)与目标 DLL 是一致的,因为不同体系结构下的应用程序二进制接口可能会有所差异[^3]。 - **理解内存管理和生命周期**:由于涉及到两种不同的编程环境之间的互操作,因此对于资源分配、释放以及异常处理等方面要有清晰的认识,防止潜在的风险如内存泄漏等问题的发生。 - **掌握基本的 C/C++ 知识**:尽管可以直接从 JS 层面上发起对原生 API 的请求,但对于那些底层细节的理解仍然是不可或缺的一部分,特别是在调试阶段更是如此。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值