Posted 鍓嶇绀惧尯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了相关的知识,希望对你有一定的参考价值。
efe.baidu.com/blog/nodejs-module-analyze/
Node.js 鐨勫嚭鐜帮紝璁?JavaScript 鑴辩浜嗘祻瑙堝櫒鐨勬潫缂氾紝杩涘叆浜嗗箍闃旂殑鏈嶅姟绔紑鍙戦鍩熴€傝€?Node.js 瀵?CommonJS 妯″潡鍖栬鑼冪殑寮曞叆锛屽垯鏇存槸璁?JavaScript鎴愪负浜嗕竴闂ㄧ湡姝h兘澶熼€傚簲澶у瀷宸ョ▼鐨勮瑷€銆?/span>
鍦?Node.js 涓娇鐢ㄦā鍧楅潪甯哥畝鍗曪紝鎴戜滑鏃ュ父寮€鍙戜腑鍑犱箮閮芥湁杩囪繖鏍风殑缁忓巻锛氬啓涓€娈?javascript 浠g爜锛宺equire 涓€浜涙兂瑕佺殑鍖咃紝鐒跺悗灏嗕唬鐮佷骇鐗?exports 瀵煎嚭銆備絾鏄紝瀵逛簬 Node.js 妯″潡鍖栬儗鍚庣殑鍔犺浇涓庤繍琛屽師鐞嗭紝鎴戜滑鏄惁娓呮鍛€傞鍏堟姏鍑轰互涓嬪嚑涓棶棰橈細
Node.js 涓殑妯″潡鏀寔鍝簺鏂囦欢绫诲瀷锛?/span>
鏍稿績妯″潡鍜岀涓夋柟妯″潡鐨勫姞杞借繍琛屾祦绋嬫湁浠€涔堜笉鍚岋紵
闄や簡 JavaScript 妯″潡浠ュ锛屾€庢牱鍘诲啓涓€涓?C/C++ 鎵╁睍妯″潡锛?/span>
鈥︹€?/span>
鏈瘒鏂囩珷锛屽氨浼氱粨鍚?Node.js 婧愮爜锛屾帰绌朵竴涓嬩互涓婅繖浜涢棶棰樿儗鍚庣殑绛旀銆?/span>
1. Node.js 妯″潡绫诲瀷
鍦?Node.js 涓紝妯″潡涓昏鍙互鍒嗕负浠ヤ笅鍑犵绫诲瀷锛?/span>
鏍稿績妯″潡锛氬寘鍚湪 Node.js 婧愮爜涓紝琚紪璇戣繘 Node.js 鍙墽琛屼簩杩涘埗鏂囦欢 JavaScript 妯″潡锛屼篃鍙?native 妯″潡锛屾瘮濡傚父鐢ㄧ殑 http, fs 绛夌瓑
C/C++ 妯″潡锛屼篃鍙?built-in 妯″潡锛屼竴鑸垜浠笉鐩存帴璋冪敤锛岃€屾槸鍦?native module 涓皟鐢紝鐒跺悗鎴戜滑鍐?require
native 妯″潡锛屾瘮濡傛垜浠湪 Node.js 涓父鐢ㄧ殑 buffer锛宖s锛宱s 绛?native 妯″潡锛屽叾搴曞眰閮芥湁璋冪敤 built-in 妯″潡銆?/span>
绗笁鏂规ā鍧楋細闈?Node.js 婧愮爜鑷甫鐨勬ā鍧楅兘鍙互缁熺О绗笁鏂规ā鍧楋紝姣斿 express锛寃ebpack 绛夌瓑銆?/span>
JavaScript 妯″潡锛岃繖鏄渶甯歌鐨勶紝鎴戜滑寮€鍙戠殑鏃跺€欎竴鑸兘鍐欑殑鏄?JavaScript 妯″潡
JSON 妯″潡锛岃繖涓緢绠€鍗曪紝灏辨槸涓€涓?JSON 鏂囦欢
C/C++ 鎵╁睍妯″潡锛屼娇鐢?C/C++ 缂栧啓锛岀紪璇戜箣鍚庡悗缂€鍚嶄负 .node
鏈瘒鏂囩珷涓紝鎴戜滑浼氫竴涓€娑夊強鍒颁笂杩板嚑绉嶆ā鍧楃殑鍔犺浇銆佽繍琛屽師鐞嗐€?/span>
2. Node.js 婧愮爜缁撴瀯涓€瑙?/span>
杩欓噷浣跨敤 Node.js 6.x 鐗堟湰婧愮爜涓轰緥瀛愭潵鍋氬垎鏋愩€傚幓 github 涓婁笅杞界浉搴旂増鏈殑 Node.js 婧愮爜锛屽彲浠ョ湅鍒颁唬鐮佸ぇ浣撶粨鏋勫涓嬶細
鈹溾攢鈹€ AUTHORS
鈹溾攢鈹€ BSDmakefile
鈹溾攢鈹€ BUILDING.md
鈹溾攢鈹€ CHANGELOG.md
鈹溾攢鈹€ CODE_OF_CONDUCT.md
鈹溾攢鈹€ COLLABORATOR_GUIDE.md
鈹溾攢鈹€ CONTRIBUTING.md
鈹溾攢鈹€ GOVERNANCE.md
鈹溾攢鈹€ LICENSE
鈹溾攢鈹€ Makefile
鈹溾攢鈹€ README.md
鈹溾攢鈹€ android-configure
鈹溾攢鈹€ benchmark
鈹溾攢鈹€ common.gypi
鈹溾攢鈹€ configure
鈹溾攢鈹€ deps
鈹溾攢鈹€ doc
鈹溾攢鈹€ lib
鈹溾攢鈹€ node.gyp
鈹溾攢鈹€ node.gypi
鈹溾攢鈹€ src
鈹溾攢鈹€ test
鈹溾攢鈹€ tools
鈹斺攢鈹€ vcbuild.bat
鍏朵腑锛?/span>
./lib鏂囦欢澶逛富瑕佸寘鍚簡鍚勭 JavaScript 鏂囦欢锛屾垜浠父鐢ㄧ殑 JavaScript native 妯″潡閮藉湪杩欓噷銆?/span>
./src鏂囦欢澶逛富瑕佸寘鍚簡 Node.js 鐨?C/C++ 婧愮爜鏂囦欢锛屽叾涓緢澶?built-in 妯″潡閮藉湪杩欓噷銆?/span>
./deps鏂囦欢澶瑰寘鍚簡 Node.js 渚濊禆鐨勫悇绉嶅簱锛屽吀鍨嬬殑濡?v8锛宭ibuv锛寊lib 绛夈€?/span>
鎴戜滑鍦ㄥ紑鍙戜腑浣跨敤鐨?release 鐗堟湰锛屽叾瀹炲氨鏄粠婧愮爜缂栬瘧寰楀埌鐨勫彲鎵ц鏂囦欢銆傚鏋滄垜浠兂瑕佸 Node.js 杩涜涓€浜涗釜鎬у寲鐨勫畾鍒讹紝鍒欏彲浠ュ婧愮爜杩涜淇敼锛岀劧鍚庡啀杩愯缂栬瘧锛屽緱鍒板畾鍒跺寲鐨?Node.js 鐗堟湰銆傝繖閲屼互 Linux 骞冲彴涓轰緥锛岀畝瑕佷粙缁嶄竴涓?Node.js 缂栬瘧娴佺▼銆?/span>
棣栧厛锛屾垜浠渶瑕佽璇嗕竴涓嬬紪璇戠敤鍒扮殑缁勭粐宸ュ叿锛屽嵆 gyp銆侼ode.js 婧愮爜涓垜浠彲浠ョ湅鍒颁竴涓?node.gyp锛岃繖涓枃浠朵腑鐨勫唴瀹规槸鐢?python 鍐欐垚鐨勪竴浜?JSON-like 閰嶇疆锛屽畾涔変簡涓€杩炰覆鐨勬瀯寤哄伐绋嬩换鍔°€傛垜浠妇涓緥瀛愶紝鍏朵腑鏈変竴涓瓧娈靛涓嬶細
{
'target_name': 'node_js2c',
'type': 'none',
'toolsets': ['host'],
'actions': [
{
'action_name': 'node_js2c',
'inputs': [
'<@(library_files)',
'./config.gypi',
],
'outputs': [
'<(SHARED_INTERMEDIATE_DIR)/node_natives.h',
],
'conditions': [
[ 'node_use_dtrace=="false" and node_use_etw=="false"', {
'inputs': [ 'src/notrace_macros.py' ]
}],
['node_use_lttng=="false"', {
'inputs': [ 'src/nolttng_macros.py' ]
}],
[ 'node_use_perfctr=="false"', {
'inputs': [ 'src/perfctr_macros.py' ]
}]
],
'action': [
'python',
'tools/js2c.py',
'<@(_outputs)',
'<@(_inputs)',
],
},
],
}, # end node_js2c
杩欎釜浠诲姟涓昏鐨勪綔鐢ㄤ粠鍚嶇О node_js2c 灏卞彲浠ョ湅鍑烘潵锛屾槸灏?JavaScript 杞崲涓?C/C++ 浠g爜銆傝繖涓换鍔℃垜浠笅闈㈣繕浼氭彁鍒般€?/span>
棣栧厛缂栬瘧 Node.js锛岄渶瑕佹彁鍓嶅畨瑁呬竴浜涘伐鍏凤細
gcc 鍜?g++ 4.9.4 鍙婁互涓婄増鏈?/span>
clang 鍜?clang++
python 2.6 鎴栬€?2.7锛岃繖閲岃娉ㄦ剰锛屽彧鑳芥槸杩欎袱涓増鏈紝涓嶅彲浠ヤ负python 3+
GNU MAKE 3.81 鍙婁互涓婄増鏈?/span>
鏈変簡杩欎簺宸ュ叿锛岃繘鍏?Node.js 婧愮爜鐩綍锛屾垜浠彧闇€瑕佷緷娆¤繍琛屽涓嬪懡浠わ細
./configuration
make
make install
鍗冲彲缂栬瘧鐢熸垚鍙墽琛屾枃浠跺苟瀹夎浜嗐€?/span>
3. 浠?node index.js 寮€濮?/span>
璁╂垜浠鍏堜粠鏈€绠€鍗曠殑鎯呭喌寮€濮嬨€傚亣璁炬湁涓€涓?index.js 鏂囦欢锛岄噷闈㈠彧鏈変竴琛屽緢绠€鍗曠殑 console.log('hello world') 浠g爜銆傚綋杈撳叆 node index.js 鐨勬椂鍊欙紝Node.js 鏄浣曠紪璇戙€佽繍琛岃繖涓枃浠剁殑鍛紵
褰撹緭鍏?Node.js 鍛戒护鐨勬椂鍊欙紝璋冪敤鐨勬槸 Node.js 婧愮爜褰撲腑鐨?main 鍑芥暟锛屽湪 src/node_main.cc 涓細
// src/node_main.cc
#include "node.h"
#ifdef _WIN32
#include
int wmain(int argc, wchar_t *wargv[]) {
// windows涓嬮潰鐨勫叆鍙?/span>
}
#else
// UNIX
int main(int argc, char *argv[]) {
// Disable stdio buffering, it interacts poorly with printf()
// calls elsewhere in the program (e.g., any logging from V8.)
setvbuf(stdout, nullptr, _IONBF, 0);
setvbuf(stderr, nullptr, _IONBF, 0);
// 鍏虫敞涓嬮潰杩欎竴琛?/span>
return node::Start(argc, argv);
}
#endif
杩欎釜鏂囦欢鍙仛鍏ュ彛鐢紝鍖哄垎浜?Windows 鍜?Unix 鐜銆傛垜浠互 Unix 涓轰緥锛屽湪 main 鍑芥暟涓渶鍚庤皟鐢ㄤ簡 node::Start锛岃繖涓槸鍦?src/node.cc 鏂囦欢涓細
// src/node.cc
int Start(int argc, char** argv) {
// ...
{
NodeInstanceData instance_data(NodeInstanceType::MAIN,
uv_default_loop(),
argc,
const_cast<const char**>(argv),
exec_argc,
exec_argv,
use_debug_agent);
StartNodeInstance(&instance_data);
exit_code = instance_data.exit_code();
}
// ...
}
// ...
static void StartNodeInstance(void* arg) {
// ...
{
Environment::AsyncCallbackScope callback_scope(env);
LoadEnvironment(env);
}
// ...
}
// ...
void LoadEnvironment(Environment* env) {
// ...
Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(),
"bootstrap_node.js");
Local<Value> f_value = ExecuteString(env, MainSource(env), script_name);
if (try_catch.HasCaught()) {
ReportException(env, try_catch);
exit(10);
}
// The bootstrap_node.js file returns a function 'f'
CHECK(f_value->IsFunction());
Local<Function> f = Local<Function>::Cast(f_value);
// ...
f->Call(Null(env->isolate()), 1, &arg);
}
鏁翠釜鏂囦欢姣旇緝闀匡紝鍦ㄤ笂闈唬鐮佹閲岋紝鍙埅鍙栦簡鎴戜滑鏈€闇€瑕佸叧娉ㄧ殑娴佺▼鐗囨锛岃皟鐢ㄥ叧绯诲涓嬶細 Start -> StartNodeInstance -> LoadEnvironment銆?/span>
鍦?LoadEnvironment 闇€瑕佹垜浠叧娉紝涓昏鍋氱殑浜嬫儏灏辨槸锛屽彇鍑?bootstrap_node.js 涓殑浠g爜瀛楃涓诧紝瑙f瀽鎴愬嚱鏁帮紝骞舵渶鍚庨€氳繃 f->Call 鍘绘墽琛屻€?/span>
OK锛岄噸鐐规潵浜嗭紝浠?Node.js 鍚姩浠ユ潵锛屾垜浠粓浜庣湅鍒颁簡绗竴涓?JavaScript 鏂囦欢 bootstrap_node.js锛屼粠鏂囦欢鍚嶆垜浠篃鍙互鐪嬪嚭杩欎釜鏄竴涓叆鍙f€ц川鐨勬枃浠躲€傞偅涔堟垜浠揩鍘荤湅鐪嬪惂锛岃鏂囦欢璺緞涓?lib/internal/bootstrap_node.js锛?/span>
// lib/internal/boostrap_node.js
(function(process) {
function startup() {
// ...
else if (process.argv[1]) {
const path = NativeModule.require('path');
process.argv[1] = path.resolve(process.argv[1]);
const Module = NativeModule.require('module');
// ...
preloadModules();
run(Module.runMain);
}
// ...
}
// ...
startup();
}
// lib/module.js
// ...
// bootstrap main module.
Module.runMain = function() {
// Load the main module--the command line argument.
Module._load(process.argv[1], null, true);
// Handle any nextTicks added in the first tick of the program
process._tickCallback();
};
// ...
杩欓噷鎴戜滑渚濈劧鍏虫敞涓绘祦绋嬶紝鍙互鐪嬪埌锛宐ootstrap_node.js 涓紝鎵ц浜嗕竴涓?startup() 鍑芥暟銆傞€氳繃 process.argv[1] 鎷垮埌鏂囦欢鍚嶏紝鍦ㄦ垜浠殑 node index.js 涓紝process.argv[1] 鏄剧劧灏辨槸 index.js锛岀劧鍚庤皟鐢?path.resolve 瑙f瀽鍑烘枃浠惰矾寰勩€傚湪鏈€鍚庯紝run(Module.runMain) 鏉ョ紪璇戞墽琛屾垜浠殑 index.js銆?/span>
鑰?Module.runMain 鍑芥暟瀹氫箟鍦?lib/module.js 涓紝鍦ㄤ笂杩颁唬鐮佺墖娈电殑鏈€鍚庯紝鍒楀嚭浜嗚繖涓嚱鏁帮紝鍙互鐪嬪埌锛屼富瑕佹槸璋冪敤 Module._load 鏉ュ姞杞芥墽琛?process.argv[1]銆?/span>
涓嬫枃鎴戜滑鍦ㄥ垎鏋愭ā鍧楃殑 require 鐨勬椂鍊欙紝涔熶細鏉ュ埌 lib/module.js 涓紝涔熶細鍒嗘瀽鍒?Module._load銆傚洜姝ゆ垜浠彲浠ョ湅鍑猴紝Node.js 鍚姩涓€涓枃浠剁殑杩囩▼锛屽叾瀹炲埌鏈€鍚庯紝涔熸槸 require 涓€涓枃浠剁殑杩囩▼锛屽彲浠ョ悊瑙d负鏄珛鍗?require 涓€涓枃浠躲€備笅闈㈠氨鏉ュ垎鏋?require 鐨勫師鐞嗐€?/span>
4. 妯″潡鍔犺浇鍘熺悊鐨勫叧閿細require
鎴戜滑杩涗竴姝ワ紝鍋囪鎴戜滑鐨?index.js 鏈夊涓嬪唴瀹癸細
var http = require('http');
閭d箞褰撴墽琛岃繖涓€鍙ヤ唬鐮佺殑鏃跺€欙紝浼氬彂鐢熶粈涔堝憿锛?/span>
require鐨勫畾涔変緷鐒跺湪 lib/module.js 涓細
// lib/module.js
// ...
Module.prototype.require = function(path) {
assert(path, 'missing path');
assert(typeof path === 'string', 'path must be a string');
return Module._load(path, this, /* isMain */ false);
};
// ...
require 鏂规硶瀹氫箟鍦∕odule鐨勫師鍨嬮摼涓娿€傚彲浠ョ湅鍒拌繖涓柟娉曚腑锛岃皟鐢ㄤ簡 Module._load銆?/span>
鎴戜滑杩欎箞蹇氨鍙堟潵鍒颁簡 Module._load 鏉ョ湅鐪嬭繖涓叧閿殑鏂规硶绌剁珶鍋氫簡浠€涔堝惂锛?/span>
// lib/module.js
// ...
Module._load = function(request, parent, isMain) {
if (parent) {
debug('Module._load REQUEST %s parent: %s', request, parent.id);
}
var filename = Module._resolveFilename(request, parent, isMain);
var cachedModule = Module._cache[filename];
if (cachedModule) {
return cachedModule.exports;
}
if (NativeModule.nonInternalExists(filename)) {
debug('load native module %s', request);
return NativeModule.require(filename);
}
var module = new Module(filename, parent);
if (isMain) {
process.mainModule = module;
module.id = '.';
}
Module._cache[filename] = module;
tryModuleLoad(module, filename);
return module.exports;
};
// ...
杩欐浠g爜鐨勬祦绋嬫瘮杈冩竻鏅帮紝鍏蜂綋璇存潵锛?/span>
鏍规嵁鏂囦欢鍚嶏紝璋冪敤 Module._resolveFilename 瑙f瀽鏂囦欢鐨勮矾寰?/span>
鏌ョ湅缂撳瓨 Module._cache 涓槸鍚︽湁璇ユā鍧楋紝濡傛灉鏈夛紝鐩存帴杩斿洖
閫氳繃 NativeModule.nonInternalExists 鍒ゆ柇璇ユā鍧楁槸鍚︿负鏍稿績妯″潡锛屽鏋滄牳蹇冩ā鍧楋紝璋冪敤鏍稿績妯″潡鐨勫姞杞芥柟娉?NativeModule.require
濡傛灉涓嶆槸鏍稿績妯″潡锛屾柊鍒涘缓涓€涓?Module 瀵硅薄锛岃皟鐢?tryModuleLoad 鍑芥暟鍔犺浇妯″潡
鎴戜滑棣栧厛鏉ョ湅涓€涓?Module._resolveFilename锛岀湅鎳傝繖涓柟娉曞浜庢垜浠悊瑙?Node.js 鐨勬枃浠惰矾寰勮В鏋愬師鐞嗗緢鏈夊府鍔╋細
// lib/module.js
// ...
Module._resolveFilename = function(request, parent, isMain) {
// ...
var filename = Module._findPath(request, paths, isMain);
if (!filename) {
var err = new Error("Cannot find module '" + request + "'");
err.code = 'MODULE_NOT_FOUND';
throw err;
}
return filename;
};
// ...
鍦?Module._resolveFilename 涓皟鐢ㄤ簡 Module._findPath锛屾ā鍧楀姞杞界殑鍒ゆ柇閫昏緫瀹為檯涓婇泦涓湪杩欎釜鏂规硶涓紝鐢变簬杩欎釜鏂规硶杈冮暱锛岀洿鎺ラ檮涓?github 璇ユ柟娉曚唬鐮侊細
https://github.com/nodejs/node/blob/v6.x/lib/module.js#L158
鍙互鐪嬪嚭锛屾枃浠惰矾寰勮В鏋愮殑閫昏緫娴佺▼鏄繖鏍风殑锛?/span>
鍏堢敓鎴?cacheKey锛屽垽鏂浉搴?cache 鏄惁瀛樺湪锛岃嫢瀛樺湪鐩存帴杩斿洖
濡傛灉 path 鐨勬渶鍚庝竴涓瓧绗︿笉鏄?/锛?/span>
濡傛灉璺緞鏄竴涓枃浠跺苟涓斿瓨鍦紝閭d箞鐩存帴杩斿洖鏂囦欢鐨勮矾寰?/span>
濡傛灉璺緞鏄竴涓洰褰曪紝璋冪敤 tryPackage 鍑芥暟鍘昏В鏋愮洰褰曚笅鐨?package.json锛岀劧鍚庡彇鍑哄叾涓殑 main 瀛楁鎵€鍐欏叆鐨勬枃浠惰矾寰?/span>
鍒ゆ柇璺緞濡傛灉瀛樺湪锛岀洿鎺ヨ繑鍥?/span>
灏濊瘯鍦ㄨ矾寰勫悗闈㈠姞涓?.js, .json, .node 涓夌鍚庣紑鍚嶏紝鍒ゆ柇鏄惁瀛樺湪锛屽瓨鍦ㄥ垯杩斿洖
灏濊瘯鍦ㄨ矾寰勫悗闈緷娆″姞涓?index.js, index.json, index.node锛屽垽鏂槸鍚﹀瓨鍦紝瀛樺湪鍒欒繑鍥?/span>
濡傛灉杩樹笉鎴愬姛锛岀洿鎺ュ褰撳墠璺緞鍔犱笂 .js, .json, .node 鍚庣紑鍚嶈繘琛屽皾璇?/span>
濡傛灉 path 鐨勬渶鍚庝竴涓瓧绗︽槸 /锛?/span>
璋冪敤 tryPackage 锛岃В鏋愭祦绋嬪拰涓婇潰鐨勬儏鍐电被浼?/span>
濡傛灉涓嶆垚鍔燂紝灏濊瘯鍦ㄨ矾寰勫悗闈緷娆″姞涓?index.js, index.json, index.node锛屽垽鏂槸鍚﹀瓨鍦紝瀛樺湪鍒欒繑鍥?/span>
瑙f瀽鏂囦欢涓敤鍒扮殑 tryPackage 鍜?tryExtensions 鏂规硶鐨?github 閾炬帴锛?https://github.com/nodejs/node/blob/v6.x/lib/module.js#L108 https://github.com/nodejs/node/blob/v6.x/lib/module.js#L146
鏁翠釜娴佺▼鍙互鍙傝€冧笅闈㈣繖寮犲浘锛?/span>
鑰屽湪鏂囦欢璺緞瑙f瀽瀹屾垚涔嬪悗锛屾牴鎹枃浠惰矾寰勬煡鐪嬬紦瀛樻槸鍚﹀瓨鍦紝瀛樺湪鐩存帴杩斿洖锛屼笉瀛樺湪鐨勮瘽锛岃蛋鍒?3 鎴栬€?4 姝ラ銆?/span>
杩欓噷锛屽湪 3銆? 涓ゆ浜х敓浜嗕袱涓垎鏀紝鍗虫牳蹇冩ā鍧楀拰绗笁鏂规ā鍧楃殑鍔犺浇鏂规硶涓嶄竴鏍枫€傜敱浜庢垜浠亣璁句簡鎴戜滑鐨?index.js 涓负 var http = require('http')锛宧ttp 鏄竴涓牳蹇冩ā鍧楋紝鎵€浠ユ垜浠厛鏉ュ垎鏋愭牳蹇冩ā鍧楀姞杞界殑杩欎釜鍒嗘敮銆?/span>
4.1 鏍稿績妯″潡鍔犺浇鍘熺悊
鏍稿績妯″潡鏄€氳繃 NativeModule.require 鍔犺浇鐨勶紝NativeModule鐨勫畾涔夊湪 bootstrap_node.js 涓紝闄勪笂 github 閾炬帴锛?https://github.com/nodejs/node/blob/v6.x/lib/internal/bootstrap_node.js#L401
浠庝唬鐮佷腑鍙互鐪嬪埌锛孨ativeModule.require 鐨勬祦绋嬪涓嬶細
鍒ゆ柇 cache 涓槸鍚﹀凡缁忓姞杞借繃锛屽鏋滄湁锛岀洿鎺ヨ繑鍥?exports
鏂板缓 nativeModule 瀵硅薄锛岀劧鍚庣紦瀛橈紝骞跺姞杞界紪璇?/span>
棣栧厛鎴戜滑鏉ョ湅涓€涓嬪浣曠紪璇戯紝浠庝唬鐮佷腑鐪嬫槸璋冪敤浜?compile 鏂规硶锛岃€屽湪 NativeModule.prototype.compile 鏂规硶涓紝棣栧厛鏄€氳繃 NativeModule.getSource 鑾峰彇浜嗚鍔犺浇妯″潡鐨勬簮鐮侊紝閭d箞杩欎釜婧愮爜鏄浣曡幏鍙栫殑鍛紵鐪嬩竴涓?getSource 鏂规硶鐨勫畾涔夛細
// lib/internal/bootstrap_node.js
// ...
NativeModule._source = process.binding('natives');
// ...
NativeModule.getSource = function(id) {
return NativeModule._source[id];
};
鐩存帴浠?NativeModule._source 鑾峰彇鐨勶紝鑰岃繖涓張鏄湪鍝噷璧嬪€肩殑鍛紵鍦ㄤ笂杩颁唬鐮佷腑涔熸埅鍙栦簡鍑烘潵锛屾槸閫氳繃 NativeModule._source = process.binding('natives') 鑾峰彇鐨勩€?/span>
杩欓噷灏辫鎻掑叆浠嬬粛涓€涓?JavaScript native 妯″潡浠g爜鏄浣曞瓨鍌ㄧ殑浜嗐€侼ode.js 婧愮爜缂栬瘧鐨勬椂鍊欙紝浼氶噰鐢?v8 闄勫甫鐨?js2c.py 宸ュ叿锛屽皢 lib 鏂囦欢澶逛笅闈㈢殑 js 妯″潡鐨勪唬鐮侀兘杞崲鎴?C 閲岄潰鐨勬暟缁勶紝鐢熸垚涓€涓?node_natives.h 澶存枃浠讹紝璁板綍杩欎釜鏁扮粍锛?/span>
namespace node {
const char node_native[] = {47, 47, 32, 67, 112 鈥?span class="mq-1278">}
const char console_native[] = {47, 47, 32, 67, 112 鈥?span class="mq-1304">}
const char buffer_native[] = {47, 47, 32, 67, 112 鈥?span class="mq-1330">}
鈥?/span>
}
struct _native {const char name; const char* source; size_t source_len;};
static const struct _native natives[] = {
{ 鈥?span class="mq-1378">node鈥?span class="mq-1379">, node_native, sizeof(node_native)-1 },
{鈥?span class="mq-1396">dgram鈥?span class="mq-1397">, dgram_native, sizeof(dgram_native)-1 },
{鈥?span class="mq-1414">console鈥?span class="mq-1415">, console_native, sizeof(console_native)-1 },
{鈥?span class="mq-1432">buffer鈥?span class="mq-1433">, buffer_native, sizeof(buffer_native)-1 },
鈥?/span>
}
鑰屼笂鏂囦腑 NativeModule._source = process.binding('natives'); 鐨勪綔鐢紝灏辨槸鍙栧嚭杩欎釜 natives 鏁扮粍锛岃祴鍊肩粰NativeModule._source锛屾墍浠ュ湪 getSource 鏂规硶涓紝鐩存帴鍙互浣跨敤妯″潡鍚嶄綔涓虹储寮曪紝浠庢暟缁勪腑鍙栧嚭妯″潡鐨勬簮浠g爜銆?/span>
鍦ㄨ繖閲屾垜浠彃鍏ュ洖椤句竴涓嬩笂鏂囷紝鍦ㄤ粙缁?Node.js 缂栬瘧鐨勬椂鍊欙紝鎴戜滑浠嬬粛浜?node.gyp锛屽叾涓湁涓€涓换鍔℃槸 node_js2c锛屽綋鏃剁瑪鑰呮彁鍒颁粠鍚嶇О鐪嬭繖涓换鍔℃槸灏?JavaScript 杞崲涓?C 浠g爜锛岃€岃繖閲岀殑 natives 鏁扮粍涓殑 C 浠g爜锛屾鏄繖涓瀯寤轰换鍔$殑浜х墿銆傝€屽埌浜嗚繖閲岋紝鎴戜滑缁堜簬鐭ラ亾浜嗚繖涓紪璇戜换鍔$殑浣滅敤浜嗐€?/span>
鐭ラ亾浜嗘簮鐮佺殑鑾峰彇锛岀户缁線涓嬬湅 compile 鏂规硶锛岀湅鐪嬫簮鐮佹槸濡備綍缂栬瘧鐨勶細
// lib/internal/bootstrap_node.js
NativeModule.wrap = function(script) {
return NativeModule.wrapper[0] + script + NativeModule.wrapper[1];
};
NativeModule.wrapper = [
'(function (exports, require, module, __filename, __dirname) { ',
' });'
];
NativeModule.prototype.compile = function() {
var source = NativeModule.getSource(this.id);
source = NativeModule.wrap(source);
this.loading = true;
try {
const fn = runInThisContext(source, {
filename: this.filename,
lineOffset: 0,
displayErrors: true
});
fn(this.exports, NativeModule.require, this, this.filename);
this.loaded = true;
} finally {
this.loading = false;
}
};
// ...
NativeModule.prototype.compile 鍦ㄨ幏鍙栧埌婧愮爜涔嬪悗锛屽畠涓昏鍋氫簡锛氫娇鐢?wrap 鏂规硶澶勭悊婧愪唬鐮侊紝鏈€鍚庤皟鐢?runInThisContext 杩涜缂栬瘧寰楀埌涓€涓嚱鏁帮紝鏈€鍚庢墽琛岃鍑芥暟銆傚叾涓?wrap 鏂规硶锛屾槸缁欐簮浠g爜鍔犱笂浜嗕竴澶翠竴灏撅紝鍏跺疄鐩稿綋浜庢槸灏嗘簮鐮佸寘鍦ㄤ簡涓€涓嚱鏁颁腑锛岃繖涓嚱鏁扮殑鍙傛暟鏈?exports, require, module 绛夈€傝繖灏辨槸涓轰粈涔堟垜浠啓妯″潡鐨勬椂鍊欙紝涓嶉渶瑕佸畾涔?exports, require, module 灏卞彲浠ョ洿鎺ョ敤鐨勫師鍥犮€?/span>
鑷虫灏卞熀鏈娓呮浜?Node.js 鏍稿績妯″潡鐨勫姞杞借繃绋嬨€傝鍒拌繖閲屽ぇ瀹跺彲鑳芥湁涓€涓枒鎯戯紝涓婅堪鍒嗘瀽杩囩▼锛屽ソ鍍忓彧娑夊強鍒颁簡鏍稿績妯″潡涓殑 JavaScript native妯″潡锛岄偅涔堝浜?C/C++ built-in 妯″潡鍛紵
鍏跺疄鏄繖鏍风殑锛屽浜?built-in 妯″潡鑰岃█锛屽畠浠笉鏄€氳繃 require 鏉ュ紩鍏ョ殑锛岃€屾槸閫氳繃 precess.binding('妯″潡鍚?) 寮曞叆鐨勩€備竴鑸垜浠緢灏戝湪鑷繁鐨勪唬鐮佷腑鐩存帴浣跨敤 process.binding 鏉ュ紩鍏uilt-in妯″潡锛岃€屾槸閫氳繃 require 寮曠敤native妯″潡锛岃€?native 妯″潡閲岄潰浼氬紩鍏?built-in 妯″潡銆傛瘮濡傛垜浠父鐢ㄧ殑 buffer 妯″潡锛屽叾鍐呴儴瀹炵幇涓氨寮曞叆浜?C/C++ built-in 妯″潡锛岃繖鏄负浜嗛伩寮€ v8 鐨勫唴瀛橀檺鍒讹細
// lib/buffer.js
'use strict';
// 閫氳繃 process.binding 寮曞叆鍚嶄负 buffer 鐨?C/C++ built-in 妯″潡
const binding = process.binding('buffer');
// ...
杩欐牱锛屾垜浠湪 require('buffer') 鐨勬椂鍊欙紝鍏跺疄鏄棿鎺ョ殑浣跨敤浜?C/C++ built-in 妯″潡銆?/span>
杩欓噷鍐嶆鍑虹幇浜?process.binding锛佷簨瀹炰笂锛宲rocess.binding 杩欎釜鏂规硶瀹氫箟鍦?node.cc 涓細
// src/node.cc
// ...
static void Binding(const FunctionCallbackInfo<Value>& args) {
// ...
node_module* mod = get_builtin_module(*module_v);
// ...
}
// ...
env->SetMethod(process, "binding", Binding);
// ...
Binding 杩欎釜鍑芥暟涓叧閿殑涓€姝ユ槸 get_builtin_module銆傝繖閲岄渶瑕佸啀娆℃彃鍏ヤ粙缁嶄竴涓?C/C++ 鍐呭缓妯″潡鐨勫瓨鍌ㄦ柟寮忥細
鍦?Node.js 涓紝鍐呭缓妯″潡鏄€氳繃涓€涓悕涓?node_module_struct 鐨勭粨鏋勪綋瀹氫箟鐨勩€傛墍浠ョ殑鍐呭缓妯″潡浼氳鏀惧叆涓€涓彨鍋?node_module_list 鐨勬暟缁勪腑銆傝€?process.binding 鐨勪綔鐢紝姝f槸浣跨敤 get_builtin_module 浠庤繖涓暟缁勪腑鍙栧嚭鐩稿簲鐨勫唴寤烘ā鍧椾唬鐮併€?/span>
缁间笂锛屾垜浠氨瀹屾暣浠嬬粛浜嗘牳蹇冩ā鍧楃殑鍔犺浇鍘熺悊锛屼富瑕佹槸鍖哄垎 JavaScript 绫诲瀷鐨?native 妯″潡鍜?C/C++ 绫诲瀷鐨?built-in 妯″潡銆傝繖閲岀粯鍒朵竴寮犲浘鏉ユ弿杩颁竴涓嬫牳蹇冩ā鍧楀姞杞借繃绋嬶細
鑰屽洖蹇嗘垜浠湪鏈€寮€濮嬩粙缁嶇殑锛宯ative 妯″潡鍦ㄦ簮鐮佷腑瀛樻斁鍦?lib/ 鐩綍涓嬶紝鑰?built-in 妯″潡鍦ㄦ簮鐮佷腑瀛樻斁鍦?src/ 鐩綍涓嬶紝涓嬮潰杩欏紶鍥惧垯浠庣紪璇戠殑瑙掑害姊崇悊浜?native 鍜?built-in 妯″潡濡備綍琚紪璇戣繘 Node.js 鍙墽琛屾枃浠讹細
4.2 绗笁鏂规ā鍧楀姞杞藉師鐞?/span>
涓嬮潰璁╂垜浠户缁垎鏋愮浜屼釜鍒嗘敮锛屽亣璁炬垜浠殑 index.js 涓?require 鐨勪笉鏄?http锛岃€屾槸涓€涓敤鎴疯嚜瀹氫箟妯″潡锛岄偅涔堝湪 module.js 涓? 鎴戜滑浼氳蛋鍒?tryModuleLoad 鏂规硶涓細
// lib/module.js
// ...
function tryModuleLoad(module, filename) {
var threw = true;
try {
module.load(filename);
threw = false;
} finally {
if (threw) {
delete Module._cache[filename];
}
}
}
// ...
Module.prototype.load = function(filename) {
debug('load %j for module %j', filename, this.id);
assert(!this.loaded);
this.filename = filename;
this.paths = Module._nodeModulePaths(path.dirname(filename));
var extension = path.extname(filename) || '.js';
if (!Module._extensions[extension]) extension = '.js';
Module._extensions[extension](this, filename);
this.loaded = true;
};
// ...
杩欓噷鐪嬪埌锛宼ryModuleLoad 涓疄闄呰皟鐢ㄤ簡 Module.prototype.load 瀹氫箟鐨勬柟娉曪紝杩欎釜鏂规硶涓昏鍋氱殑浜嬫儏鏄紝妫€娴?filename 鐨勬墿灞曞悕锛岀劧鍚庨拡瀵逛笉鍚岀殑鎵╁睍鍚嶏紝璋冪敤涓嶅悓鐨?Module._extensions 鏂规硶鏉ュ姞杞姐€佺紪璇戞ā鍧椼€傛帴鐫€鎴戜滑鐪嬬湅 Module._extensions:
// lib/module.js
// ...
// Native extension for .js
Module._extensions['.js'] = function(module, filename) {
var content = fs.readFileSync(filename, 'utf8');
module._compile(internalModule.stripBOM(content), filename);
};
// Native extension for .json
Module._extensions['.json'] = function(module, filename) {
var content = fs.readFileSync(filename, 'utf8');
try {
module.exports = JSON.parse(internalModule.stripBOM(content));
} catch (err) {
err.message = filename + ': ' + err.message;
throw err;
}
};
//Native extension for .node
Module._extensions['.node'] = function(module, filename) {
return process.dlopen(module, path._makeLong(filename));
};
// ...
鍙互鐪嬪嚭锛屼竴鍏辨敮鎸佷笁绉嶇被鍨嬬殑妯″潡鍔犺浇锛?js, .json, .node銆傚叾涓?.json 绫诲瀷鐨勬枃浠跺姞杞芥柟娉曟槸鏈€绠€鍗曠殑锛岀洿鎺ヨ鍙栨枃浠跺唴瀹癸紝鐒跺悗 JSON.parse 涔嬪悗杩斿洖瀵硅薄鍗冲彲銆?/span>
涓嬮潰鏉ョ湅瀵?.js 鐨勫鐞嗭紝棣栧厛涔熸槸閫氳繃 fs 妯″潡鍚屾璇诲彇鏂囦欢鍐呭锛岀劧鍚庤皟鐢ㄤ簡 module._compile锛岀湅鐪嬬浉鍏充唬鐮侊細
// lib/module.js
// ...
Module.wrap = NativeModule.wrap;
// ...
Module.prototype._compile = function(content, filename) {
// ...
// create wrapper function
var wrapper = Module.wrap(content);
var compiledWrapper = vm.runInThisContext(wrapper, {
filename: filename,
lineOffset: 0,
displayErrors: true
});
// ...
var result = compiledWrapper.apply(this.exports, args);
if (depth === 0) stat.cache = null;
return result;
};
// ...
棣栧厛璋冪敤 Module.wrap 瀵规簮浠g爜杩涜鍖呰9锛屼箣鍚庤皟鐢?vm.runInThisContext 鏂规硶杩涜缂栬瘧鎵ц锛屾渶鍚庤繑鍥?exports 鐨勫€笺€傝€屼粠 Module.wrap = NativeModule.wrap 杩欎竴鍙ュ彲浠ョ湅鍑猴紝绗笁鏂规ā鍧楃殑 wrap 鏂规硶锛屽拰鏍稿績妯″潡鐨?wrap 鏂规硶鏄竴鏍风殑銆傛垜浠洖蹇嗕竴涓嬪垰鎵嶈鍒扮殑鏍稿績js妯″潡鍔犺浇鍏抽敭浠g爜锛?/span>
// lib/internal/bootstrap_node.js
NativeModule.wrap = function(script) {
return NativeModule.wrapper[0] + script + NativeModule.wrapper[1];
};
NativeModule.wrapper = [
'(function (exports, require, module, __filename, __dirname) { ',
' });'
];
NativeModule.prototype.compile = function() {
var source = NativeModule.getSource(this.id);
source = NativeModule.wrap(source);
this.loading = true;
try {
const fn = runInThisContext(source, {
filename: this.filename,
lineOffset: 0,
displayErrors: true
});
fn(this.exports, NativeModule.require, this, this.filename);
this.loaded = true;
} finally {
this.loading = false;
}
};
涓ゅ帰瀵规瘮锛屽彂鐜颁簩鑰呭婧愪唬鐮佺殑缂栬瘧鎵ц鍑犱箮鏄竴妯′竴鏍风殑銆備粠鏁翠綋娴佺▼涓婃潵璁诧紝鏍稿績 JavaScript 妯″潡涓庣涓夋柟 JavaScript 妯″潡鏈€澶х殑涓嶅悓灏辨槸锛屾牳蹇?JavaScript 妯″潡婧愪唬鐮佹槸閫氳繃 process.binding('natives') 浠庡唴瀛樹腑鑾峰彇鐨勶紝鑰岀涓夋柟 JavaScript 妯″潡婧愪唬鐮佹槸閫氳繃 fs.readFileSync 鏂规硶浠庢枃浠朵腑璇诲彇鐨勩€?/span>
鏈€鍚庯紝鍐嶆潵鐪嬩竴涓嬪姞杞界涓夋柟 C/C++妯″潡锛?node鍚庣紑锛夈€傜洿瑙備笂鏉ョ湅锛屽緢绠€鍗曪紝灏辨槸璋冪敤浜?process.dlopen 鏂规硶銆傝繖涓柟娉曠殑瀹氫箟鍦?node.cc 涓細
// src/node.cc
// ...
env->SetMethod(process, "dlopen", DLOpen);
// ...
void DLOpen(const FunctionCallbackInfo<Value>& args) {
// ...
const bool is_dlopen_error = uv_dlopen(*filename, &lib);
// ...
}
// ...
瀹為檯涓婃渶缁堣皟鐢ㄤ簡 DLOpen 鍑芥暟锛岃鍑芥暟涓渶閲嶈鐨勬槸浣跨敤 uv_dlopen 鏂规硶鎵撳紑鍔ㄦ€侀摼鎺ュ簱锛岀劧鍚庡 C/C++ 妯″潡杩涜鍔犺浇銆倁v_dlopen 鏂规硶鏄畾涔夊湪 libuv 搴撲腑鐨勩€俵ibuv 搴撴槸涓€涓法骞冲彴鐨勫紓姝?IO 搴撱€傚浜庢墿灞曟ā鍧楃殑鍔ㄦ€佸姞杞借繖閮ㄥ垎鍔熻兘锛屽湪 *nix 骞冲彴涓嬶紝瀹為檯涓婅皟鐢ㄧ殑鏄?dlfcn.h 涓畾涔夌殑 dlopen() 鏂规硶锛岃€屽湪 Windows 涓嬶紝鍒欎负 LoadLibraryExW() 鏂规硶锛屽湪涓や釜骞冲彴涓嬶紝浠栦滑鍔犺浇鐨勫垎鍒槸 .so 鍜?.dll 鏂囦欢锛岃€?Node.js 涓紝杩欎簺鏂囦欢缁熶竴琚懡鍚嶄簡 .node 鍚庣紑锛屽睆钄戒簡骞冲彴鐨勫樊寮傘€?/span>
鍏充簬 libuv 搴擄紝鏄?Node.js 寮傛 IO 鐨勬牳蹇冮┍鍔ㄥ姏锛岃繖涓€鍧楁湰韬氨鍊煎緱涓撻棬浣滀负涓€涓笓棰樻潵鐮旂┒锛岃繖閲屽氨涓嶅睍寮€璁蹭簡銆?/span>
鍒版涓烘锛屾垜浠悊娓呮浜嗕笁绉嶇涓夋柟妯″潡鐨勫姞杞姐€佺紪璇戣繃绋嬨€?/span>
5. C/C++ 鎵╁睍妯″潡鐨勫紑鍙戜互鍙婂簲鐢ㄥ満鏅?/span>
涓婃枃鍒嗘瀽浜?Node.js 褰撲腑鍚勭被妯″潡鐨勫姞杞芥祦绋嬨€傚ぇ瀹跺浜?JavaScript 妯″潡鐨勫紑鍙戝簲璇ユ槸椹捐交灏辩啛浜嗭紝浣嗘槸瀵逛簬 C/C++ 鎵╁睍妯″潡寮€鍙戝彲鑳借繕鏈変簺闄岀敓銆傝繖涓€鑺傚氨绠€鍗曚粙缁嶄竴涓嬫墿灞曟ā鍧楃殑寮€鍙戯紝骞惰皥璋堝叾搴旂敤鍦烘櫙銆?/span>
鍏充簬 Node.js 鎵╁睍妯″潡鐨勫紑鍙戯紝鍦?Node.js 瀹樼綉鏂囨。涓笓闂ㄦ湁涓€鑺備簣浠ヤ粙缁嶏紝澶у鍙互绉绘瀹樼綉鏂囨。鏌ョ湅锛歨ttps://nodejs.org/docs/latest-v6.x/api/addons.html 銆傝繖閲屼粎浠呬互鍏朵腑鐨?hello world 渚嬪瓙鏉ヤ粙缁嶄竴涓嬬紪鍐欐墿灞曟ā鍧楃殑涓€浜涙瘮杈冮噸瑕佺殑姒傚康锛?/span>
鍋囪鎴戜滑甯屾湜閫氳繃鎵╁睍妯″潡鏉ュ疄鐜颁竴涓瓑鍚屼簬濡備笅 JavaScript 鍑芥暟鐨勫姛鑳斤細
module.exports.hello = () => 'world';
棣栧厛鍒涘缓涓€涓?hello.cc 鏂囦欢锛岀紪鍐欏涓嬩唬鐮侊細
// hello.cc
#include <node.h>
namespace demo {
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;
void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));
}
void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "hello", Method);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, init)
} // namespace demo
鏂囦欢铏界煭锛屼絾鏄凡缁忓嚭鐜颁簡涓€浜涙垜浠瘮杈冮檶鐢熺殑浠g爜锛岃繖閲屼竴涓€浠嬬粛涓€涓嬶紝瀵逛簬浜嗚В鎵╁睍妯″潡鍩虹鐭ヨ瘑杩樻槸寰堟湁甯姪鐨勩€?/span>
棣栧厛鍦ㄥ紑澶村紩鍏ヤ簡 node.h锛岃繖涓槸缂栧啓 Node.js 鎵╁睍鏃跺繀鐢ㄧ殑澶存枃浠讹紝閲岄潰鍑犱箮鍖呭惈浜嗘垜浠墍闇€瑕佺殑鍚勭搴撱€佹暟鎹被鍨嬨€?/span>
鍏舵锛岀湅鍒颁簡寰堝 using v8:xxx 杩欐牱鐨勪唬鐮併€傛垜浠煡閬擄紝Node.js 鏄熀浜?v8 寮曟搸鐨勶紝鑰?v8 寮曟搸锛屽氨鏄敤 C++ 鏉ュ啓鐨勩€傛垜浠寮€鍙?C++ 鎵╁睍妯″潡锛屼究闇€瑕佷娇鐢?v8 涓彁渚涚殑寰堝鏁版嵁绫诲瀷锛岃€岃繖涓€绯诲垪浠g爜锛屾鏄0鏄庝簡闇€瑕佷娇鐢?v8 鍛藉悕绌洪棿涓嬬殑杩欎簺鏁版嵁绫诲瀷銆?/span>
鐒跺悗鏉ョ湅 Method 鏂规硶锛屽畠鐨勫弬鏁扮被鍨?FunctionCallbackInfo
鎺ヤ笅鏉ラ渶瑕佸畾涔夋墿灞曟ā鍧楃殑鍒濆鍖栨柟娉曪紝杩欓噷鏄?Init 鍑芥暟锛屽彧鏈変竴鍙ョ畝鍗曠殑 NODE_SET_METHOD(exports, "hello", Method);锛屼唬琛ㄧ粰 exports 璧嬩簣涓€涓悕涓?hello 鐨勬柟娉曪紝杩欎釜鏂规硶鐨勫叿浣撳畾涔夊氨鏄?Method 鍑芥暟銆?/span>
鏈€鍚庢槸涓€涓畯瀹氫箟锛歂ODE_MODULE(NODE_GYP_MODULE_NAME, init)锛岀涓€涓弬鏁版槸甯屾湜鐨勬墿灞曟ā鍧楀悕绉帮紝绗簩涓弬鏁板氨鏄妯″潡鐨勫垵濮嬪寲鏂规硶銆?/span>
涓轰簡缂栬瘧杩欎釜妯″潡锛屾垜浠渶瑕侀€氳繃npm瀹夎 node-gyp 缂栬瘧宸ュ叿銆傝宸ュ叿灏?Google 鐨?gyp 宸ュ叿灏佽锛岀敤鏉ユ瀯寤?Node.js 鎵╁睍銆傚畨瑁呰繖涓伐鍏峰悗锛屾垜浠湪婧愮爜鏂囦欢澶逛笅闈㈠鍔犱竴涓悕涓?bingding.gyp 鐨勯厤缃枃浠讹紝瀵逛簬鎴戜滑杩欎釜渚嬪瓙锛屾枃浠跺彧瑕佽繖鏍峰啓锛?/span>
{
"targets": [
{
"target_name": "addon",
"sources": [ "hello.cc" ]
}
]
}
杩欐牱锛岃繍琛?node-gyp build 鍗冲彲缂栬瘧鎵╁睍妯″潡銆傚湪杩欎釜杩囩▼涓紝node-gyp 杩樹細鍘绘寚瀹氱洰褰曪紙涓€鑸槸 ~/.node-gyp锛変笅闈㈡悳鎴戜滑褰撳墠 Node.js 鐗堟湰鐨勪竴浜涘ご鏂囦欢鍜屽簱鏂囦欢锛屽鏋滀笉瀛樺湪锛屽畠杩樹細甯垜浠幓 Node.js 瀹樼綉涓嬭浇銆傝繖鏍凤紝鍦ㄧ紪鍐欐墿灞曠殑鏃跺€欙紝閫氳繃 #include <>锛屾垜浠氨鍙互鐩存帴浣跨敤鎵€鏈?Node.js 鐨勫ご鏂囦欢浜嗐€?/span>
濡傛灉缂栬瘧鎴愬姛锛屼細鍦ㄥ綋鍓嶆枃浠跺す鐨?build/Release/ 璺緞涓嬬湅鍒颁竴涓?addon.node锛岃繖涓氨鏄垜浠紪璇戝ソ鐨勫彲 require 鐨勬墿灞曟ā鍧椼€?/span>
浠庝笂闈㈢殑渚嬪瓙涓紝鎴戜滑鑳藉ぇ浣撶湅鍑烘墿灞曟ā鍧楃殑杩愪綔妯″紡锛屽畠鍙互鎺ユ敹鏉ヨ嚜 JavaScript 鐨勫弬鏁帮紝鐒跺悗涓棿鍙互璋冪敤 C/C++ 璇█鐨勮兘鍔涘幓鍋氬悇绉嶈繍绠椼€佸鐞嗭紝鐒跺悗鏈€鍚庡彲浠ュ皢缁撴灉鍐嶈繑鍥炵粰 JavaScript銆?/span>
鍊煎緱娉ㄦ剰鐨勬槸锛屼笉鍚?Node.js 鐗堟湰锛屼緷璧栫殑 v8 鐗堟湰涓嶅悓锛屽鑷村緢澶?API 浼氭湁宸埆锛屽洜姝や娇鐢ㄥ師鐢?C/C++ 寮€鍙戞墿灞曠殑杩囩▼涓紝涔熼渶瑕侀拡瀵逛笉鍚岀増鏈殑 Node.js 鍋氬吋瀹瑰鐞嗐€傛瘮濡傝锛屽0鏄庝竴涓嚱鏁帮紝鍦?v6.x 鍜?v0.12 浠ヤ笅鐨勭増鏈腑锛屽垎鍒渶瑕佽繖鏍峰啓锛?/span>
Handle
Example(const Arguments& args); // 0.10.x void Example(FunctionCallbackInfo
& args); // 6.x
鍙互鐪嬪埌锛屽嚱鏁扮殑澹版槑锛屽寘鎷嚱鏁颁腑鍙傛暟鐨勫啓娉曪紝閮戒笉灏界浉鍚屻€傝繖璁╀汉涓嶇敱寰楁兂璧蜂簡鍦?Node.js 寮€鍙戜腑锛屼负浜嗗啓 ES6锛屼篃鏄渶瑕佷娇鐢?Babel 鏉ュ府蹇欒繘琛屽吋瀹规€ц浆鎹€傞偅涔堝湪 Node.js 鎵╁睍寮€鍙戦鍩燂紝鏈夋病鏈夌被浼?Babel 杩欐牱甯姪鎴戜滑澶勭悊鍏煎鎬ч棶棰樼殑搴撳憿锛熺瓟妗堟槸鑲畾鐨勶紝瀹冪殑鍚嶅瓧鍙仛 NAN (Native Abstraction for Node.js)銆傚畠鏈川涓婃槸涓€鍫嗗畯锛岃兘澶熷府鍔╂垜浠娴?Node.js 鐨勪笉鍚岀増鏈紝骞惰皟鐢ㄤ笉鍚岀殑 API銆備緥濡傦紝鍦?NAN 鐨勫府鍔╀笅锛屽0鏄庝竴涓嚱鏁帮紝鎴戜滑涓嶉渶瑕佸啀鑰冭檻 Node.js 鐗堟湰锛岃€屽彧闇€瑕佸啓涓€娈佃繖鏍风殑浠g爜锛?/span>
#include
NAN_METHOD(Example) {
// ...
}
NAN 鐨勫畯浼氬湪缂栬瘧鐨勬椂鍊欒嚜鍔ㄥ垽鏂紝鏍规嵁 Node.js 鐗堟湰鐨勪笉鍚屽睍寮€涓嶅悓鐨勭粨鏋滐紝浠庤€岃В鍐充簡鍏煎鎬ч棶棰樸€傚 NAN 鏇磋缁嗙殑浠嬬粛锛屾劅鍏磋叮鐨勫悓瀛﹀彲浠ョЩ姝ヨ椤圭洰鐨?github 涓婚〉锛歨ttps://github.com/nodejs/nan銆?/span>
浠嬬粛浜嗚繖涔堝鎵╁睍妯″潡鐨勫紑鍙戯紝鍙兘鏈夊悓瀛︿細闂簡锛屽儚杩欎簺鎵╁睍妯″潡瀹炵幇鐨勫姛鑳斤紝鐪嬭捣鏉ヤ技涔庣敤js涔熷彲浠ュ緢蹇殑瀹炵幇锛屼綍蹇呭ぇ璐瑰懆鎶樺幓寮€鍙戞墿灞曞憿锛熻繖灏卞紩鍑轰簡涓€涓棶棰橈細C/C++ 鎵╁睍鐨勯€傜敤鍦烘櫙銆?/span>
绗旇€呭湪杩欓噷澶ф褰掔撼浜嗗嚑绫?C/C++ 閫傜敤鐨勬儏鏅細
璁$畻瀵嗛泦鍨嬪簲鐢ㄣ€傛垜浠煡閬擄紝Node.js 鐨勭紪绋嬫ā鍨嬫槸鍗曠嚎绋?+ 寮傛 IO锛屽叾涓崟绾跨▼瀵艰嚧浜嗗畠鍦ㄨ绠楀瘑闆嗗瀷搴旂敤涓婃槸涓€涓蒋鑲嬶紝澶ч噺鐨勮绠椾細闃诲 JavaScript 涓荤嚎绋嬶紝瀵艰嚧鏃犳硶鍝嶅簲鍏朵粬璇锋眰銆傚浜庤繖绉嶅満鏅紝灏卞彲浠ヤ娇鐢?C/C++ 鎵╁睍妯″潡锛屾潵鍔犲揩璁$畻閫熷害锛屾瘯绔燂紝铏界劧 v8 寮曟搸鐨勬墽琛岄€熷害寰堝揩锛屼絾缁堢┒杩樻槸姣斾笉杩?C/C++銆傚彟澶栵紝浣跨敤 C/C++锛岃繕鍙互鍏佽鎴戜滑寮€澶氱嚎绋嬶紝閬垮厤闃诲 JavaScript 涓荤嚎绋嬶紝绀惧尯閲岀洰鍓嶅凡缁忔湁涓€浜涘熀浜庢墿灞曟ā鍧楃殑 Node.js 澶氱嚎绋嬫柟妗堬紝鍏朵腑鏈€鍙楁杩庣殑鍙兘鏄竴涓彨鍋?thread-a-gogo 鐨勯」鐩紝鍏蜂綋鍙互绉绘 github锛歨ttps://github.com/xk/node-threads-a-gogo銆?/span>
鍐呭瓨娑堣€楄緝澶х殑搴旂敤銆侼ode.js 鏄熀浜?v8 鐨勶紝鑰?v8 涓€寮€濮嬫槸涓烘祻瑙堝櫒璁捐鐨勶紝鎵€浠ュ叾鍦ㄥ唴瀛樻柟闈㈡槸鏈夋瘮杈冧弗鏍肩殑闄愬埗鐨勶紝鎵€浠ュ浜庝竴浜涢渶瑕佽緝澶у唴瀛樼殑搴旂敤锛岀洿鎺ュ熀浜?v8 鍙兘浼氭湁浜涘姏涓嶄粠蹇冿紝杩欎釜鏃跺€欏氨闇€瑕佷娇鐢ㄦ墿灞曟ā鍧楋紝鏉ョ粫寮€ v8 鐨勫唴瀛橀檺鍒讹紝鏈€鍏稿瀷鐨勫氨鏄垜浠父鐢ㄧ殑 buffer.js 妯″潡锛屽叾搴曞眰涔熸槸璋冪敤浜?C++锛屽湪 C++ 鐨勫眰闈笂鍘荤敵璇峰唴瀛橈紝閬垮厤 v8 鍐呭瓨鐡堕銆?/span>
鍏充簬绗竴鐐癸紝绗旇€呰繖閲屼篃鍒嗗埆鐢ㄥ師鐢?Node.js 浠ュ強 Node.js 鎵╁睍瀹炵幇浜嗕竴涓祴璇曚緥瀛愭潵瀵规瘮璁$畻鎬ц兘銆傛祴璇曠敤渚嬫槸缁忓吀鐨勮绠楁枑娉㈤偅濂戞暟鍒楋紝棣栧厛浣跨敤 Node.js 鍘熺敓璇█瀹炵幇涓€涓绠楁枑娉㈤偅濂戞暟鍒楃殑鍑芥暟锛屽彇鍚嶄负 fibJs锛?/span>
function fibJs(n) {
if (n === 0 || n === 1) {
return n;
}
else {
return fibJs(n - 1) + fibJs(n - 2);
}
}
鐒跺悗浣跨敤 C++ 缂栧啓涓€涓疄鐜板悓鏍峰姛鑳界殑鎵╁睍鍑芥暟锛屽彇鍚?fibC:
// fibC.cpp
#include
#include
using namespace v8;
int fib(int n) {
if (n == 0 || n ==1) {
return n;
}
else {
return fib(n - 1) + fib(n - 2);
}
}
void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
int n = args[0]->NumberValue();
int result = fib(n);
args.GetReturnValue().Set(result);
}
void init(Local < Object > exports, Local < Object > module) {
NODE_SET_METHOD(module, "exports", Method);
}
NODE_MODULE(fibC, init)
鍦ㄦ祴璇曚腑锛屽垎鍒娇鐢ㄨ繖涓や釜鍑芥暟璁$畻浠?1~40 鐨勬枑娉㈤偅濂戞暟鍒?
function testSpeed(fn, testName) {
var start = Date.now();
for (var i = 0; i < 40; i++) {
fn(i);
}
var spend = Date.now() - start;
console.log(testName, 'spend time: ', spend);
}
// 浣跨敤鎵╁睍妯″潡娴嬭瘯
var fibC = require('./build/Release/fibC'); // 杩欓噷鏄墿灞曟ā鍧楃紪璇戜骇鐗╃殑瀛樻斁璺緞
testSpeed(fibC, 'c++ test:');
// 浣跨敤 JavaScript 鍑芥暟杩涜娴嬭瘯
function fibJs(n) {
if (n === 0 || n === 1) {
return n;
}
else {
return fibJs(n - 1) + fibJs(n - 2);
}
}
testSpeed(fibJs, 'js test:');
// c++ test: spend time: 1221
// js test: spend time: 2611
澶氭娴嬭瘯锛屾墿灞曟ā鍧楀钩鍧囪姳璐规椂闀垮ぇ绾?1.2s锛岃€?JavaScript 妯″潡鑺辫垂鏃堕暱澶х害 2.6s锛屽彲瑙佸湪姝ゅ満鏅笅锛孋/C++ 鎵╁睍鎬ц兘杩樻槸瑕佸揩涓婁笉灏戠殑銆?/span>
褰撶劧锛岃繖鍑犵偣鍙槸鍩轰簬绗旇€呯殑璁よ瘑銆傚湪瀹為檯寮€鍙戣繃绋嬩腑锛屽ぇ瀹跺湪閬囧埌闂鐨勬椂鍊欙紝涔熷彲浠ュ皾璇曠潃鑰冭檻濡傛灉浣跨敤 C/C++ 鎵╁睍妯″潡锛岄棶棰樻槸涓嶆槸鑳藉寰楀埌鏇村ソ鐨勮В鍐炽€?/span>
缁撹
鏂囩珷璇诲埌杩欓噷锛屾垜浠啀鍥炲幓鐪嬩竴涓嬩竴寮€濮嬫彁鍑虹殑閭d簺闂锛屾槸鍚﹀湪鏂囩珷鍒嗘瀽鐨勮繃绋嬩腑閮藉緱鍒颁簡瑙g瓟锛熷啀鏉ュ洖椤句竴涓嬫湰鏂囩殑閫昏緫鑴夌粶锛?/span>
棣栧厛浠ヤ竴涓猲ode index.js 鐨勮繍琛屽師鐞嗗紑濮嬶紝鎸囧嚭浣跨敤node 杩愯涓€涓枃浠讹紝绛夊悓浜庣珛鍗虫墽琛屼竴娆equire 銆?/span>
鐒跺悗寮曞嚭浜唍ode涓殑require鏂规硶锛屽湪杩欓噷锛屽尯鍒嗕簡鏍稿績妯″潡銆佸唴寤烘ā鍧楀拰闈炴牳蹇冩ā鍧楀嚑绉嶆儏鍐碉紝鍒嗗埆璇﹁堪浜嗗姞杞姐€佺紪璇戠殑娴佺▼鍘熺悊銆傚湪杩欎釜杩囩▼涓紝杩樺垎鍒秹鍙婂埌浜嗘ā鍧楄矾寰勮В鏋愩€佹ā鍧楃紦瀛樼瓑绛夌煡璇嗙偣鐨勬弿杩般€?/span>
鏈€鍚庝粙缁嶄簡澶у涓嶅お鐔熸倝鐨刢/c++鎵╁睍妯″潡鐨勫紑鍙戯紝骞剁粨鍚堜竴涓€ц兘瀵规瘮鐨勪緥瀛愭潵璇存槑鍏堕€傜敤鍦烘櫙銆?/span>
浜嬪疄涓婏紝閫氳繃瀛︿範 Node.js 妯″潡鍔犺浇娴佺▼锛屾湁鍔╀簬鎴戜滑鏇存繁鍒荤殑浜嗚В Node.js 搴曞眰鐨勮繍琛屽師鐞嗭紝鑰屾帉鎻′簡鍏朵腑鐨勬墿灞曟ā鍧楀紑鍙戯紝骞跺浼氬湪閫傚綋鐨勫満鏅笅浣跨敤锛屽垯鑳藉浣垮緱鎴戜滑寮€鍙戝嚭鐨?Node.js 搴旂敤鎬ц兘鏇撮珮銆?/span>
瀛︿範 Node.js 鍘熺悊鏄竴鏉℃极闀跨殑璺緞銆傚缓璁簡瑙d簡搴曞眰妯″潡鏈哄埗鐨勮鑰咃紝鍙互鍘绘洿娣卞叆鐨勫涔?v8, libuv 绛夌瓑鐭ヨ瘑锛屽浜庣簿閫?Node.js锛屽繀灏嗗ぇ鏈夎(鐩娿€?/span>
鍏嶈垂璧犻€侀珮绾у墠绔棰?璁╀綘蹇€熸檵绾?/span>
鏈€鏉冨▉
鏈€鍏ㄩ潰
鏈€绮惧僵
瑙夊緱鏈枃瀵逛綘鏈夊府鍔╋紵璇峰垎浜粰鏇村浜?/span>
鍏虫敞銆屽墠绔ぇ鍏ㄣ€嶏紝鎻愬崌鍓嶇鎶€鑳?/span>
以上是关于的主要内容,如果未能解决你的问题,请参考以下文章