日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
如何把Node.js嵌入自己的項(xiàng)目中
#include "node.h"
#include "uv.h"
#include

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& args,
const std::vector& exec_args);

int main(int argc, char** argv) {
argv = uv_setup_args(argc, argv);
std::vector args(argv, argv + argc);
std::vector exec_args;
std::vector 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 platform =
MultiIsolatePlatform::Create(4);
V8::InitializePlatform(platform.get());
V8::Initialize();

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

V8::Dispose();
// V8::DisposePlatform();
return ret;
}

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

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);
Context::Scope context_scope(setup->context());

MaybeLocal loadenv_ret = node::LoadEnvironment(
env,
"const publicRequire ="
" require('module').createRequire(process.cwd() + '/');"
"globalThis.require = publicRequire;"
"publicRequire('./test')");

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;
}

大部分都是默認(rèn)的流程,我們可以先不用關(guān)注,重點(diǎn)是 LoadEnvironment 函數(shù)的邏輯。LoadEnvironment 最后會(huì)執(zhí)行我們傳入的字符串代碼。這段代碼中,前面是 Node.js 提供的 demo,后面一句是我加的,test.js 里簡(jiǎn)單輸出 hello world。下面來(lái)編譯一下。

g++ Node.cc src/node_code_cache_stub.cc src/node_snapshot_stub.cc -I/node/v17.9.0/include/node -std=c++14 -L /node/out/Release -l v8_base_without_compiler -l v8_compiler -l v8_init -l v8_initializers -l v8_libbase -l v8_libplatform -l v8_snapshot -l brotli -l cares -l gtest -l gtest_main -l histogram -l icudata -l icui18n -l icutools -l icuucx -l llhttp -l nghttp2 -l nghttp3 -l ngtcp2  -l openssl -l torque_base -l uv -l uvwasi -l v8_zlib -l zlib -l pthread -l node

因?yàn)?code cache 和 快照函數(shù)的符號(hào)找不到的問(wèn)題,這里先曲線救國(guó)一下,從 Node.js 源碼里引入這兩個(gè)文件,后續(xù)再去研究具體方案。編譯完后就拿到了一個(gè) a.out 文件,執(zhí)行該文件就可以看到輸出 hello world。cool,我們已經(jīng)實(shí)現(xiàn)了把 Node.js 嵌入到我們的項(xiàng)目。下面具體來(lái)看一下涉及到的一些邏輯。從 LoadEnvironment 看起。

MaybeLocal LoadEnvironment(
Environment* env,
const char* main_script_source_utf8) {
Isolate* isolate = env->isolate();
return LoadEnvironment(
env,
[&](const StartExecutionCallbackInfo& info) -> MaybeLocal {
// 一會(huì)分析
});
}

LoadEnvironment 進(jìn)一步調(diào)了另一個(gè) LoadEnvironment。

MaybeLocal LoadEnvironment(
Environment* env,
StartExecutionCallback cb) {
env->InitializeLibuv();
env->InitializeDiagnostics();
return StartExecution(env, cb);
}

LoadEnvironment 進(jìn)行了一些初始化,接著調(diào) StartExecution。

MaybeLocal StartExecution(Environment* env, StartExecutionCallback cb) {
InternalCallbackScope callback_scope(
env,
Object::New(env->isolate()),
{ 1, 0 },
InternalCallbackScope::kSkipAsyncHooks);

if (cb != nullptr) {
EscapableHandleScope scope(env->isolate());

if (StartExecution(env, "internal/bootstrap/environment").IsEmpty())
return {};

StartExecutionCallbackInfo info = {
env->process_object(),
env->native_module_require(),
};

return scope.EscapeMaybe(cb(info));
}
}

StartExecution 最終執(zhí)行了 第一個(gè) LoadEnvironment 傳入到回調(diào),并傳入了 process 和原生 JS 模塊加載器。接著看回調(diào)函數(shù)的邏輯。

std::string name = "embedder_main_" + std::to_string(env->thread_id());
// 插入原生 JS 模塊代碼中
native_module::NativeModuleEnv::Add(
name.c_str(),
UnionBytes(**main_utf16, main_utf16->length()));
env->set_main_utf16(std::move(main_utf16));
std::vector> params = {
env->process_string(),
env->require_string()};
std::vector> args = {
env->process_object(),
env->native_module_require()};
// 執(zhí)行我們的代碼
return ExecuteBootstrapper(env, name.c_str(), ¶ms, &args);
}

回調(diào)函數(shù)通過(guò) ExecuteBootstrapper 執(zhí)行我們傳入的代碼。

MaybeLocal ExecuteBootstrapper(Environment* env,
const char* id,
std::vector>* parameters,
std::vector>* arguments) {
EscapableHandleScope scope(env->isolate());
// 從原生 JS 模塊代碼中找到我們的代碼
MaybeLocal maybe_fn =
NativeModuleEnv::LookupAndCompile(env->context(), id, parameters, env);

Local fn;
if (!maybe_fn.ToLocal(&fn)) {
return MaybeLocal();
}
// 執(zhí)行我們的代碼
MaybeLocal result = fn->Call(env->context(),
Undefined(env->isolate()),
arguments->size(),
arguments->data());
}

再回過(guò)頭來(lái)看看我們的代碼。

const publicRequire = require('module').createRequire(process.cwd() + '/');
globalThis.require = publicRequire;
publicRequire('./test');

require 函數(shù)是原生 JS 模塊加載器,可以用來(lái)加載 Node.js 原生 JS 模塊。通過(guò) module 模塊可以創(chuàng)建一個(gè)用戶(hù) JS 模塊加載器。通過(guò)用戶(hù) JS 模塊加載器,我們就可以把我們的代碼串起來(lái)了。


當(dāng)前標(biāo)題:如何把Node.js嵌入自己的項(xiàng)目中
標(biāo)題鏈接:http://www.dlmjj.cn/article/dpggpcs.html