昔発生した落とし穴 - Node.js を使用して NBUT のオンライン ジャッジを再構築する際、評価側も含めて再構築する必要がありました。 (いつ完成するかは心配しないでください(/‵Д´)/~ ╧╧
つまり、今私たちがしなければならないことは、実際に C/C を使用して Node.js モジュールを実装することです。
準備
労働者が自分の仕事をうまくやり遂げたいなら、まず~~悪党を演じ~~、自分の道具を研ぐ必要があります。
ノード-gyp
まず、node-gyp モジュールが必要です。
任意のコーナーで、次を実行します:
一連のなんとかの後で、あなたはインストールされます。
パイソン
そうするとPython環境が必要になります。
公式ウェブサイトにアクセスしてご自身で入手してください。
注:node-gyp の GitHub によると、Python のバージョンが 2.5.0 ~ 3.0.0 であることを確認してください。
コンパイル環境
うーん、詳しく書くのが面倒なので、node-gyp にアクセスしてコンパイラの要件を確認してください。そしてよく注ぎます。
はじめに
公式 Web サイトの Hello World の紹介について少しお話しましょう。
ハローワールド
C ファイルを用意してください (たとえば ~~sb.cc~~ hello.cc という名前)。
それでは、段階的に進みましょう。最初にヘッダー ファイルを作成し、名前空間を定義します。
メイン関数
次に、戻り値が Handle
それでは、これらのことを簡単に分析してみましょう:
ハンドル
人間としての誠実さを持っていなければなりません、ここから引用することをあらかじめ断っておきます(@fool)。
V8 は、Handle 型を使用して JavaScript オブジェクトをホストします。C の std::sharedpointer と同様に、Handle 型間の割り当てはオブジェクト参照を直接渡しますが、違いは、V8 がインテリジェントな一般的に使用される参照ではなく、独自の GC を使用してオブジェクトのライフサイクルを管理することです。ポインタをカウントしています。
JavaScript の型には、C の対応するカスタム型 (String、Integer、Object、Date、Array など) があり、JavaScript の継承関係に厳密に準拠します。これらの型を C で使用する場合は、ネイティブ スタックとヒープを使用する代わりに、ハンドル管理を使用して GC を使用してライフ サイクルを管理する必要があります。
このいわゆる Value は、V8 エンジンのヘッダー ファイル v8.h のさまざまな継承関係からわかります。これは、実際には JavaScript のさまざまなオブジェクトの基本クラスです。
このことを理解すると、不定型の値を返す Hello 関数を書くという上記の関数宣言の意味が大体理解できると思います。
注: Handle の管理下では、特定の型 (String、Integer など) のみを返すことができます。
引数
これは、この関数に渡されるパラメータです。 Node.js ではパラメーターの数がランダムであることは誰もが知っています。これらのパラメーターが C に渡されると、この Arguments 型のオブジェクトに変換されます。
具体的な使い方については後ほど説明します。ここでは、これが何であるかを理解する必要があります。 (なぜそんなに注意するのですか?公式の Node.js ドキュメントの例は個別に説明されているからです。私は今、最初の Hello World の例について話しているだけです (´థ౪థ)σ
貢献
次に、レンガとタイルを追加し始めました。たった 2 つの簡単な文:
この 2 つの文は何を意味しますか?大まかな意味は、Node.js で文字列「world」を返すことです。
ハンドルスコープ
同じ参照がここから来ています。
Handle のライフサイクルは C スマート ポインターのライフサイクルとは異なり、C セマンティクスの範囲 (つまり、{} で囲まれた部分) 内には存在しません。HandleScope を通じて手動で指定する必要があります。 HandleScope オブジェクトはスタック上にのみ配置できます。HandleScope オブジェクトが宣言された後、その後に作成される Handle のライフサイクルは HandleScope オブジェクトが破棄された後、GC によって判断されます。リサイクルされた。
したがって、ライフサイクルを管理する必要がある場合は、このスコープを宣言する必要があります。では、なぜコードがこのようにならないのでしょうか?
関数が戻るとスコープは破棄され、スコープが管理するハンドルもリサイクルされるため、この String は無意味になります。
そこで、V8 は魔法のアイデア、HandleScope::Close(Handle
したがって、前のコードのscope.Close(String::New("world")); があります。
文字列::新規
この String クラスは、Node.js のネイティブ String クラスに対応します。 Value クラスから継承されます。これに似たものとして、
もあります。•配列
•整数
•ブール値
•オブジェクト
•日付
•番号
•機能
•...
これらの一部は Value から継承され、一部は 2 回継承されます。ここではあまり調査しません。V8 コード (少なくともヘッダー ファイル) を確認するか、このマニュアルを読んでください。
では、この New はどうでしょうか?ここで見ることができます。新しい String オブジェクトを作成するだけです。
この時点で、この main 関数の分析は完了しました。
オブジェクトのエクスポート
Node.js で記述する場合、関数やオブジェクトをどのようにエクスポートするかを確認してみましょう。
では、これを C でどのように行うのでしょうか?
初期化関数
まず、初期化関数を作成します。
これはカメのお尻です!関数名が何であっても構いませんが、渡されるパラメータは Handle
次に、エクスポートされた内容をここに書き込みます:
一般的な意味は、このエクスポート オブジェクトに hello というフィールドを追加し、対応するものが関数であり、この関数が親愛なる Hello 関数であるということです。
擬似コードでわかりやすく言うと:
完成しました!
(終わったよお姉ちゃん!黙ってろ(‘д‘⊂彡☆))Д´)
真・エクスポート
これは最後のステップであり、これがエクスポートの入り口であることを最終的に宣言する必要があるため、コードの最後に次の行を追加します。
NODE_MODULE(こんにちは、初期化)
心配しないでください。この NODE_MODULE はマクロです。つまり、init 初期化関数を使用して、hello にエクスポートされるものをエクスポートします。では、この「こんにちは」はどこから来たのでしょうか?
ファイル名から来ています!はい、そうです、それはファイル名から来ています。事前に宣言する必要はなく、それが使用できないことを心配する必要はありません。つまり、最終的にコンパイルされたバイナリ ファイルの名前が何であっても、ここに hello を入力します。もちろん接尾語。
詳細については、公式ドキュメントを参照してください。
すべての Node アドオンは初期化関数をエクスポートする必要があることに注意してください:
module_name は、最終バイナリのファイル名 (.node 接尾辞を除く) と一致する必要があります。
コンパイル (๑•́ ₃ •̀๑)
Makefile に似た新しいアーカイブ ファイル binding.gyp を作成しましょう。
そしてこのコードを中に追加します:
設定
ファイルの準備ができたら、このディレクトリで次のコマンドを実行する必要があります:
ビルド
Makefile が生成されたら、構築とコンパイルを開始します。
$node-gyp build
ゲイになれ!ノードヽ(✿゚▽゚)ノC
先ほどディレクトリに新しいファイル jianfeizao.js を作成します。
寝てください。次のセクションではさらに詳しく説明します
遅くなりましたので、今日はここで書き終えます。Hello world の最も基本的な C 拡張機能は、もう誰でも作成できるようになります。次回はもっと詳しく書く予定ですが、次回はいつになるかはわかりません。
(おいおい、オナホってこんなに無責任なもんだ!(o゚ロ゚)┌┛Σ(ノ´ω`)ノ