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

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

 更新時間:2014年09月24日 17:11:43   投稿:hebedich  
上篇文章的主要內(nèi)容講訴了用C/C++來實現(xiàn) Node.js 的模塊,本文更深一步繼續(xù)探討這個問題,有需要的朋友可以參考下

溫故而知新,可以為濕矣

  首先請大家記住這個 V8 的在線手冊——http://izs.me/v8-docs/main.html。

  還記得上次的 building.gyp 文件嗎?

復制代碼 代碼如下:

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

   就像這樣,舉一反三,如果多幾個 *.cc 文件的話就是這樣的:
"sources": [ "addon.cc", "myexample.cc" ]

   上次我們把倆步驟分開了,實際上配置和編譯可以放在一起的:
$ node-gyp configure build

   復習完了嗎?沒?!

  好的,那我們繼續(xù)吧。

表番

函數(shù)參數(shù)

  現(xiàn)在我們終于要講參數(shù)了呢。

  讓我們設想有這樣一個函數(shù) add(a, b) 代表把 a 和 b 相加返回結(jié)果,所以先把函數(shù)外框?qū)懞茫?br />

復制代碼 代碼如下:

#include <node.h>
using namespace v8;

Handle<Value> Add(const Arguments& args)
{
    HandleScope scope;

    //... 又來!
}

 Arguments

  這個就是函數(shù)的參數(shù)了。我們不妨先看看 v8 的官方手冊參考。
 •int Length() const
 •Local<Value> operator[](int i) const
 
  其它的我們咱不關心,這兩個可重要了!一個代表傳入函數(shù)的參數(shù)個數(shù),另一個中括號就是通過下標索引來訪問第 n 個參數(shù)的。

  所以如上的需求,我們大致就可以理解為 args.Length() 為 2,args[0] 代表 a 以及 args[1] 代表 b 了。并且我們要判斷這兩個數(shù)的類型必須得是 Number。

  注意到?jīng)],中括號的索引操作符返回結(jié)果是一個 Local<Value> 也就是 Node.js 的所有類型基類。所以傳進來的參數(shù)類型不定的,我們必須得自己判斷是什么參數(shù)。這就關系到了這個 Value 類型的一些函數(shù)了。

 •IsArray()
•IsBoolean()
•IsDate()
•IsFunction()
•IsInt32()
•IsNativeError()
•IsNull()
•IsNumber()
•IsRegExp()
•IsString()
•...
 
  我就不一一列舉了,剩下的自己看文檔。。:.゚ヽ(*´∀`)ノ゚.:。

ThrowException

  這個是我們等下要用到的一個函數(shù)。具體在 v8 文檔中可以找到。

  顧名思義,就是拋出錯誤啦。執(zhí)行這個語句之后,相當于在 Node.js 本地文件中執(zhí)行了一條 throw() 語句一樣。比如說:
ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));

   就相當于執(zhí)行了一條 Node.js 的:
throw new TypeError("Wrong number of arguments");

 Undefined()

  這個函數(shù)呢也在文檔里面。

  具體就是一個空值,因為有些函數(shù)并不需要返回什么具體的值,或者說沒有返回值,這個時候就需要用 Undefined() 來代替了。

動手吧騷年!

  在理解了以上的幾個要點之后,我相信你們很快就能寫出 a + b 的邏輯了,我就把 Node.js 官方手冊的代碼抄過來給你們過一遍就算完事了:

復制代碼 代碼如下:

#include <node.h>
using namespace v8;

Handle<Value> Add(const Arguments& args)
{
    HandleScope scope;

    // 代表了可以傳入 2 個以上的參數(shù),但實際上我們只用前兩個
    if(args.Length() < 2)
    {
        // 拋出錯誤
        ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));

        // 返回空值
        return scope.Close(Undefined());
    }

    // 若前兩個參數(shù)其中一個不是數(shù)字的話
    if(!args[0]->IsNumber() || !args[1]->IsNumber())
    {
        // 拋出錯誤并返回空值
        ThrowException(Exception::TypeError(String::New("Wrong arguments")));
        return scope.Close(Undefined());
    }

    // 具體參考 v8 文檔
    //     http://izs.me/v8-docs/classv8_1_1Value.html#a6eac2b07dced58f1761bbfd53bf0e366)
    // 的 `NumberValue` 函數(shù)
    Local<Number> num = Number::New(args[0]->NumberValue() + args[1]->NumberValue());

    return scope.Close(num);
}

   函數(shù)大功告成!

  最后把尾部的導出函數(shù)給寫好就 OK 了。

復制代碼 代碼如下:

void Init(Handle<Object> exports)
{
    exports->Set(String::NewSymbol("add"),
        FunctionTemplate::New(Add)->GetFunction());
}

NODE_MODULE(addon, Init)


   等你編譯好之后,我們就能這樣用了:

復制代碼 代碼如下:
var addon = require('./build/Release/addon');
console.log(addon.add(1, 1) + "b");

   你會看到一個 2b !✧。٩(ˊᗜˋ)و✧*。

回調(diào)函數(shù)

  上一章我們只講了個 Hello world,這一章阿婆主就良心發(fā)現(xiàn)一下,再來個回調(diào)函數(shù)的寫法。

  慣例我們先寫好框架:

復制代碼 代碼如下:

#include <node.h>
using namespace v8;

Handle<Value> RunCallback(const Arguments& args)
{
  HandleScope scope;

  // ... 噼里啪啦噼里啪啦

  return scope.Close(Undefined());
}

   然后我們決定它的用法是這樣的:
func(function(msg) {
    console.log(msg);
});

   即它會給回調(diào)函數(shù)傳入一個參數(shù),我們設想它是一個字符串,然后我們可以 console.log() 出來看。

首先你要有一個字符串系列

  廢話不多說,先給它一個字符串喂飽了再說吧。(√ ζ ε:)

  不過我們得讓這個字符串是通用類型的,因為 Node.js 代碼是弱類型的。
Local<Value>::New(String::New("hello world"));

   什么?你問我什么是 Local<Value>?

  那我稍稍講一下吧,參考自這里和V8參考文檔。

  如文檔所示,Local<T> 實際上繼承自 Handle<T>,我記得上一章已經(jīng)講過 Handle<T> 這個東西了。

  然后下面就是講 Local 了。


Handle 有兩種類型, Local Handle 和 Persistent Handle ,類型分別是 Local<T> : Handle<T> 和 Persistent<T> : Handle<T> ,前者和 Handle<T> 沒有區(qū)別生存周期都在 scope 內(nèi)。而后者的生命周期脫離 scope ,你需要手動調(diào)用 Persistent::Dispose 結(jié)束其生命周期。也就是說 Local Handle 相當于在 C++`在棧上分配對象而 Persistent Handle 相當于 C++ 在堆上分配對象。
 
然后你要有個參數(shù)表系列

  終端命令行調(diào)用 C/C++ 之后怎么取命令行參數(shù)?

復制代碼 代碼如下:

#include <stdio.h>

void main(int argc, char* argv[])
{
    // ...
}

   對了,這里的 argc 就是命令行參數(shù)個數(shù),argv[] 就是各個參數(shù)了。那么調(diào)用 Node.js 的回調(diào)函數(shù),v8 也采用了類似的方法:

復制代碼 代碼如下:
V8EXPORT Local<Value> v8::Function::Call(Handle<Object>recv,
    int argc,
    Handle<Value> argv[]
);

 ~~QAQ 卡在了 Handle<Object> recv 了?。。∶魈炖^續(xù)寫。~~
 
  好吧,新的一天開始了我感覺我充滿了力量。(∩^o^)⊃━☆゚.*・。

  經(jīng)過我多方面求證(SegmentFault和StackOverflow以及一個扣扣群),終于解決了上面這個函數(shù)仨參數(shù)的意思。

  后面兩個參數(shù)就不多說了,一個是參數(shù)個數(shù),另一個就是一個參數(shù)的數(shù)組了。至于第一個參數(shù) Handle<Object> recv,StackOverflow 仁兄的解釋是這樣的:


It is the same as apply in JS. In JS, you do

復制代碼 代碼如下:

var context = ...;
cb.apply(context, [ ...args...]);

 The object passed as the first argument becomes this within the function scope. More documentation on MDN. If you don't know JS well, you can read more about JS's this here: http://unschooled.org/2012/03/understanding-javascript-this/
 
—— 摘自 StackOverflow

  總之其作用就是指定了被調(diào)用函數(shù)的 this 指針。這個 Call 的用法就跟 JavaScript 中的 bind()、call()、apply() 類似。

  所以我們要做的事情就是先把參數(shù)表建好,然后傳入這個 Call 函數(shù)供其執(zhí)行。

  第一步,顯示轉(zhuǎn)換函數(shù),因為本來是 Object 類型:
Local<Function> cb = Local<Function>::Cast(args[0]);

   第二步,建立參數(shù)表(數(shù)組):
Local<Value> argv[argc] = { Local<Value>::New(String::New("hello world")) };

 最后調(diào)用函數(shù)系列

  調(diào)用 cb ,把參數(shù)傳進去:
cb->Call(Context::GetCurrent()->Global(), 1, argv);

   這里第一個參數(shù) Context::GetCurrent()->Global() 所代表的意思就是獲取全局上下文作為函數(shù)的 this;第二個參數(shù)就是參數(shù)表中的個數(shù)(畢竟雖然 Node.js 的數(shù)組是有長度屬性的,但是 C++ 里面數(shù)組的長度實際上系統(tǒng)是不知道的,還得你自己傳進一個數(shù)來說明數(shù)組長度);最后一個參數(shù)就是剛才我們建立好的參數(shù)表了。

終章之結(jié)束文件系列

  相信這一步大家已經(jīng)輕車熟路了吧,就是把函數(shù)寫好,然后放進導出函數(shù)里面,最后申明一下。

  我就直接放出代碼吧,或者直接跑去 Node.js 的文檔看也行。

復制代碼 代碼如下:

#include <node.h>
using namespace v8;

Handle<Value> RunCallback(const Arguments& args)
{
    HandleScope scope;
    Local<Function> cb = Local<Function>::Cast(args[0]);
    const unsigned argc = 1;
    Local<Value> argv[argc] = { Local<Value>::New(String::New("hello world")) };
    cb->Call(Context::GetCurrent()->Global(), argc, argv);

    return scope.Close(Undefined());
}

void Init(Handle<Object> exports, Handle<Object> module)
{
    module->Set(String::NewSymbol("exports"),
        FunctionTemplate::New(RunCallback)->GetFunction());
}

NODE_MODULE(addon, Init)

   Well done! 最后剩下的步驟就自己去吧。至于 Js 里面這么調(diào)用這個函數(shù),我在之前已經(jīng)提到過了。

番外

  嘛嘛,我感覺我的學習筆記寫得越來越奔放了求破~

  今天就先寫到這里吧,寫學習筆記的過程中我又漲姿勢了,比如說那個 Call 函數(shù)的參數(shù)意義。

  如果你們覺得本系列學習筆記對你們還有幫助的話,就來和我一起搞基吧么么噠~Σ>―(〃°ω°〃)♡→

相關文章

  • 解決npm?install版本不匹配問題:?npm?ERR!?code?ETARGET?npm?ERR!?notarget?No?matching?version?found?for

    解決npm?install版本不匹配問題:?npm?ERR!?code?ETARGET?npm?ERR!?

    這篇文章主要介紹了如何解決npm?install版本不匹配問題:?npm?ERR!?code?ETARGET?npm?ERR!?notarget?No?matching?version?found?for,文中給出了詳細的解決方法,需要的朋友可以參考下
    2024-02-02
  • 微信小程序搭載node.js服務器的簡單教程

    微信小程序搭載node.js服務器的簡單教程

    小程序是一種全新的連接用戶與服務的方式,它可以在微信內(nèi)被便捷地獲取和傳播,同時具有出色的使用體驗,下面這篇文章主要給大家介紹了關于微信小程序搭載node.js服務器的簡單教程,需要的朋友可以參考下
    2022-12-12
  • Node.js利用Net模塊實現(xiàn)多人命令行聊天室的方法

    Node.js利用Net模塊實現(xiàn)多人命令行聊天室的方法

    Node.js Net 模塊提供了一些用于底層的網(wǎng)絡通信的小工具,包含了創(chuàng)建服務器/客戶端的方法,下面這篇文章主要給大家介紹了Node.js利用Net模塊實現(xiàn)命令行多人聊天室的方法,有需要的朋友們可以參考借鑒,下面來一起看看吧。
    2016-12-12
  • 深入nodejs中流(stream)的理解

    深入nodejs中流(stream)的理解

    本篇文章主要介紹了深入nodejs中流(stream)的理解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • npm?list輸出結(jié)果包含extraneous標志記錄分析

    npm?list輸出結(jié)果包含extraneous標志記錄分析

    這篇文章主要為大家介紹了npm?list輸出結(jié)果包含extraneous標志記錄分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01
  • 淺談NodeJs之數(shù)據(jù)庫異常處理

    淺談NodeJs之數(shù)據(jù)庫異常處理

    這篇文章主要介紹了淺談NodeJs之數(shù)據(jù)庫異常處理,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • 阿里云ecs服務器中安裝部署node.js的步驟

    阿里云ecs服務器中安裝部署node.js的步驟

    這篇文章給大家介紹了在阿里云ecs服務器中安裝部署node.js的詳細步驟,對大家安裝node.js具有一定的參考借鑒價值,有需要的朋友們下面來一起看看吧。
    2016-10-10
  • node.js自動上傳ftp的腳本分享

    node.js自動上傳ftp的腳本分享

    這篇文章主要給大家介紹了一個關于node.js自動上傳ftp腳本的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧
    2018-06-06
  • nvm查看所有node包命令失效原因解決方案

    nvm查看所有node包命令失效原因解決方案

    使用nvm時可能會遇到超時問題,這是由于node的包存放在國外服務器上,解決方法是在nvm的配置文件中添加鏡像地址,下面就來具體介紹一下步驟,感興趣的可以了解一下
    2024-09-09
  • 手把手帶你安裝多個node版本

    手把手帶你安裝多個node版本

    在項目開發(fā)過程中,不同項目使用的node版本不同,有時會因為node版本過高或太低,導致報錯,下面這篇文章主要給大家介紹了關于安裝多個node版本的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-08-08

最新評論

武陟县| 西峡县| 安宁市| 新郑市| 福贡县| 桐城市| 射洪县| 根河市| 光泽县| 边坝县| 获嘉县| 汕头市| 司法| 长乐市| 五常市| 灵山县| 南投市| 松江区| 鄂托克旗| 霍山县| 长寿区| 平安县| 重庆市| 西安市| 喜德县| 邓州市| 泰来县| 酉阳| 宁晋县| 凤庆县| 辉县市| 徐水县| 长顺县| 贵溪市| 城步| 新平| 普宁市| 肇州县| 宜良县| 汾阳市| 乐业县|