node.jsは、javascriptを使用して書面でバックエンドを書くのに最適な効果があり、もっと試す価値があります。ただし、直接使用できない機能が必要な場合、またはまったく実装できないモジュールさえも必要な場合は、C/C ++ライブラリからそのような成果を導入できますか?答えはイエスです。あなたがしなければならないのは、プラグインを書き、JavaScriptコードで他のコードベースリソースを使用することです。今日の問い合わせの旅を一緒に始めましょう。
導入
node.jsが公式ドキュメントで述べているように、プラグインは動的にリンクする共有オブジェクトであり、JavaScriptコードをC/C ++ライブラリに接続できます。これは、C/C ++ライブラリから何でも参照し、プラグインを作成してnode.jsに組み込むことができることを意味します。
例として、標準のSTD :: Stringオブジェクトのカプセル化を作成します。
準備
執筆を開始する前に、後続のモジュールコンパイルに必要なすべての素材を準備していることを確認する必要があります。誰もがNode-Gypとすべての依存関係を必要としています。次のコマンドを使用して、node-gypをインストールできます。
NPMインストール-Gノード-Gyp
依存関係に関しては、UNIXシステム用の次のプロジェクトを準備する必要があります。•Python(バージョン2.7、3.xが正しく機能できません)
• 作る
•C ++コンパイラツールチェーン(GPPやG ++など)
たとえば、Ubuntuでは、次のコマンドを使用して上記のすべてのプロジェクトをインストールできます(Python 2.7がプリインストールされているはずです):
sudo apt-get install build-essentions
Windowsシステム環境では、必要なのは次のとおりです。
•Python(バージョン2.7.3、3.xは正常に機能できません)
•Microsoft Visual Studio C ++ 2010(Windows XP/Vista用)
•Windowsデスクトップ用のMicrosoft Visual Studio C ++ 2012(Windows 7/8用)
強調するために、Visual StudioのExpressバージョンも正常に機能します。
Binding.gypファイル
このファイルはNode-Gypで使用されており、プラグインに適切なビルドファイルを生成するように設計されています。ここをクリックして、Wikipediaが提供する.gypファイル説明ドキュメントを表示できますが、今日使用したい例は非常に簡単です。次のコードを使用する必要があります。
{"Targets":[{"Target_name": "stdstring"、 "sources":["addon.cc"、 "stdstring.cc"]}]}ターゲット_nameを好きなものに設定できる場合。ソースアレイには、プラグインが使用する必要があるすべてのソースファイルが含まれています。この例では、Addon.CCも含まれています。これは、プラグインとstdstring.ccをコンパイルするために必要なコードに対応するために使用されます。
stdstringwrapperクラス
最初のステップは、stdstring.hファイルで独自のクラスを定義することです。 C ++プログラミングに精通している場合、次の2行のコードに不慣れではありません。
#ifndef stdstring_h #define stdstring_h
これは、ガードを含む標準に属します。次に、以下の2つのヘッダーを含めるカテゴリに含める必要があります。
#含む
#含む
最初のものはSTD :: Stringクラスを対象としていますが、2番目にはすべてのノードとV8関連コンテンツのActsが含まれます。
このステップが完了した後、クラスを宣言できます。
クラスstdstringwrapper:public node :: objectwrap {
プラグインに含めるすべてのクラスについては、ノード:: objectWrapクラスを拡張する必要があります。
これで、このクラスの私有財産の定義を開始できます。
プライベート:std :: string* s_;明示的なstdstringwrapper(std :: string s = ""); 〜StdStringWrapper();
コンストラクターと分析機能に加えて、STD :: Stringのポインターも定義する必要があります。これはこのテクノロジーのコアであり、C/C ++コードベースをノードに接続するために使用できます。C/C ++クラスのプライベートポインターを定義し、このポインターを使用してその後のすべての方法で操作を実装します。
次に、v8で作成したクラスの関数を提供するコンストラクターの静的プロパティを宣言します。
静的V8 ::永続的なコンストラクター。
興味のある友人は、ここをクリックしてテンプレートの説明計画を参照してください。
また、上記のコンストラクターに割り当てられる新しい方法も必要です。V8はクラスを初期化します。
static v8 :: handle new(const v8 :: arguments&args);
V8に作用するすべての関数は、次の要件に従う必要があります。V8::引数オブジェクトへの参照を受け入れ、V8 ::ハンドル> V8 ::値を返します。
この後、オブジェクトのプロトタイプに他の2つの方法を挿入する必要があります。
static v8 :: handle add(const v8 :: arguments&args);静的V8 ::ハンドルToString(const v8 :: arguments&args);
ToString()メソッドを使用すると、通常のJavaScript文字列で使用する場合、[オブジェクトオブジェクト]の値の代わりにS_の値を取得できます。
最後に、初期化方法(この方法はV8によって呼び出され、コンストラクター機能に割り当てられます)を導入し、Closeを含むガードを含みます。
public:静的ボイドinit(v8 ::ハンドルエクスポート); }; #endif
JavaScriptモジュールにおけるエクスポートオブジェクトの役割は、Module.Exportsと同等です。
stdstring.ccファイル、コンストラクター、および解析機能
次に、stdstring.ccファイルを作成します。最初にヘッダーを含める必要があります。
#include "stdstring.h"
以下は、コンストラクターのプロパティを定義します(静的関数に属しているため)。
v8 ::永続的なstdstringwrapper :: constructor;
クラスにサービスを提供するこのコンストラクターは、S_属性を割り当てます。
stdstringwrapper :: stdstringwrapper(std :: string s){s_ = new std :: string(s); }そして、解析機能はそれを削除して、メモリのオーバーフローを避けます。
stdstringWrapper :: 〜STDStringWrapper(){delete s_; }さらに、そのような状況が例外を引き起こすたびに、上記の操作を覚えておくか、共有ポインターを使用するため、新しいもので割り当てられたすべてのコンテンツを削除する必要があります。
initメソッド
この方法はV8によって呼び出され、クラスを初期化することを目的としています(コンストラクターを割り当て、ExportsオブジェクトのJavaScriptで使用するすべてのコンテンツを配置します):
void stdstringwrapper :: init(v8 ::ハンドルエクスポート){
まず、新しい方法の関数テンプレートを作成する必要があります。
v8 :: local tpl = v8 :: functionTemplate :: new(new);
これは、JavaScriptの新しい機能に少し似ています。これにより、独自のJavaScriptクラスを準備できます。
これで、実際のニーズに応じて関数の名前を設定できます(このステップを見逃した場合、コンストラクターは匿名状態になります。つまり、名前はfunction somename(){}またはfunction(){})です。
tpl-> setClassName(v8 :: String :: Newsymbol( "stdstring"));
V8 :: String :: NewsyMbol()を使用して、プロパティ名の特別なタイプの文字列を作成します。これにより、エンジンの操作の時間を少し節約できます。
この後、クラスインスタンスに含まれるフィールドの数を設定する必要があります。
tpl-> instancetemplate() - > setInternalfieldCount(2);
add()とtoString()の2つの方法があるため、数値を2に設定します。これにより、関数プロトタイプに独自のメソッドを追加できます。
tpl-> prototypetemplate() - > set(v8 :: string :: newsymbol( "add")、v8 :: functionTemplate :: new(add) - > getFunction());
tpl-> prototypetemplate() - > set(v8 :: string :: newsymbol( "toString")、v8 :: functionTemplate :: new(toString) - > getFunction());
コードのこの部分は非常に大きく見えますが、注意深く観察する限り、ルールが見つかります。Tpl-> prototypetemplate() - > set()を使用して各メソッドを追加します。また、v8 :: string :: newsymbol()を使用して、名前とfunctiontemplateを提供します。
最後に、コンストラクタークラスプロパティ内のエクスポートオブジェクトにコンストラクターを配置できます。
constructor = v8 :: persistent :: new(tpl-> getFunction()); exports-> set(v8 :: string :: newsymbol( "stdstring")、constructor); }
新しい方法
ここで、私たちがしなければならないことは、JavaScriptオブジェクトと同じように機能する方法を定義することです。Prototype.Constructor:
v8 :: handle stdstringwrapper :: new(const v8 :: arguments&args){最初にスコープを作成する必要があります。
v8 ::ハンドルスコープスコープ;
この後、argsオブジェクトの.isconstructcall()メソッドを使用して、新しいキーワードを使用してコンストラクターを呼び出すことができるかどうかを確認できます。
if(args.isconstructcall()){可能であれば、最初に次のようにパラメーターをSTD ::文字列に渡します。
v8 :: string :: utf8value str(args [0] - > toString()); std :: string s(*str);
...そのため、カプセル化されたクラスのコンストラクターに渡すことができます。
stdstringwrapper* obj = new stdstringwrapper(s);
この後、以前に作成したオブジェクトの.wrap()メソッド(ノード:: objectWrapから継承)を使用して、この変数に割り当てることができます。
obj-> wrap(args.this());
最後に、この新しく作成されたオブジェクトを返すことができます。
args.this()を返します。
関数を新しいで呼び出すことができない場合は、コンストラクターを直接呼び出すこともできます。次に、私たちがしたいことは、パラメーターカウントの定数を設定することです。
} else {const int argc = 1;次に、独自のパラメーターを使用して配列を作成する必要があります。
v8 :: local argv [argc] = {args [0]};次に、constructor-> newinstanceメソッドの結果をscope.closeに渡して、オブジェクトが後で役割を再生できるようにします(Scope.closeは、基本的にオブジェクト処理ハンドルをより高い範囲に移動することで誰もが維持できるようにします - これは機能が有効になる方法でもあります):
return scope.close(constructor-> newinstance(argc、argv)); }}
メソッドを追加します
ここで、すべての人がオブジェクトの内部std :: stringにコンテンツを追加できるようにすることを目的としたADDメソッドを作成しましょう。
v8 :: handle stdstringwrapper :: add(const v8 :: arguments&args){まず、関数の範囲を作成し、以前のようにパラメーターをSTD :: Stringに変換する必要があります。
v8 ::ハンドルスコープスコープ; v8 :: string :: utf8value str(args [0] - > toString()); std :: string s(*str);
次に、オブジェクトを開梱する必要があります。また、この逆カプセル化操作も実行しました。今回は、この変数からオブジェクトへのポインターを取得します。
stdstringwrapper* obj = objectwrap :: unwrap(args.this());
その後、S_属性にアクセスして、その.Append()メソッドを使用できます。
obj-> s _-> append(s);
最後に、S_属性の現在の値を返します(scope.closeを再度使用する必要があります):
return scope.close(v8 :: string :: new(obj-> s _-> c_str()));
v8 :: string :: new()メソッドはchar pointerを値としてのみ受け入れることができるため、obj-> s _-> c_str()を使用して取得する必要があります。
現時点では、プラグインフォルダーにビルドディレクトリを作成する必要があります。
テスト
これで、プラグインをテストできます。プラグインディレクトリにtest.jsファイルと必要なコンピレーションライブラリを作成します(.node拡張子を直接スキップできます):
var addon = require( './ build/release/addon');
次に、オブジェクトの新しいインスタンスを作成します。
var test = new addon.stdstring( 'test');
次に、文字列に追加または変換するなど、それを行います。
test.add( '!'); console.log( 'test/' s contents:%s '、test);
実行後、コンソールで次の実行結果が表示されます。
結論は
このチュートリアルを読んだ後、懸念を払拭し、C/C ++ライブラリに基づいてカスタマイズされたnode.jsプラグインを非常に困難なタスクとして作成してテストできることを願っています。このテクノロジーを使用して、ほぼすべてのC/C ++ライブラリをnode.jsに簡単に紹介できます。必要に応じて、実際のニーズに応じてプラグインにさらに関数を追加することもできます。 STD :: Stringは多くの方法を提供し、それらを運動材料として使用できます。
実用的なリンク
興味のある友人は、Node.jsプラグイン開発、V8およびCイベントループライブラリに関連するより多くのリソースと詳細について、次のリンクを確認できます。
•node.jsプラグインドキュメント
•V8ドキュメント
•libuv(cイベントループライブラリ)、githubから
英語:http://code.tutsplus.com/tutorials/writing-nodejs-addons - cms-21771