目录
JS调用C++的两种方式:node-ffi、C++拓展插件。
一、node-ffi模块
node-ffi 对不了解C++的同学很友好。操作简单,npm install ffi搭建好环境就好了。缺点是只支持C形式的接口。
二、C++拓展插件
C++拓展插件需要C++的知识,适合兼任C++工程师的同学来搞,功能强大。
1.hello world入门
先写个简单的helloword调用。
第一步 先写配置文件binding.gyp
{
"targets": [
{
"target_name": "test",
"sources": [ "test.cc" ]
}
]
}
第二步 test.js文件
var test = require('./build/Release/test');
test.hello('test', function(data) {
console.log(data);
});
第三步 test.cc文件
#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);
文件准备好就可以编译了,先进到代码根目录
执行node-gyp config 生成build目录,而且这时已经能够看到已经有了VS的一个C++的项目了。
执行node-gyp build 就在build/release目录下生成了test.node文件了
现在node test.js就会发现js调到C++了。
2.开发延伸
在第一步完成后我们就可以做项目开发了。毕竟我们的项目不可能是一个helloword吧。
网上有好多方法是还是配置binding.gyp文件,这个没必要太麻烦了。既然第一步已经生成了VS的C++工程项目了,那我们就按照我们C++的正常开发流程来就好了。
我的做法是把我的C++项目做成动态库,第一步生成的VS项目相当于加了一次外壳。在这个外壳项目中用V8的方法导出C++的接口。
不同语种的混合编程最主要的就是两点,一是接口的导出,二是参数的转换。搞明白这两点后就是时间问题了。
参数转换要是嫌google筛选信息麻烦就直接去v8头文件找相应的接口。
贴两个参考地址
node.js的中文网(大神请直接看英文):http://nodejs.cn/api/addons.html
感谢大哥的helloword: https://www.jianshu.com/p/857b4d38aba1
感谢大哥整理的参数转换:https://blog.csdn.net/youth0532/article/details/74721247