【发布时间】:2014-01-10 18:28:28
【问题描述】:
这就是我的问题的全部内容,真的,但我认为回答这个问题很有趣。
【问题讨论】:
标签: c++ node.js go node.js-addon
这就是我的问题的全部内容,真的,但我认为回答这个问题很有趣。
【问题讨论】:
标签: c++ node.js go node.js-addon
node.js 的原生模块必须与 V8 进程深度交互,其中包含很多 v8 概念,例如 gc、javascript 上下文、...
而且我认为 V8 没有公开兼容且稳定的 API 供其他语言与之交互。这就是为什么 node.js 原生插件应该使用 C++ 构建并始终导入 V8 C++ 标头。
但是你可以通过用 C++ 包装 GO 代码来使用 GO 编写 node.js 原生插件:
文件:module.go
package main
func Add(a, b int) int {
return a + b
}
文件:module.c
#include <node.h>
#include <v8.h>
using namespace v8;
extern int go_add(int, int) __asm__ ("example.main.Add");
void init(Handle<Object> exports) {
// call go_add
}
NODE_MODULE(module, init)
更多关于“如何从 C/C++ 调用 GO 函数”:
编辑:
请查看@jdi cmets 和链接:https://groups.google.com/forum/#!msg/golang-nuts/FzPbOwbTlPs/dAJVWQHx6m4J
Quote: 它可能适用于简单的事情,比如 add (不产生垃圾或需要运行时),但据我所知,任何一个编译器都不支持(目前)。部分工作是针对 linux 完成的(参见 golang.org/issue/256),但还有许多悬而未决的问题(加载两个共享对象时会发生什么?等等)
【讨论】:
main条目编译一个c程序。
只是为了重新发布这个作为答案而不是评论......
我跟进了 golang-nuts 邮件列表,了解支持用 Go 为其他语言编写扩展。回复来源can be found here。
对于像 add (不生成 垃圾或需要运行时),但(尚)不支持 据我所知,无论是编译器。部分工作是为 linux 完成的 (请参阅golang.org/issue/256),但有许多未解决的问题 (当你加载两个共享对象时会发生什么?等等)
所以说真的,用 Go 编写扩展似乎没有多大意义,然而,因为大多数语言功能都不可用,而且你已经在 C/C++ 领域添加包装器入口点。
【讨论】:
随着在 go 中添加对共享库的支持,这现在是可能的。
calculator.go:
// package name: calculator
package main
import "C"
//export Sum
func Sum(x, y float64) float64 {
return x + y
}
func main() {
}
node-calculator.cc:
#include "calculator.h"
#include <node.h>
namespace calc {
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;
using v8::Number;
using v8::Exception;
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
Local<Number> num = Number::New(isolate, Sum(args[0]->NumberValue(), args[1]->NumberValue()));
// 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(calculator, init)
}
binding.gyp:
{
"targets": [
{
"target_name": "node-calculator",
"sources": [
"node-calculator.cc"
],
"libraries": [
"../calculator.a"
],
},
],
}
test.js:
const calculator = require('./build/Release/node-calculator');
console.log('4+5=', calculator.add(4, 5));
构建:
go build -buildmode c-archive -o calculator.a calculator.go
node-gyp configure
node-gyp build
输出:
#> node test.js
4+5= 9
【讨论】:
ld: warning: ignoring file ../calculator.a, file was built for archive which is not the architecture being linked (x86_64): ../calculator.a