napi - ¿Se podría escribir una extensión Node.js nativa en Go, en lugar de en C++?
node js n api (3)
Con la adición de soporte para bibliotecas compartidas en marcha, esto es posible ahora.
archivo: calculator.go
// package name: calculator
package main
import "C"
//export Sum
func Sum(x, y float64) float64 {
return x + y
}
func main() {
}
archivo: 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)
}
archivo: test.cc
const calculator = require(''./build/Release/node-calculator'');
console.log(''4+5='', calculator.add(4, 5));
archivo: binding.gyp
{
"targets": [
{
"target_name": "node-calculator",
"sources": [
"node-calculator.cc"
],
"libraries": [
"../calculator.a"
],
},
],
}
Construir:
go build -buildmode c-archive -o calculator.a calculator.go
node-gyp configure
node-gyp build
Salida:
#> node test.js
4+5= 9
Eso es todo lo que hay en mi pregunta, realmente, pero creo que es una cosa interesante que hay que responder.
El módulo nativo para node.js debe interactuar profundamente con el proceso V8, que contiene una gran cantidad de conceptos de v8 como gc, javascript context, ...
Y no creo que V8 haya expuesto API compatibles y estables para que otros idiomas interactúen con él. Es por eso que el complemento nativo node.js debe compilarse con C ++ y siempre importa los encabezados V8 C ++.
Pero puede usar GO para escribir los complementos nativos de node.js envolviendo el código GO con C ++:
archivo: module.go
package main
func Add(a, b int) int {
return a + b
}
archivo: módulo.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)
Más sobre "cómo llamar a GO functionn desde C / C ++":
Editar:
Consulte los comentarios de @jdi y el enlace: https://groups.google.com/forum/#!msg/golang-nuts/FzPbOwbTlPs/dAJVWQHx6m4J
Cita: Podría ser factible para cosas simples como agregar (que no generan basura o requieren el tiempo de ejecución), pero ninguno de los compiladores lo admite (por lo que sé). Parte del trabajo se realiza para linux (consulte golang.org/issue/256), pero hay una serie de preguntas abiertas (¿qué sucede cuando carga dos objetos compartidos? Etc.)
Solo para volver a publicar esto como una respuesta en lugar de un comentario ...
Seguí con la lista de correo de golang-nuts respecto al soporte para escribir extensiones en Go para otros idiomas. La fuente de la respuesta se puede encontrar aquí .
Podría ser factible para cosas simples como agregar (que no generan basura o requieren el tiempo de ejecución), pero hasta ahora no está soportado por ninguno de los compiladores. Parte del trabajo se realiza para linux (consulte golang.org/issue/256 ), pero hay una serie de preguntas abiertas (¿qué sucede cuando carga dos objetos compartidos? Etc.)
Entonces, realmente, no parece haber mucho sentido escribir una extensión en Go, sin embargo, ya que la mayoría de las funciones de idioma no estarán disponibles, y de todos modos ya estás en C / C ++ land para agregar la envoltura al punto de entrada .