ホームページ >ウェブフロントエンド >jsチュートリアル >C/Cを使用してNode.jsモジュールを実装する(2)_node.js

C/Cを使用してNode.jsモジュールを実装する(2)_node.js

WBOY
WBOYオリジナル
2016-05-16 16:35:311120ブラウズ

過去を振り返り、新しいことを学ぶと幸せになれます

まず最初に、この V8 オンライン マニュアル (http://izs.me/v8-docs/main.html) を思い出してください。

前回のbuilding.gypファイルをまだ覚えていますか?

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

{
"ターゲット": [
{
"target_name": "アドオン",
"ソース": [ "addon.cc" ]
}
]
}

これと同じように、*.cc ファイルがさらにいくつかある場合は、次のようになります:
"ソース": [ "addon.cc", "myexample.cc" ]

前回は 2 つのステップに分けましたが、実際には、構成とコンパイルは次のようにまとめることができます。 $node-gypconfigurebuild

レビューはもう終わりましたか?それなし? !

はい、続けましょう。

目次

関数パラメータ

いよいよパラメータについて話さなければなりません。

a と b を加算して結果を返す関数 add(a, b) があると仮定して、最初に関数の概要を記述します。


コードをコピー コードは次のとおりです:
#include
名前空間 v8 を使用;
ハンドル<値> Add(const Arguments& args)

{
HandleScope スコープ;

//...また行きます!

}

引数

これは関数のパラメータです。まずはv8の公式マニュアルリファレンスを見てみましょう。

•int Length() const
•ローカル 演算子[](int i) const

残りは気にしない、この 2 つが重要です。 1 つは関数に渡されるパラメーターの数を表し、もう 1 つの括弧は添字インデックスを介して n 番目のパラメーターにアクセスするために使用されます。

したがって、args.Length() が 2、args[0] が a、args[1] が b を表すので、上記の要件を大まかに理解できます。そして、これら 2 つの数値の型が Number でなければならないことを判断する必要があります。

角括弧内のインデックス演算子は、Node.js のすべての型の基本クラスである Local を返すことに注意してください。したがって、渡されるパラメータは不確実な型であり、それがどのようなパラメータであるかを自分で判断する必要があります。これは、この値タイプのいくつかの関数に関連しています。

•IsArray()

•IsBoolean()
•IsDate()
•IsFunction()
•IsInt32()
•IsNativeError()
•IsNull()
•IsNumber()
•IsRegExp()
•IsString()
•...

それらを 1 つずつリストするつもりはありません。残りについてはドキュメントを読んでください。 。:.゚ヽ(*´∀`)ノ゚.:。

例外をスロー

これは後で使用する関数です。詳細については、v8 のドキュメントを参照してください。

名前が示すように、エラーをスローします。このステートメントの実行後は、Node.js ローカル ファイルで throw() ステートメントを実行するのと同じになります。例:

ThrowException(Exception::TypeError(String::New("引数の数が間違っています")));

これは、Node.js を実行するのと同じです:

throw new TypeError("引数の数が間違っています");

未定義()

この関数はドキュメントにも記載されています。

具体的には、一部の関数は特定の値を返す必要がないか、現時点では戻り値がないため、これは null 値です。

やってみよう、サオニアン!

上記の点を理解すれば、すぐに a b のロジックを書けるようになると思います。Node.js 公式マニュアルからコードをコピーして、実行してみましょう。


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

#include
名前空間 v8 を使用;

ハンドル<値> Add(const Arguments& args)
{
HandleScope スコープ;

// 3 つ以上のパラメータを渡すことができることを意味しますが、実際には最初の 2 つだけを使用します
If(args.Length() {
// エラーをスローします
ThrowException(Exception::TypeError(String::New("引数の数が間違っています")));

// null 値を返す returnscope.Close(Unknown());
}

// 最初の 2 つのパラメータのいずれかが数値でない場合

If(!args[0]->IsNumber() || !args[1]->IsNumber())
{
// エラーをスローし、null 値を返します
ThrowException(Exception::TypeError(String::New("Wrong argument")));
returnscope.Close(Unknown());
}

// 詳細については、v8 ドキュメントを参照してください

//
http://izs.me/v8-docs/classv8_1_1Value.html#a6eac2b07dced58f1761bbfd53bf0e366) // `NumberValue` 関数
ローカル<数値> num = Number::New(args[0]->NumberValue() args[1]->NumberValue());

returnscope.Close(num);

}

機能は完了です!

最後にexport関数を記述すればOKです。


コードをコピー コードは次のとおりです:
void Init(ハンドル<オブジェクト> エクスポート)
{
エクスポート->Set(String::NewSymbol("add"),
FunctionTemplate::New(Add)->GetFunction());
}
NODE_MODULE(アドオン、初期化)


コンパイルしたら、次のように使用できます:

コードをコピーします コードは次のとおりです。
var addon = require('./build/Release/アドオン') ;
console.log(addon.add(1, 1) "b");

2b が見えます! ✧。٩(ˊᗜˋ)و✧*。

コールバック関数

前の章では、Hello world についてのみ説明しました。この章では、おばあちゃんが意識的な発見をし、別のコールバック関数を作成しました。

いつものように、最初にフレームワークを作成します。


コードをコピー コードは次のとおりです:
#include
名前空間 v8 を使用;
ハンドル<値>RunCallback(const Arguments& args)

{
HandleScope スコープ;

// ... パチパチパチパチ

returnscope.Close(Unknown());

}

そして、その使用法は次のように決定しました。

func(関数(msg) {
console.log(msg);
});

つまり、パラメータをコールバック関数に渡し、それを console.log() で出力できると想定します。

まず文字列シリーズが必要です

早速、最初に文字列を与えてから、それについて話しましょう。 (√ ε :)

ただし、Node.js コードの型指定が弱いため、この文字列をユニバーサル型にする必要があります。
Local::New(String::New("hello world"));

え? Local とは何ですか?

それでは、それについて少しお話しさせてください。ここと V8 リファレンス ドキュメントを参照してください。

ドキュメントに示されているように、Local は実際には Handle から継承されています。

それではローカルについて話しましょう。


ハンドルにはローカル ハンドルと永続ハンドルの 2 種類があり、それぞれローカル : ハンドル に違いはありません。ライフサイクルは範囲内です。後者のライフサイクルは範囲外であるため、そのライフサイクルを終了するには Persistent::Dispose を手動で呼び出す必要があります。つまり、ローカル ハンドルは C がスタック上にオブジェクトを割り当てることと同等であり、永続ハンドルは C がヒープ上にオブジェクトを割り当てることと同等です。

次に、パラメータテーブルシリーズが必要です

ターミナルのコマンドラインから C/C を呼び出した後、コマンドラインパラメータを取得するにはどうすればよいですか?

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

#include

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

ちなみに、ここでのargcはコマンドラインパラメータの数、argv[]は各パラメータです。次に、Node.js のコールバック関数を呼び出します。v8 も同様の方法を採用しています。

コードをコピー コードは次のとおりです。
V8EXPORT Local v8::Function::Call(Handle<オブジェクト>recv ,
int argc,
ハンドル<値> argv[]
);

~~QAQ が Handle でスタックしています! ! !明日も続きを書きます。 ~~

さぁ、新しい一日が始まり、元気が湧いてきました。 (∩^o^)⊃━☆゚.*・。

多くの側面 (SegmentFault、StackOverflow、KouKou グループ) で検証した結果、上記の関数の 3 つのパラメーターの意味が最終的に解決されました。

次の 2 つのパラメータについては多くは説明しません。1 つはパラメータの数で、もう 1 つはパラメータの配列です。最初のパラメータ Handle については、StackOverflow の説明は次のとおりです。

JS での apply と同じです。

コードをコピー コードは次のとおりです:
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 までご連絡ください。