Wie bettet man den Node.js-Interpreter in C/C++ ein?

Lesezeit: 7 Minuten

Ich möchte Node.js-Skripte in meinen C/C++-Anwendungen verwenden. Einige Leute schlugen mir vor, mit v8, libev und libeio zu beginnen; aber es bedeutet, Node.js von Grund auf neu zu schreiben.

Ist es also möglich, Node.js in C oder C++ einzubetten?

  • node.js ist eigentlich V8 eingebettet in einen Webserver. Da Ihre Anwendung wahrscheinlich kein Webserver ist, können Sie einfach V8 (oder eine andere Javascript-Engine) darin einbetten.

    – MAK

    2. April 2011 um 19:01 Uhr

  • Technisch gesehen macht node.js nicht nur Webserver. Es kann unzählige verschiedene Rollen erfüllen, aber es ist wirklich gut für HTTP-Server (Dateiserver, Webserver usw.). In beiden Fällen haben Sie Recht, wenn Sie stattdessen nur V8 verwenden.

    – beatgammit

    3. April 2011 um 5:27 Uhr

  • @MAK node.js ist kein Webserver. Es integriert ein Webserver-Modul, aber es ist sicherlich kein Webserver. In C++-Apps bringt node.js jede Menge Module, die nur mit v8 nicht verfügbar sind.

    – Kojote

    10. Dezember 2012 um 10:01 Uhr


Benutzeravatar von errordeveloper
Fehlerentwickler

Man sollte sich vorher überlegen, ob es das wäre ausreichen, um Ihre Anwendung als C++-Modul für Node zu implementieren und dann kleben Sie den Hauptteil als Node-Skript.

Andernfalls möchten Sie vielleicht “Node neu implementieren”, indem Sie den Kerncode als Beispiel nehmen und die Teile entfernen, die Sie nicht benötigen (z. B. HTTP-Modul), und dann Ihre Komponenten hineinstecken. Der am wenigsten schmerzhafte Weg wäre, einen Teilbaum zusammenzuführen und das Build-System herauszureißen und dann Präfixe in den Build-Skripten hinzuzufügen, um auf das Verzeichnis zu verweisen, in dem es sich befindet. Dann können Sie verhindern, dass bestimmte Teile gebaut werden. Das Build-System von Node enthält jedoch mehrere Teile, und es kann eine ziemlich schwierige Aufgabe sein, dies zu tun.

Sie können auch versuchen, Node mit Ihren standardmäßig geladenen Dateien neu zu packen und den Namen der ausführbaren Datei zu ändern. Dies ist jedoch nur eine komplexere Art, den ersten Ansatz zu wählen, den ich beschrieben habe, Sie können einfach ein Skript installieren /usr/bin/ was so gehen wird:

  #!/usr/bin/node
  var myAppMain = require('libmyApp');
  myAppMain.withConfig(filename,
  function(err, cnf) {
     if (err) throw err; // parser or file access error
     cnf.evalMe();
  });

Sie können einen JSlint als Parser verwenden, dann nach gefährlichen Aufrufen suchen und dann eval(conf_script) oder einfach verwenden require(config.js)obwohl Sie hinzufügen müssen exports.someMethod = function (...) {...}. Aber require() ist im Allgemeinen viel sicherer, aber Sie möchten vielleicht einen Präprozessor für Ihre Konfiguration implementieren, der ihn ersetzt exports.someMethod = function (...) {...} anstelle Ihrer Funktionen und wird angehängt require('OnlyCallMySafeMethods') und jeden Versuch ablehnen require('fs') oder andere Freiheiten, die Sie möglicherweise nicht verwenden möchten. Diese Art von Sicherheit ist nur eine optionale Sache für Sie vielleicht haben möchten, es liegt wirklich an dir. Obwohl ich nehme an, Sie möchten vielleicht das bisschen mit tun exports.someMethod = .... Substitution und habe eine require('myAppConfigLib) oben hinzugefügt, damit der Benutzer nur Ihre API und alles, was er in sein Skript / seine Konfiguration einfügen möchte, verwendet!

AKTUALISIEREN: Es gibt einen recht nützlichen Kommentar dazu Zeile 66 von src/node.js:

  // To allow people to extend Node in different ways, this hook allows
  // one to drop a file lib/_third_party_main.js into the build
  // directory which will be executed instead of Node's normal loading.

Bitte beachten Sie auch, dass der Inhalt von src/ werden zur Build-Zeit in Bytecode kompiliert.

Das Einbetten von Node.JS wird jetzt offiziell von einem Node.JS-Fork JXcore unterstützt. Einbettungsdokumente sind verfügbar unter dieser Link.

  • Dies ist ein ausgezeichneter Vorschlag und sollte imo die akzeptierte Antwort sein, genau nach dem OP.

    – Paul Grove

    27. Januar 2016 um 15:14 Uhr

  • Scheint ab 2016 ausgelaufen zu sein

    – Codierung

    18. November 2021 um 0:33 Uhr

Benutzeravatar von ZECTBynmo
ZECTBynmo

Ich habe etwas gebaut, das dem nahe kommt, wonach Sie suchen:

https://github.com/ZECTBynmo/tacnode

Es ist eine Bibliothek, mit der node.js statisch in eine C++-Anwendung eingebunden werden kann. Es ist definitiv nicht ausgefeilt, aber ich habe es verwendet, um einfache Knotenskripte zu starten.

  • Habe es versucht, aber ein Syntaxfehler im Build-Skript “vcbuild.bat” ist schlimm genug, um nicht mehr Zeit damit zu verbringen.

    – Lothar

    6. Juli 2014 um 12:21 Uhr

Es ist wahrscheinlich, dass V8 in C++ geschrieben ist, node.js kann auf V8 ausgeführt werden, aber es sei denn, Sie haben eine äußerst Ein guter Grund, warum Sie Javascript über C++ ausführen würden, sind Sie wahrscheinlich viel besser bedient, wenn Sie eine geeignete C++-Bibliothek finden und die benötigte Funktionalität direkt in C++ implementieren. Die Aufgabe, Skriptsprachen und nativen Code zu integrieren, ist normalerweise nicht trivial. Z.B V8-Dokumentation. Qt bietet eine ziemlich anständige Integration zwischen C++ und Javascript und es ist immer noch nicht trivial, Objekte zwischen Skript und Code hin und her zu verschieben.

Ich war gerade beim Auschecken js-git Das ist für Node.js gemacht und hängt auch von einigen anderen Node.js-Modulen ab.

Derselbe Entwickler hat jedoch ein Tool geschrieben tim-Aufgabe um vor allem einige allgemeine Node.js-Funktionen zusammenzufassen require, und einige Node.js-Module so zusammenzupacken, dass es nicht mehr von Node.js abhängig sein soll. Er benutzte es, um zu machen git-web-plattform, dh js-git gepackt als JS-Datei, die in Browsern verwendet werden kann. Die resultierende gepackte Datei sieht so aus Dies. Dieser lässt sich mit geringfügigen Modifikationen wohl auch nur im reinen V8 nutzen.

Dies könnte für Sie nützlich sein. Beachten Sie jedoch, dass dieser Ansatz begrenzt sein wird.

Benutzeravatar von Philip Taylor
Philip Taylor

Es gibt viele gute Gründe für die Einbettung von Knoten, einschließlich der Möglichkeit, npm zu nutzen.

Leider stirbt JXCore. Dieser Artikel gibt einige Alternativen.
http://www.goland.org/nodeapps/

Benutzeravatar von Codebling
Codierung

Die offizielle Dokumentation hat eine Seite, die erklärt, wie wie man Node.js in C++ einbettet. Das gibt es seitdem Knoten 12.x.

Da ist ein vollständiges Beispiel im Node-Repo. Der Einfachheit halber unten wiedergegeben:


#include "node.h"
#include "uv.h"
#include <assert.h>

// Note: This file is being referred to from doc/api/embedding.md, and excerpts
// from it are included in the documentation. Try to keep these in sync.

using node::CommonEnvironmentSetup;
using node::Environment;
using node::MultiIsolatePlatform;
using v8::Context;
using v8::HandleScope;
using v8::Isolate;
using v8::Locker;
using v8::MaybeLocal;
using v8::V8;
using v8::Value;

static int RunNodeInstance(MultiIsolatePlatform* platform,
                           const std::vector<std::string>& args,
                           const std::vector<std::string>& exec_args);

int main(int argc, char** argv) {
  argv = uv_setup_args(argc, argv);
  std::vector<std::string> args(argv, argv + argc);
  std::vector<std::string> exec_args;
  std::vector<std::string> errors;
  int exit_code = node::InitializeNodeWithArgs(&args, &exec_args, &errors);
  for (const std::string& error : errors)
    fprintf(stderr, "%s: %s\n", args[0].c_str(), error.c_str());
  if (exit_code != 0) {
    return exit_code;
  }

  std::unique_ptr<MultiIsolatePlatform> platform =
      MultiIsolatePlatform::Create(4);
  V8::InitializePlatform(platform.get());
  V8::Initialize();

  int ret = RunNodeInstance(platform.get(), args, exec_args);

  V8::Dispose();
  V8::ShutdownPlatform();
  return ret;
}

int RunNodeInstance(MultiIsolatePlatform* platform,
                    const std::vector<std::string>& args,
                    const std::vector<std::string>& exec_args) {
  int exit_code = 0;

  std::vector<std::string> errors;
  std::unique_ptr<CommonEnvironmentSetup> setup =
      CommonEnvironmentSetup::Create(platform, &errors, args, exec_args);
  if (!setup) {
    for (const std::string& err : errors)
      fprintf(stderr, "%s: %s\n", args[0].c_str(), err.c_str());
    return 1;
  }

  Isolate* isolate = setup->isolate();
  Environment* env = setup->env();

  {
    Locker locker(isolate);
    Isolate::Scope isolate_scope(isolate);
    HandleScope handle_scope(isolate);
    Context::Scope context_scope(setup->context());

    MaybeLocal<Value> loadenv_ret = node::LoadEnvironment(
        env,
        "const publicRequire ="
        "  require('module').createRequire(process.cwd() + "https://stackoverflow.com/");"
        "globalThis.require = publicRequire;"
        "globalThis.embedVars = { nön_ascıı: '🏳️‍🌈' };"
        "require('vm').runInThisContext(process.argv[1]);");

    if (loadenv_ret.IsEmpty())  // There has been a JS exception.
      return 1;

    exit_code = node::SpinEventLoop(env).FromMaybe(1);

    node::Stop(env);
  }

  return exit_code;
}

1386610cookie-checkWie bettet man den Node.js-Interpreter in C/C++ ein?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy