最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

用C/C++來實現(xiàn) Node.js 的模塊(一)

 更新時間:2014年09月24日 16:33:31   投稿:hebedich  
這篇文章的主要內(nèi)容其實簡而言之就是——用C/C++來實現(xiàn) Node.js 的模塊,非常的不錯,有需要的朋友可以參考下

 N久之前的一個坑——用 Node.js 來重構(gòu) NBUT 的 Online Judge,包括評測端也得重構(gòu)一遍。(至于什么時候完成大家就不要關心了,(/‵Д′)/~ ╧╧

  總之我們現(xiàn)在要做的其實簡而言之就是——用C/C++來實現(xiàn) Node.js 的模塊。

準備工作

  工欲善其事,必先~~耍流氓~~利其器。

node-gyp

  首先你需要一個 node-gyp 模塊。

  在任意角落,執(zhí)行:

復制代碼 代碼如下:

$ npm install node-gyp -g

   在進行一系列的 blahblah 之后,你就安裝好了。

Python

  然后你需要有個 python 環(huán)境。

  自己去官網(wǎng)搞一個來。


注意: 根據(jù) node-gyp 的GitHub顯示,請務必保證你的 python 版本介于 2.5.0 和 3.0.0 之間。
 
編譯環(huán)境

  嘛嘛,我就偷懶點不細寫了,還請自己移步到 node-gyp 去看編譯器的需求。并且倒騰好。

入門

  我就拿官網(wǎng)的入門 Hello World說事兒了。

Hello World

  請準備一個 C++ 文件,比如就叫 ~~sb.cc~~ hello.cc。

  然后我們一步步來,先往里面搞出頭文件和定義好命名空間:

復制代碼 代碼如下:

#include <node.h>
#include <v8.h>
using namespace v8;

 主要函數(shù)

  接下去我們寫一個函數(shù),其返回值是 Handle<Value>。

復制代碼 代碼如下:

Handle<Value> Hello(const Arguments& args)
{
    //... 嗷嗷待寫
}

   然后我來粗粗解析一下這些東西:

Handle<Value>

  做人要有節(jié)操,我事先申明我是從這里(@fool)參考的。


V8 里使用 Handle 類型來托管 JavaScript 對象,與 C++ 的 std::sharedpointer 類似,Handle 類型間的賦值均是直接傳遞對象引用,但不同的是,V8 使用自己的 GC 來管理對象生命周期,而不是智能指針常用的引用計數(shù)。

JavaScript 類型在 C++ 中均有對應的自定義類型,如 String 、 Integer 、 Object 、 Date 、 Array 等,嚴格遵守在 JavaScript 中的繼承關系。 C++ 中使用這些類型時,必須使用 Handle 托管,以使用 GC 來管理它們的生命周期,而不使用原生棧和堆。
 
  而這個所謂的 Value ,從 V8 引擎的頭文件 v8.h 中的各種繼承關系中可以看出來,其實就是 JavaScript 中各種對象的基類。

  在了解了這件事之后,我們大致能明白上面那段函數(shù)的申明的意思就是說,我們寫一個 Hello 函數(shù),其返回的是一個不定類型的值。


注意: 我們只能返回特定的類型,即在 Handle 托管下的 String 啊 Integer 啊等等等等。
 
Arguments

  這個就是傳入這個函數(shù)的參數(shù)了。我們都知道在 Node.js 中,參數(shù)個數(shù)是亂來的。而這些參數(shù)傳進去到 C++ 中的時候,就轉(zhuǎn)變成了這個 Arguments 類型的對象了。

  具體的用法我們在后面再說,在這里只需要明白這個是個什么東西就好。(為毛要賣關子?因為 Node.js 官方文檔中的例子就是分開來講的,我現(xiàn)在只是講第一個 Hello World 的例子而已( ´థ౪థ)σ

添磚加瓦

  接下去我們就開始添磚加瓦了。就最簡單的兩句話:

復制代碼 代碼如下:

Handle<Value> Hello(const Arguments& args)
{
    HandleScope scope;
    return scope.Close(String::New("world"));
}

   這兩句話是什么意思呢?大致的意思就是返回一個 Node.js 中的字符串 "world"。

HandleScope

  同參考自這里。


Handle 的生命周期和 C++ 智能指針不同,并不是在 C++ 語義的 scope 內(nèi)生存(即{} 包圍的部分),而需要通過 HandleScope 手動指定。HandleScope 只能分配在棧上,HandleScope 對象聲明后,其后建立的 Handle 都由 HandleScope 來管理生命周期,HandleScope 對象析構(gòu)后,其管理的 Handle 將由 GC 判斷是否回收。
 
  所以呢,我們得在需要管理他的生命周期的時候申明這個 Scope 。好的,那么為什么我們的代碼不這么寫呢?

復制代碼 代碼如下:

Handle<Value> Hello(const Arguments& args)
{
    HandleScope scope;
    return String::New("world");
}

   因為當函數(shù)返回時,scope 會被析構(gòu),其管理的Handle也都將被回收,所以這個 String 就會變得沒有意義。

  所以呢 V8 就想出了個神奇的點子——HandleScope::Close(Handle<T> Value) 函數(shù)!這個函數(shù)的用處就是關閉這個 Scope 并且把里面的參數(shù)轉(zhuǎn)交給上一個 Scope 管理,也就是進入這個函數(shù)前的 Scope。

  于是就有了我們之前的代碼 scope.Close(String::New("world"));。

String::New

  這個 String 類所對應的就是 Node.js 中原生的字符串類。繼承自 Value 類。與此類似,還有:

 •Array
•Integer
•Boolean
•Object
•Date
•Number
•Function
•...
 
  這些東西有些是繼承自 Value,有些是二次繼承。我們這里就不多做研究,自己可以看看 V8 的代碼(至少是頭文件)研究研究或者看看這個手冊。

  而這個 New 呢?這里可以看的。就是新建一個 String 對象。

  至此,這個主要函數(shù)我們就解析完畢了。

導出對象

  我們來溫習一下,如果是在 Node.js 里面寫的話,我們怎么導出函數(shù)或者對象什么的呢?

復制代碼 代碼如下:

exports.hello = function() {}

   那么,在 C++ 中我們該如何做到這一步呢?

初始化函數(shù)

  首先,我們寫個初始化函數(shù):

復制代碼 代碼如下:

void init(Handle<Object> exports)
{
    //... 嗷嗷待寫你妹啊!#゚Å゚)⊂彡☆))゚Д゚)・∵
}

   這是龜腚!函數(shù)名什么的無所謂,但是傳入的參數(shù)一定是一個 Handle&lt;Object>,代表我們下面將要在這貨上導出東西。

  然后,我們就在這里面寫上導出的東西了:

復制代碼 代碼如下:

void init(Handle<Object> exports)
{
    exports->Set(String::NewSymbol("hello"),
        FunctionTemplate::New(Hello)->GetFunction());
}

   大致的意思就是說,為這個 exports 對象添加一個字段叫 hello,所對應的東西是一個函數(shù),而這個函數(shù)就是我們親愛的 Hello 函數(shù)了。

  用偽代碼寫直白點就是:

復制代碼 代碼如下:

void init(Handle<Object> exports)
{
    exports.Set("hello", function hello);
}

   大功告成!

 ?。ù蠊Ω娉赡忝冒?!閉嘴( ‘д‘⊂彡☆))Д´)

真·導出

  這才是最后一步,我們最后要申明,這個就是導出的入口,所以我們在代碼的末尾加上這一行:
NODE_MODULE(hello, init)

   納了個尼?!這又是什么東西?

  別著急,這個 NODE_MODULE 是一個宏,它的意思呢就是說我們采用 init 這個初始化函數(shù)來把要導出的東西導出到 hello 中。那么這個 hello 哪來呢?

  它來自文件名!對,沒錯,它來自文件名。你并不需要事先申明它,你也不必擔心不能用,總之你的這個最終編譯好的二進制文件名叫什么,這里的 hello 你就填什么,當然要除去后綴名了。

  詳見官方文檔。


Note that all Node addons must export an initialization function:

復制代碼 代碼如下:

void Initialize (Handle<Object> exports);
NODE_MODULE(module_name, Initialize)

 There is no semi-colon after NODE_MODULE as it's not a function (see node.h).

The module_name needs to match the filename of the final binary (minus the .node suffix).
 
編譯 (๑•́ ₃ •̀๑)

  來吧,讓我們一起編譯吧!

  我們再新建一個類似于 Makefile 的歸檔文件吧——binding.gyp。

  并且在里面添加這樣的代碼:

復制代碼 代碼如下:

{
  "targets": [
    {
      "target_name": "hello",
      "sources": [ "hello.cc" ]
    }
  ]
}

   為什么這么寫呢?可以參考 node-gyp 的官方文檔。

configure

  在文件搞好之后,我們要在這個目錄下面執(zhí)行這個命令了:

復制代碼 代碼如下:

$ node-gyp configure

   如果一切正常的話,應該會生成一個 build 的目錄,然后里面有相關文件,也許是 M$ Visual Studio 的 vcxproj 文件等,也許是 Makefile ,視平臺而定。

build

  Makefile 也生成好之后,我們就開始構(gòu)造編譯了:
$ node-gyp build

   等到一切編譯完成,才算是真正的大功告成了!不信你去看看 build/Release 目錄,下面是不是有一個 hello.node 文件了?沒錯,這個就是 C++ 等下要給 Node.js 撿的肥皂!

搞基吧!Node ヽ(✿゚▽゚)ノ C++

  我們在剛才那個目錄下新建一個文件 jianfeizao.js:

復制代碼 代碼如下:

var addon = require("./build/Release/hello");
console.log(addon.hello());

   看到?jīng)]!看到?jīng)]!出來了出來了!Node.js 和 C++ 搞基的結(jié)果!這個 addon.hello() 就是我們之前在 C++ 代碼中寫的 Handle<Value> Hello(const Arguments& args) 了,我們現(xiàn)在就已經(jīng)把它返回的值給輸出了。

洗洗睡吧,下節(jié)更深入

  時間不早了,今天就寫到這里了,至此為止大家都能搞出最基礎的 Hello world 的 C++ 擴展了吧。下一次寫的應該會更深入一點,至于下一次是什么時候,我也不知道啦其實。
  ?。ㄎ刮刮?,擼主怎么可以這么不負責!(o゚ロ゚)┌┛Σ(ノ´ω`)ノ

相關文章

  • Node.js用Socket.IO做聊天軟件的實現(xiàn)示例

    Node.js用Socket.IO做聊天軟件的實現(xiàn)示例

    本文主要介紹了Node.js用Socket.IO做聊天軟件的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-05-05
  • node.js爬蟲框架node-crawler初體驗

    node.js爬蟲框架node-crawler初體驗

    這篇文章主要介紹了node.js爬蟲框架node-crawler的相關資料,幫助大家利用node.js進行爬蟲,感興趣的朋友可以了解下
    2020-10-10
  • 使用node.js實現(xiàn)對數(shù)據(jù)庫進行CRUD操作

    使用node.js實現(xiàn)對數(shù)據(jù)庫進行CRUD操作

    這篇文章主要為大家詳細介紹了如何使用node.js實現(xiàn)對數(shù)據(jù)庫進行CRUD(增刪改查)操作,文中的示例代碼講解詳細,感興趣的小伙伴可以參考一下
    2024-12-12
  • Node.js中.npmrc文件的配置實現(xiàn)

    Node.js中.npmrc文件的配置實現(xiàn)

    .npmrc?文件是 npm 配置的核心文件,用于管理 npm 的行為,本文就來介紹一下Node .npmrc文件配置,具有一定的參考價值,感興趣的可以了解一下
    2024-12-12
  • nodejs之get/post請求的幾種方式小結(jié)

    nodejs之get/post請求的幾種方式小結(jié)

    下面小編就為大家?guī)硪黄猲odejs之get/post請求的幾種方式小結(jié)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • 使用 Node.js 模擬滑動拼圖驗證碼操作的示例代碼

    使用 Node.js 模擬滑動拼圖驗證碼操作的示例代碼

    本篇文章主要介紹了使用 Node.js 模擬滑動驗證碼操作的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • nodeJS刪除文件方法示例

    nodeJS刪除文件方法示例

    這篇文章主要介紹了nodeJS刪除文件方法,結(jié)合實例形式分析了nodeJS實現(xiàn)文件與目錄的獲取、遍歷與刪除相關操作技巧,需要的朋友可以參考下
    2016-12-12
  • Nodejs從有門道無門菜鳥起飛必看教程

    Nodejs從有門道無門菜鳥起飛必看教程

    下面小編就為大家?guī)硪黄狽odejs從有門道無門菜鳥起飛必看教程。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-07-07
  • 三種Node.js寫文件的方式

    三種Node.js寫文件的方式

    這篇文章主要為大家詳細介紹了三種Node.js寫文件的方式,感興趣的小伙伴們可以參考一下
    2016-03-03
  • nodejs 如何手動實現(xiàn)服務器

    nodejs 如何手動實現(xiàn)服務器

    這篇文章主要介紹了nodejs 如何手動實現(xiàn)服務器,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08

最新評論

武隆县| 苏尼特左旗| 固阳县| 白水县| 呼和浩特市| 山阴县| 卢湾区| 驻马店市| 色达县| 元阳县| 博湖县| 望都县| 张家港市| 亳州市| 巴彦淖尔市| 曲阜市| 沈丘县| 东至县| 东乌珠穆沁旗| 漳州市| 昌平区| 渭源县| 嘉义市| 璧山县| 东乡县| 枣强县| 丰都县| 浦江县| 神木县| 汕尾市| 普兰店市| 门头沟区| 平昌县| 牡丹江市| 滦南县| 营山县| 泗阳县| 炉霍县| 铅山县| 安宁市| 海宁市|