首頁 web前端 js教程 用C/C 實作 Node.js 的模組(二)_node.js

用C/C 實作 Node.js 的模組(二)_node.js

May 16, 2016 pm 04:35 PM
c node.js 模組

溫故而知新,可以為濕矣

  首先請大家記住這個 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

   複習完了嗎?沒? !

  好的,那我們繼續吧。

表番

函數參數

  現在我們終於要講參數了呢。

  讓我們設想有這樣一個函數 add(a, b) 代表把 a 和 b 相加回傳結果,所以先把函數外框寫好:

複製程式碼 程式碼如下:

#include
using namespace v8;

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

    //... 又來!
}

 Arguments

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

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

  注意到沒,中括號的索引運算子回傳結果是一個 Local 也就是 Node.js 的所有型別基底類別。所以傳進來的參數類型不定的,我們必須得自己判斷是什麼參數。這就關係到了這個 Value 類型的一些函數了。

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

ThrowException

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

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

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

 Undefined()

  這個函數呢也在文檔裡面。

  具體就是一個空值,因為有些函數並不需要傳回什麼特定的值,或是說沒有回傳值,這個時候就需要用 Undefined() 來取代了。

動手吧騷年!

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

複製程式碼 程式碼如下:

#include
using namespace v8;

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

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

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

    // 若前兩個參數其中一個不是數字的話
    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#a6eac2b07ed58f1761bbfd53bf0e366dced58f1761bbfd53bf0e366
dc
    // 的 `NumberValue` 函數

    Local num = Number::New(args[0]->NumberValue() args[1]->NumberValue());


    return scope.Close(num);
}

   函數大功告成!


  最後把尾部的導出函數給寫好就 OK 了。

程式碼如下:


void Init(Handle 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 ! ✧。٩(ˊᗜˋ)و✧*。

回呼函數

  上一章我們只講了個 Hello world,這一章阿婆主就良心發現一下,再來個回調函數的寫法。


  慣例我們先寫好框架:

程式碼如下:


#include using namespace v8;


Handle RunCallback(const Arguments& args)
{

  HandleScope scope;

  // ... 噼裡啪啦噼裡啪啦


  return scope.Close(Undefined());

}


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

   即它會給回呼函數傳入一個參數,我們設想它是一個字串,然後我們可以 console.log() 出來看。

首先你要有一個字串系列

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

  不過我們得讓這個字串是通用型別的,因為 Node.js 程式碼是弱型別的。
Local::New(String::New("hello world"));

   什麼?你問我什麼是 Local

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

  如文檔所示,Local 其實繼承自 Handle,我記得上一章已經講過 Handle 這個東西了。

  然後下面就是講 Local 了。


Handle 有兩種類型, Local Handle 和 Persistent Handle ,類型分別是 Local : Handle 和 Persistent : Handle ,前者和 Handle 沒有區別生存週期都在 scope 內。而後者的生命週期脫離 scope ,你需要手動呼叫 Persistent::Dispose 結束其生命週期。也就是說 Local Handle 相當於在 C `在堆疊上分配物件而 Persistent Handle 相當於 C 在堆上分配物件。
 
然後你要有個參數表系列

  終端命令列呼叫 C/C 之後怎麼取命令列參數?

複製程式碼 程式碼如下:

#include

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

   對了,這裡的 argc 就是命令列參數個數,argv[] 就是各個參數了。那麼呼叫 Node.js 的回呼函數,v8 也採用了類似的方法:

複製程式碼 程式碼如下:
V8EXPORT Local v8::Function::Call(Handlerecv ,
    int argc,
    Handle argv[]
);

 ~~QAQ 卡在了 Handle recv 了! ! !明天繼續寫。 ~~
 
  好吧,新的一天開始了我感覺我充滿了力量。 (∩^o^)⊃━☆゚.*・。

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

  後面兩個參數就不多說了,一個是參數個數,另一個就是一個參數的數組了。至於第一個參數 Handle recv,StackOverflow 仁兄的解釋是這樣的:


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

複製程式碼 程式碼如下:

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

最初の引数として渡されるオブジェクトは、関数スコープ内で this になります。JS について詳しくない場合は、ここで JS の詳細を参照してください。http://unschooled.org /2012/03/undering-javascript-this/

——StackOverflow

より抜粋

つまり、その機能は呼び出される関数の this ポインタを指定することです。この Call の使用法は、JavaScript の binding()、call()、および apply() に似ています。

したがって、私たちがしなければならないことは、最初にパラメータテーブルを構築し、次に実行のために Call 関数を渡すことです。

最初のステップは変換関数を表示することです。変換関数は元々オブジェクト型であるためです。
ローカル cb = ローカル::Cast(args[0]);

2 番目のステップは、パラメーター テーブル (配列) を作成することです:
Local argv[argc] = { Local::New(String::New("hello world")) };

ラストコール機能シリーズ

cb を呼び出してパラメータを渡します:
cb->Call(Context::GetCurrent()->Global(), 1, argv);

ここでの最初のパラメータ Context::GetCurrent()->Global() は、関数の this としてグローバル コンテキストを取得することを意味します。2 番目のパラメータはパラメータ テーブル内の番号です (結局、Node.js ですが)。配列には長さ属性がありますが、実際にはシステムは C の配列の長さを知らないため、配列の長さを示すために自分で数値を渡す必要があります); 最後のパラメーターは作成したばかりのパラメーター テーブルです。 。

最終章ファイナルドキュメントシリーズ

関数を作成し、それをエクスポートされた関数に入れて、最後に宣言するというこのステップについては、誰もがすでによく知っていると思います。

コードを直接リリースするだけですが、Node.js ドキュメントに直接アクセスすることもできます。

コードをコピー コードは次のとおりです:

#include
名前空間 v8 を使用;

ハンドル<値>RunCallback(const Arguments& args)
{
HandleScope スコープ;
ローカル cb = ローカル::Cast(args[0]);
const unsigned argc = 1;
Local argv[argc] = { Local::New(String::New("hello world")) };
cb->Call(Context::GetCurrent()->Global(), argc, argv);

returnscope.Close(Unknown());
}

void Init(Handle エクスポート、Handle モジュール)
{
モジュール -> Set(String::NewSymbol("exports"),
FunctionTemplate::New(RunCallback)->GetFunction());
}

NODE_MODULE(アドオン、初期化)

完了しました。残りの手順は自分で実行してください。この関数を JS で呼び出すことについては、以前に説明しました。

追加

さて、勉強ノートがどんどん自由になってきている気がしますので、分解してください~

今日はこの辺で、勉強ノートを書いている途中でCall関数のパラメータの意味などでまた困ってしまいました。

この一連の学習ノートがまだ役立つと思われる場合は、ぜひ一緒に楽しんでください〜Σ>―(〃°ω°〃)♡→

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1321
25
PHP教程
1269
29
C# 教程
1249
24
WLAN擴充模組已停止[修復] WLAN擴充模組已停止[修復] Feb 19, 2024 pm 02:18 PM

如果您的Windows電腦上的WLAN擴充模組出現問題,可能會導致您與網際網路中斷連線。這種情況常常讓人感到困擾,但幸運的是,本文提供了一些簡單的建議,可以幫助您解決這個問題,讓您的無線連線重新正常運作。修復WLAN擴充模組已停止如果您的Windows電腦上的WLAN可擴充性模組已停止運作,請依照下列建議進行修復:執行網路和Internet故障排除程式停用並重新啟用無線網路連線重新啟動WLAN自動設定服務修改電源選項修改高級電源設定重新安裝網路適配器驅動程式運行一些網路命令現在,讓我們來詳細看

WLAN可擴充性模組無法啟動 WLAN可擴充性模組無法啟動 Feb 19, 2024 pm 05:09 PM

本文詳細介紹了解決事件ID10000的方法,該事件表明無線區域網路擴充模組無法啟動。在Windows11/10PC的事件日誌中可能會顯示此錯誤。 WLAN可擴充性模組是Windows的一個元件,允許獨立硬體供應商(IHV)和獨立軟體供應商(ISV)為使用者提供客製化的無線網路特性和功能。它透過增加Windows預設功能來擴充本機Windows網路元件的功能。在作業系統載入網路元件時,WLAN可擴充性模組會作為初始化的一部分啟動。如果無線區域網路擴充模組遇到問題無法啟動,您可能會在事件檢視器的日誌中看到錯誤消

C語言中的常數是什麼,可以舉例嗎? C語言中的常數是什麼,可以舉例嗎? Aug 28, 2023 pm 10:45 PM

常量也稱為變量,一旦定義,其值在程式執行期間​​就不會改變。因此,我們可以將變數宣告為引用固定值的常數。它也被稱為文字。必須使用Const關鍵字來定義常數。語法C程式語言中使用的常數語法如下-consttypeVariableName;(or)consttype*VariableName;不同類型的常數在C程式語言中使用的不同類型的常數如下所示:整數常數-例如:1,0,34, 4567浮點數常數-例如:0.0,156.89,23.456八進制和十六進制常數-例如:十六進制:0x2a,0xaa..八進制

VSCode和VS C++IntelliSense無法運作或拾取函式庫 VSCode和VS C++IntelliSense無法運作或拾取函式庫 Feb 29, 2024 pm 01:28 PM

VS程式碼和VisualStudioC++IntelliSense可能無法拾取函式庫,尤其是在處理大型專案時。當我們將滑鼠懸停在#Include&lt;wx/wx.h&gt;上時,我們看到了錯誤訊息「CannotOpen來源檔案'string.h'」(依賴於「wx/wx.h」),有時,自動完成功能無法回應。在這篇文章中,我們將看到如果VSCode和VSC++IntelliSense不能工作或不能提取庫,你可以做些什麼。為什麼我的智能感知不能在C++中運作?處理大型檔案時,IntelliSense有時

遞歸程式在C++中找到陣列的最小和最大元素 遞歸程式在C++中找到陣列的最小和最大元素 Aug 31, 2023 pm 07:37 PM

我們以整數數組Arr[]作為輸入。目標是使用遞歸方法在陣列中找到最大和最小的元素。由於我們使用遞歸,我們將遍歷整個數組,直到達到長度=1,然後返回A[0],這形成了基本情況。否則,將當前元素與當前最小或最大值進行比較,並透過遞歸更新其值以供後續元素使用。讓我們來看看這個的各種輸入輸出場景−輸入 −Arr={12,67,99,76,32};輸出 −數組中的最大值:99解釋 &mi

修復Xbox錯誤代碼8C230002 修復Xbox錯誤代碼8C230002 Feb 27, 2024 pm 03:55 PM

您是否因為錯誤代碼8C230002而無法在Xbox上購買或觀看內容?一些用戶在嘗試購買或在其控制台上觀看內容時不斷收到此錯誤。抱歉,Xbox服務出現問題。稍後再試。有關此問題的協助,請造訪www.xbox.com/errorhelp。狀態代碼:8C230002這種錯誤代碼通常是由於暫時的伺服器或網路問題引起的。但是,還有可能是由於帳戶的隱私設定或家長控制等其他原因,這些可能會阻止您購買或觀看特定內容。修正Xbox錯誤代碼8C230002如果您嘗試在Xbox控制台上觀看或購買內容時收到錯誤代碼8C

C++程式列印數字的螺旋圖案 C++程式列印數字的螺旋圖案 Sep 05, 2023 pm 06:25 PM

以不同格式顯示數字是學習基本編碼問題之一。不同的編碼概念,如條件語句和迴圈語句。有不同的程式中,我們使用特殊字元(如星號)來列印三角形或正方形。在本文中,我們將以螺旋形式列印數字,就像C++中的正方形一樣。我們將行數n作為輸入,然後從左上角開始移向右側,然後向下,然後向左,然後向上,然後再次向右,以此類推等等。螺旋圖案與數字123456724252627282982340414243309223948494431102138474645321120373635343312191817161514

C語言中的void關鍵字的作用 C語言中的void關鍵字的作用 Feb 19, 2024 pm 11:33 PM

C中的void是一個特殊的關鍵字,用來表示空類型,也就是指沒有具體類型的資料。在C語言中,void通常用於以下三個方面。函數傳回類型為void在C語言中,函數可以有不同的回傳類型,例如int、float、char等。然而,如果函數不傳回任何值,則可以將傳回類型設為void。這意味著函數執行完畢後,並不傳回具體的數值。例如:voidhelloWorld()

See all articles