C++ 嵌入器

您所在的位置:网站首页 nodeloop C++ 嵌入器

C++ 嵌入器

2023-12-29 16:46| 来源: 网络整理| 查看: 265

嵌入应用示例#

以下章节将概述如何使用这些 API 从头开始​​创建应用,该应用将执行相当于 node -e 的操作,也就是将使用一段 JavaScript 并在特定于 Node.js 的环境中运行。

英The following sections will provide an overview over how to use these APIs to create an application from scratch that will perform the equivalent of node -e , i.e. that will take a piece of JavaScript and run it in a Node.js-specific environment.

完整的代码可以在 在 Node.js 源代码树中 中找到。

英The full code can be found in the Node.js source tree.

设置每个进程状态#

Node.js 需要一些每个进程的状态管理才能运行:

英Node.js requires some per-process state management in order to run:

Node.js CLI 选项 的参数解析, V8 每个进程要求,例如 v8::Platform 实例。

下面的示例展示了如何设置这些。 一些类名分别来自 node 和 v8 C++ 命名空间。

英The following example shows how these can be set up. Some class names are from the node and v8 C++ namespaces, respectively.

int main(int argc, char** argv) { argv = uv_setup_args(argc, argv); std::vector args(argv, argv + argc); // Parse Node.js CLI options, and print any errors that have occurred while // trying to parse them. std::unique_ptr result = node::InitializeOncePerProcess(args, { node::ProcessInitializationFlags::kNoInitializeV8, node::ProcessInitializationFlags::kNoInitializeNodeV8Platform }); for (const std::string& error : result->errors()) fprintf(stderr, "%s: %s\n", args[0].c_str(), error.c_str()); if (result->early_return() != 0) { return result->exit_code(); } // Create a v8::Platform instance. `MultiIsolatePlatform::Create()` is a way // to create a v8::Platform instance that Node.js can use when creating // Worker threads. When no `MultiIsolatePlatform` instance is present, // Worker threads are disabled. std::unique_ptr platform = MultiIsolatePlatform::Create(4); V8::InitializePlatform(platform.get()); V8::Initialize(); // See below for the contents of this function. int ret = RunNodeInstance( platform.get(), result->args(), result->exec_args()); V8::Dispose(); V8::DisposePlatform(); node::TearDownOncePerProcess(); return ret; }

每个实例状态# 版本历史 版本变更 v15.0.0

添加了 CommonEnvironmentSetup 和 SpinEventLoop 实用工具。

Node.js 有一个 “Node.js 实例” 的概念,通常被称为 node::Environment。 每个 node::Environment 都与:

英Node.js has a concept of a “Node.js instance”, that is commonly being referred to as node::Environment. Each node::Environment is associated with:

正好是 v8::Isolate,即 JS 引擎实例, 正好是 uv_loop_t,即事件循环,并且 多个 v8::Context,但恰好是一个主 v8::Context。 一个 node::IsolateData 实例包含可由使用相同 v8::Isolate 的多个 node::Environment 共享的信息。 目前,没有针对此场景执行测试。

为了设置 v8::Isolate,需要提供 v8::ArrayBuffer::Allocator。 一种可能的选择是默认的 Node.js 分配器,它可以通过 node::ArrayBufferAllocator::Create() 创建。 当插件使用 Node.js C++ Buffer API 时,使用 Node.js 分配器可以实现较小的性能优化,并且需要在 process.memoryUsage() 中跟踪 ArrayBuffer 内存。

英In order to set up a v8::Isolate, an v8::ArrayBuffer::Allocator needs to be provided. One possible choice is the default Node.js allocator, which can be created through node::ArrayBufferAllocator::Create(). Using the Node.js allocator allows minor performance optimizations when addons use the Node.js C++ Buffer API, and is required in order to track ArrayBuffer memory in process.memoryUsage().

此外,每个用于 Node.js 实例的 v8::Isolate 都需要在 MultiIsolatePlatform 实例中注册和注销(如果正在使用),以便平台知道对于 v8::Isolate 调度的任务使用哪个事件循环。

英Additionally, each v8::Isolate that is used for a Node.js instance needs to be registered and unregistered with the MultiIsolatePlatform instance, if one is being used, in order for the platform to know which event loop to use for tasks scheduled by the v8::Isolate.

node::NewIsolate() 辅助函数创建 v8::Isolate,使用一些 Node.js 特定的钩子(例如 Node.js 错误句柄)设置,并自动将其注册到平台。

英The node::NewIsolate() helper function creates a v8::Isolate, sets it up with some Node.js-specific hooks (e.g. the Node.js error handler), and registers it with the platform automatically.

int RunNodeInstance(MultiIsolatePlatform* platform, const std::vector& args, const std::vector& exec_args) { int exit_code = 0; // Setup up a libuv event loop, v8::Isolate, and Node.js Environment. std::vector errors; std::unique_ptr 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); // The v8::Context needs to be entered when node::CreateEnvironment() and // node::LoadEnvironment() are being called. Context::Scope context_scope(setup->context()); // Set up the Node.js instance for execution, and run code inside of it. // There is also a variant that takes a callback and provides it with // the `require` and `process` objects, so that it can manually compile // and run scripts as needed. // The `require` function inside this script does *not* access the file // system, and can only load built-in Node.js modules. // `module.createRequire()` is being used to create one that is able to // load files from the disk, and uses the standard CommonJS file loader // instead of the internal-only `require` function. MaybeLocal loadenv_ret = node::LoadEnvironment( env, "const publicRequire =" " require('node:module').createRequire(process.cwd() + '/');" "globalThis.require = publicRequire;" "require('node: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() can be used to explicitly stop the event loop and keep // further JavaScript from running. It can be called from any thread, // and will act like worker.terminate() if called from another thread. node::Stop(env); } return exit_code; }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3