Posted 鍓嶇绀惧尯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了相关的知识,希望对你有一定的参考价值。


鐐瑰嚮涓婃柟 钃濊壊瀛?/strong>鍏虫敞鎴戜滑~

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>


  1. 鏍规嵁鏂囦欢鍚嶏紝璋冪敤 Module._resolveFilename 瑙f瀽鏂囦欢鐨勮矾寰?/span>

  2. 鏌ョ湅缂撳瓨 Module._cache 涓槸鍚︽湁璇ユā鍧楋紝濡傛灉鏈夛紝鐩存帴杩斿洖

  3. 閫氳繃 NativeModule.nonInternalExists 鍒ゆ柇璇ユā鍧楁槸鍚︿负鏍稿績妯″潡锛屽鏋滄牳蹇冩ā鍧楋紝璋冪敤鏍稿績妯″潡鐨勫姞杞芥柟娉?NativeModule.require

  4. 濡傛灉涓嶆槸鏍稿績妯″潡锛屾柊鍒涘缓涓€涓?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>


[姣忔棩涓€璇籡婧愮爜鍒嗘瀽 Node.js 妯″潡鍔犺浇涓庤繍琛屽師鐞?></p> 
<p><span class=

鑰屽湪鏂囦欢璺緞瑙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 鐨勬祦绋嬪涓嬶細


  1. 鍒ゆ柇 cache 涓槸鍚﹀凡缁忓姞杞借繃锛屽鏋滄湁锛岀洿鎺ヨ繑鍥?exports

  2. 鏂板缓 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 妯″潡銆傝繖閲岀粯鍒朵竴寮犲浘鏉ユ弿杩颁竴涓嬫牳蹇冩ā鍧楀姞杞借繃绋嬶細


[姣忔棩涓€璇籡婧愮爜鍒嗘瀽 Node.js 妯″潡鍔犺浇涓庤繍琛屽師鐞?></p> 
<p><br></p> 
<p><br></p> 
<p><span class=鑰屽洖蹇嗘垜浠湪鏈€寮€濮嬩粙缁嶇殑锛宯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 & args锛岃繖涓?args 灏辨槸浠?JavaScript 涓紶鍏ョ殑鍙傛暟锛屽悓鏃讹紝濡傛灉鎯冲湪 Method 涓负 JavaScript 杩斿洖鍙橀噺锛屽垯闇€瑕佽皟鐢?args.GetReturnValue().Set 鏂规硶銆?


鎺ヤ笅鏉ラ渶瑕佸畾涔夋墿灞曟ā鍧楃殑鍒濆鍖栨柟娉曪紝杩欓噷鏄?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++ 閫傜敤鐨勬儏鏅細


  1. 璁$畻瀵嗛泦鍨嬪簲鐢ㄣ€傛垜浠煡閬擄紝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>

  2. 鍐呭瓨娑堣€楄緝澶х殑搴旂敤銆侼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>


    鎵撻€犲浗鍐呮渶澶х殑鍓嶇绀惧尯
QR Code
鍓嶇

鏈€鏉冨▉


鏈€鍏ㄩ潰


鏈€绮惧僵


鍓嶇绀惧尯



瑙夊緱鏈枃瀵逛綘鏈夊府鍔╋紵璇峰垎浜粰鏇村浜?/span>

鍏虫敞銆屽墠绔ぇ鍏ㄣ€嶏紝鎻愬崌鍓嶇鎶€鑳?/span>

以上是关于的主要内容,如果未能解决你的问题,请参考以下文章

Python 操作Redis

python爬虫入门----- 阿里巴巴供应商爬虫

Python词典设置默认值小技巧

《python学习手册(第4版)》pdf

Django settings.py 的media路径设置

Python中的赋值,浅拷贝和深拷贝的区别