C++ 是否可以在Go中编写原生Node.js扩展,而不是C++;?

C++ 是否可以在Go中编写原生Node.js扩展,而不是C++;?,c++,node.js,go,node.js-addon,C++,Node.js,Go,Node.js Addon,这就是我的问题的全部,真的,但我认为这是一个有趣的回答。node.js的本机模块必须与包含许多V8概念(如gc、javascript上下文等)的V8进程进行深入的交互 我认为V8没有为其他语言提供兼容和稳定的API来与之交互。这就是为什么No.js原生插件应该用C++构建,并且总是导入V8C++头。 但您可以使用GO编写node.js本机插件,方法是使用C++包装GO代码: 文件:module.go package main func Add(a, b int) int { retu

这就是我的问题的全部,真的,但我认为这是一个有趣的回答。

node.js的本机模块必须与包含许多V8概念(如gc、javascript上下文等)的V8进程进行深入的交互

我认为V8没有为其他语言提供兼容和稳定的API来与之交互。这就是为什么No.js原生插件应该用C++构建,并且总是导入V8C++头。
但您可以使用GO编写node.js本机插件,方法是使用C++包装GO代码:

文件: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)
#包括
#包括
使用名称空间v8;
extern int go_add(int,int)_asm__(“example.main.add”);
void init(句柄导出){
//呼叫go_添加
}
节点_模块(模块,初始化)
有关“如何从C/C++调用GO functionn”的更多信息:


编辑:

请参阅@jdi评论和链接:


Quote:对于像add这样的简单事情(不产生垃圾或不需要运行时)来说,它可能是可行的,但据我所知,这两个编译器都不支持它。部分工作是针对linux完成的(请参见golang.org/issue/256),但还有一些开放性问题(加载两个共享对象时会发生什么情况?等等)

只是将其作为答案而不是评论重新发布

我跟进了golang nuts邮件列表中关于支持用Go为其他语言编写扩展的内容。回应的来源

对于像add(不生成 垃圾或需要运行时),但不受 据我所知,这两个编译器都有。部分工作是针对linux完成的 (请参阅),但还有一些悬而未决的问题 (加载两个共享对象时会发生什么情况?等等)


因此,实际上,在Go中编写扩展似乎没有多大意义,但是,大多数语言功能都不可用,而且您已经在C/C++中为入口点添加了包装器

通过在go中添加对共享库的支持,现在这是可能的

计算器。开始

// package name: calculator
package main

import "C"

//export Sum
func Sum(x, y float64) float64 {
    return x + y
}

func main() {
}
节点计算器.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)
}
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

我认为Go应该是一个入口点,即使你是从C调用它?据我所知,您无法为其他语言编写“扩展”。我现在正在安装gccgo。你在上看过答案了吗?我看他们可以用
main
条目编译一个c程序。我到现在还没有。我想我只是在golang nuts邮件列表上没有看到任何对该功能的确认。每当有人提出这个问题时,他们都会说不能编写扩展来嵌入到其他语言中。不确定这种方法的局限性是什么。有兴趣知道。请看。它还没有得到官方支持,功能也非常有限。正如我所怀疑的,运行时不会被正确初始化,您必须做一些不会产生垃圾或不需要运行时的事情。这似乎使它成为一个没有什么好处的选项。@jdi谢谢!我不知道这个限制,我想你对这个问题给出了一个正确的答案。我使用Go 1.9.3得到了一个错误:
ld:warning:忽略文件../calculator.a,文件是为存档而构建的,它不是被链接的体系结构(x86_64):../calculator.a
#> node test.js 
4+5= 9