8 votes

Appeler une fonction JavaScript existante à partir d'un addon C++ Node.js - à partir d'un autre fil de discussion

Peut-être que je ne recherche tout simplement pas les bons termes mais je suis bloqué..

J'ai besoin d'appeler une fonction JavaScript depuis C++, très similaire à ce qui peut être fait en utilisant l'API C basique.

Note: Je ne veux pas passer un callback au code C++ mais je connais déjà le nom de la fonction à appeler!

Par exemple, j'ai une fonction comme celle-ci en JavaScript:

function log_message_callback(context, message) {
  console.log(`${context}: ${message}`);
}

my_napi_module.initialize();   // <-- démarre un thread qui appellerait log_message_callback

Et depuis C++ je veux l'appeler (d'ailleurs, depuis un thread différent du thread principal):

#include 

void log_message_callback(char const* message) {
  // code Napi magique qui appellerait log_message_callback en JavaScript
} 

void some_thread_fn() {
  log_message_callback("hello world");
}

Puis-je le faire? Comment le ferais-je? Et qu'aurais-je dû rechercher?!

5voto

Satyan Points 1054

Les fonctions JavaScript ne peuvent normalement être appelées que depuis le thread principal d'un module natif. Vous pouvez obtenir plus d'informations à ce sujet sur

. https://nodejs.org/dist/latest-v11.x/docs/api/n-api.html#n_api_asynchronous_thread_safe_function_calls

La fonction napi_call_function() peut être utilisée pour appeler une fonction JavaScript depuis la couche native. La documentation contient un extrait de code pour son utilisation également. https://nodejs.org/dist/latest-v11.x/docs/api/n-api.html#n_api_napi_call_function

4voto

frans Points 2516

Ceci n'est PAS une réponse - juste quelques résultats de recherche..

On dirait que le code que je dois écrire doit ressembler à ceci - actuellement je ne sais pas comment tout configurer pour que tout fonctionne..

La plupart du code est tiré de cette branche eventing.

Ces valeurs doivent être disponibles - il semble que je doive les initialiser lors de l'initialisation du module..

static v8::Persistent context_;
static v8::Isolate *isolate_;

Cette fonction transforme à la fois log_message_callback() du monde JavaScript en un v8::Function et l'appelle. Une approche plus sophistiquée séparerait ces étapes:

extern "C" {

void log_message_callback(char const* message) {
  v8::Locker locker(isolate_);
  v8::Isolate::Scope isolate_scope(isolate_);
  v8::HandleScope handle_scope(isolate_);
  auto context = context_.Get(isolate_);
  v8::Context::Scope context_scope(context);

  v8::Persistent log_message_callback_fn;

  /// ceci n'est nécessaire qu'une seule fois - juste pour la démonstration
  {
    auto global = context->Global();
    v8::Local log_message_callback_def;
    if (!global->Get(
          context, v8Str(isolate_, "log_message_callback")).ToLocal(&log_message_callback_def)) {
      return;
    }

    if (!log_message_callback_def->IsFunction()) {
      return;
    }

    if (log_message_callback_def->IsFunction()) {
      auto on_update_fun = log_message_callback_def.As();
      log_message_callback_fn.Reset(isolate_, on_update_fun);
    }
  }  

  v8::Local args[2];
  log_message_callback_fn.Get(isolate_)->Call(context->Global(), 2, args);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X