欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

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

準備工作

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

node-gyp

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

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

復制代碼 代碼如下:

$ npm install node-gyp -g

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

Python

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

  自己去官網搞一個來。


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

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

入門

  我就拿官網的入門 Hello World說事兒了。

Hello World

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

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

復制代碼 代碼如下:

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

 主要函數

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

復制代碼 代碼如下:

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

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

Handle<Value>

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


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

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

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


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

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

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

添磚加瓦

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

復制代碼 代碼如下:

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

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

HandleScope

  同參考自這里。


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

復制代碼 代碼如下:

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

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

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

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

String::New

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

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

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

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

導出對象

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

復制代碼 代碼如下:

exports.hello = function() {}

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

初始化函數

  首先,我們寫個初始化函數:

復制代碼 代碼如下:

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

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

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

復制代碼 代碼如下:

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

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

  用偽代碼寫直白點就是:

復制代碼 代碼如下:

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

   大功告成!

  (大功告成你妹??!閉嘴( ‘д‘⊂彡☆))Д´)

真·導出

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

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

  別著急,這個 NODE_MODULE 是一個宏,它的意思呢就是說我們采用 init 這個初始化函數來把要導出的東西導出到 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 也生成好之后,我們就開始構造編譯了:
$ node-gyp build

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

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

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

復制代碼 代碼如下:

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

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

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

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

相關文章

  • node.js實現快速截圖

    node.js實現快速截圖

    本文給大家匯總介紹了幾種node.js實現快速截屏的方法,這里分享給大家,希望大家能夠喜歡。
    2016-08-08
  • node.js文件系統(tǒng)之文件寫入實例詳解

    node.js文件系統(tǒng)之文件寫入實例詳解

    Node.js和其他語言一樣,也有文件操作,下面這篇文章主要給大家介紹了關于node.js文件系統(tǒng)之文件寫入的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-03-03
  • 利用npm 安裝刪除模塊的方法

    利用npm 安裝刪除模塊的方法

    今天小編就為大家分享一篇利用npm 安裝刪除模塊的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • Express下采用bcryptjs進行密碼加密的方法

    Express下采用bcryptjs進行密碼加密的方法

    本篇文章主要介紹了Express下采用bcryptjs進行密碼加密的方法,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-02-02
  • node.js抓取并分析網頁內容有無特殊內容的js文件

    node.js抓取并分析網頁內容有無特殊內容的js文件

    nodejs獲取網頁內容綁定data事件,獲取到的數據會分幾次相應,如果想全局內容匹配,需要等待請求結束,在end結束事件里把累積起來的全局數據進行操作,本文給大家介紹node.js抓取并分析網頁內容有無特殊內容的js文件,需要的朋友參考下
    2015-11-11
  • Electron架構深入探究

    Electron架構深入探究

    這篇文章主要為大家介紹了Electron架構深入探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • nodejs簡單實現TCP服務器端和客戶端的聊天功能示例

    nodejs簡單實現TCP服務器端和客戶端的聊天功能示例

    這篇文章主要介紹了nodejs簡單實現TCP服務器端和客戶端的聊天功能,結合實例形式分析了nodejs基于TCP協議實現的聊天程序客戶端與服務器端具體步驟與相關操作技巧,代碼備有較為詳盡的注釋便于理解,需要的朋友可以參考下
    2018-01-01
  • 從零學習node.js之簡易的網絡爬蟲(四)

    從零學習node.js之簡易的網絡爬蟲(四)

    簡單的爬蟲實現原理很簡單:發(fā)送http請求至目標地址獲取HTML頁面數據,然后從獲取來的頁面數據中提取需要的數據保存。下面這篇文章主要介紹了利用node.js實現簡易的網絡爬蟲的相關資料,需要的朋友可以參考下。
    2017-02-02
  • node.js事件循環(huán)機制及與js區(qū)別詳解

    node.js事件循環(huán)機制及與js區(qū)別詳解

    這篇文章主要為大家介紹了node.js事件循環(huán)機制及與js區(qū)別詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • CentOS7中源碼編譯安裝NodeJS的完整步驟

    CentOS7中源碼編譯安裝NodeJS的完整步驟

    這篇文章主要給大家介紹了關于CentOS7中源碼編譯安裝NodeJS的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用nodejs具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-10-10

最新評論