ホームページ ウェブフロントエンド jsチュートリアル Node.js_node.js でコンポーネントを実装する 3 つの方法

Node.js_node.js でコンポーネントを実装する 3 つの方法

May 16, 2016 pm 03:13 PM

まず、v8 API の使用と swig フレームワークの使用の違いを紹介します。

(1) v8 API メソッドは、強力で完全な機能を備えた公式が提供するネイティブ メソッドです。欠点は、v8 API に精通する必要があり、作成がより面倒であることです。 js に変換されるため、他のスクリプト言語を簡単にサポートすることはできません。

(2) swig はサードパーティのサポートであり、Python、lua、js などのさまざまな一般的なスクリプト言語用の C++ コンポーネント パッケージング コードの生成をサポートする強力なコンポーネント開発ツールです。swig ユーザーは次のことのみを行う必要があります。 C++ コードを記述し、設定ファイルを変更する さまざまなスクリプト言語のコンポーネント開発フレームワークを知らなくても、さまざまなスクリプト言語で C++ コンポーネントを開発できます。欠点は、JavaScript コールバックがサポートされていないこと、ドキュメントとデモ コードが不完全であることです。ユーザーは多くありません。

1. Node.js コンポーネントを実装するための Pure JS
(1) helloworld ディレクトリに移動し、npm init を実行して package.json を初期化します。さまざまなオプションを無視し、デフォルトのままにします。

(2) コンポーネント実装index.js、例:

module.exports.Hello = function(name) {
    console.log('Hello ' + name);
}
ログイン後にコピー

(3) 外側のディレクトリで実行します: npm install ./helloworld、helloworld は、node_modules ディレクトリにインストールされます。
(4) コンポーネント使用コードを記述します:

var m = require('helloworld');
m.Hello('zhangsan');
//输出: Hello zhangsan
ログイン後にコピー

2. v8 API を使用して JS コンポーネントを実装する - 同期モード
(1) binding.gyp を書き込みます。例:

{
 "targets": [
  {
   "target_name": "hello",
   "sources": [ "hello.cpp" ]
  }
 ]
}
ログイン後にコピー

(2) コンポーネント hello.cpp の実装を記述します。例:

#include <node.h>

namespace cpphello {
  using v8::FunctionCallbackInfo;
  using v8::Isolate;
  using v8::Local;
  using v8::Object;
  using v8::String;
  using v8::Value;

  void Foo(const FunctionCallbackInfo<Value>& args) {
    Isolate* isolate = args.GetIsolate();
    args.GetReturnValue().Set(String::NewFromUtf8(isolate, "Hello World"));
  }

  void Init(Local<Object> exports) {
    NODE_SET_METHOD(exports, "foo", Foo);
  }

  NODE_MODULE(cpphello, Init)
}

ログイン後にコピー

(3) コンポーネントをコンパイルします

node-gyp configure
node-gyp build
./build/Release/目录下会生成hello.node模块。
ログイン後にコピー

(4) テスト用のjsコードを書く

const m = require('./build/Release/hello')
console.log(m.foo()); //输出 Hello World
ログイン後にコピー

(5) インストール用に package.json を追加します。例:

{                                                                                                         
  "name": "hello",
  "version": "1.0.0",
  "description": "", 
  "main": "index.js",
  "scripts": {
    "test": "node test.js"
  }, 
  "author": "", 
  "license": "ISC"
}
ログイン後にコピー

(5) コンポーネントをnode_modulesにインストールします

コンポーネント ディレクトリの上位ディレクトリに移動し、次のコマンドを実行します: npm install ./hloc //注: helloc はコンポーネント ディレクトリです
hello モジュールは現在のディレクトリの node_modules ディレクトリにインストールされます。テスト コードは次のように記述されます。

var m = require('hello');
console.log(m.foo());  
ログイン後にコピー
3. v8 API を使用して JS コンポーネントを実装する - 非同期モード

上記の説明は同期コンポーネントです。 foo() 関数は同期関数です。つまり、foo() 関数の呼び出し元は、foo() 関数が実行を完了するまで待つ必要があります。 IO に時間のかかる操作、関数、非同期 foo() 関数を使用すると、ブロッキング待機が軽減され、全体的なパフォーマンスが向上します。

非同期コンポーネントを実装するには、libuv の uv_queue_work API に注意するだけで済みます。メイン コード hello.cpp とコンポーネント ユーザー コードを除き、他の部分は上記の 3 つのデモと一致します。

hello.cpp:

/*
* Node.js cpp Addons demo: async call and call back.
* gcc 4.8.2
* author:cswuyg
* Date:2016.02.22
* */
#include <iostream>
#include <node.h>
#include <uv.h> 
#include <sstream>
#include <unistd.h>
#include <pthread.h>

namespace cpphello {
  using v8::FunctionCallbackInfo;
  using v8::Function;
  using v8::Isolate;
  using v8::Local;
  using v8::Object;
  using v8::Value;
  using v8::Exception;
  using v8::Persistent;
  using v8::HandleScope;
  using v8::Integer;
  using v8::String;

  // async task
  struct MyTask{
    uv_work_t work;
    int a{0};
    int b{0};
    int output{0};
    unsigned long long work_tid{0};
    unsigned long long main_tid{0};
    Persistent<Function> callback;
  };

  // async function
  void query_async(uv_work_t* work) {
    MyTask* task = (MyTask*)work->data;
    task->output = task->a + task->b;
    task->work_tid = pthread_self();
    usleep(1000 * 1000 * 1); // 1 second
  }

  // async complete callback
  void query_finish(uv_work_t* work, int status) {
    Isolate* isolate = Isolate::GetCurrent();
    HandleScope handle_scope(isolate);
    MyTask* task = (MyTask*)work->data;
    const unsigned int argc = 3;
    std::stringstream stream;
    stream << task->main_tid;
    std::string main_tid_s{stream.str()};
    stream.str("");
    stream << task->work_tid;
    std::string work_tid_s{stream.str()};
    
    Local<Value> argv[argc] = {
      Integer::New(isolate, task->output), 
      String::NewFromUtf8(isolate, main_tid_s.c_str()),
      String::NewFromUtf8(isolate, work_tid_s.c_str())
    };
    Local<Function>::New(isolate, task->callback)->Call(isolate->GetCurrentContext()->Global(), argc, argv);
    task->callback.Reset();
    delete task;
  }

  // async main
  void async_foo(const FunctionCallbackInfo<Value>& args) {
    Isolate* isolate = args.GetIsolate();
    HandleScope handle_scope(isolate);
    if (args.Length() != 3) {
      isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "arguments num : 3")));
      return;
    } 
    if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsFunction()) {
      isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "arguments error")));
      return;
    }
    MyTask* my_task = new MyTask;
    my_task->a = args[0]->ToInteger()->Value();
    my_task->b = args[1]->ToInteger()->Value();
    my_task->callback.Reset(isolate, Local<Function>::Cast(args[2]));
    my_task->work.data = my_task;
    my_task->main_tid = pthread_self();
    uv_loop_t *loop = uv_default_loop();
    uv_queue_work(loop, &my_task->work, query_async, query_finish); 
  }

  void Init(Local<Object> exports) {
    NODE_SET_METHOD(exports, "foo", async_foo);
  }

  NODE_MODULE(cpphello, Init)
}

ログイン後にコピー
非同期の考え方は非常に簡単で、作業関数、完了関数、およびクロススレッド送信用のデータを運ぶ構造体を実装するには、uv_queue_work を呼び出すだけです。難しいのは、v8 のデータ構造と API に慣れることです。

テスト.js

// test helloUV module
'use strict';
const m = require('helloUV')

m.foo(1, 2, (a, b, c)=>{
  console.log('finish job:' + a);
  console.log('main thread:' + b);
  console.log('work thread:' + c);
});
/*
output:
finish job:3
main thread:139660941432640
work thread:139660876334848
*/

ログイン後にコピー
4. swig-javascript は Node.js コンポーネントを実装します

swig フレームワークを使用して Node.js コンポーネントを作成します

(1) コンポーネントの実装を作成します: *.h および *.cpp

例:

namespace a {
  class A{
  public:
    int add(int a, int y);
  };
  int add(int x, int y);
}
ログイン後にコピー
(2) swig パッケージングの cpp ファイルの生成に使用される *.i を書き込みます

例:

/* File : IExport.i */
%module my_mod 
%include "typemaps.i"
%include "std_string.i"
%include "std_vector.i"
%{
#include "export.h"
%}
 
%apply int *OUTPUT { int *result, int* xx};
%apply std::string *OUTPUT { std::string* result, std::string* yy };
%apply std::string &OUTPUT { std::string& result };                                                                                
 
%include "export.h"
namespace std {
  %template(vectori) vector<int>;
  %template(vectorstr) vector<std::string>;
};
ログイン後にコピー
上記の %apply は、コード内の int* result、int* xx、std::string* result、std::string* yy、std::string& result が出力の説明であることを意味します。交換品。

C++ 関数パラメータのポインタ パラメータが値 (*.i ファイルの OUTPUT で指定) を返す場合、Swig はそれらを JS 関数の戻り値として処理します。複数のポインタがある場合は、JS 関数の戻り値です。はリストです。
%template(vectori) Vector は、vectori 型が JS に対して定義されていることを意味します。これは、通常、vector をパラメータまたは戻り値として使用する C++ 関数です。
(3)node-gyp
を使用してコンパイル用の binding.gyp を作成します (4) warpper cpp ファイルを生成します。生成するときは、v8 バージョン情報に注意してください。例: swig -javascript -node -c++ -DV8_VERSION=0x040599 example.i
(5) コンパイル&テスト
問題は、stl 型とカスタム型の使用にあります。この点に関する公式ドキュメントは少なすぎます。
swig - std::vector、std::string の JavaScript カプセル化の使用。主に *.i ファイルの実装に焦点を当てた私の演習を参照してください。

5.その他
v8 API を使用して Node.js コンポーネントを実装する場合、Lua コンポーネントの実装との類似点がわかります。Lua にはステート マシンがあり、Node には Isolate があります。

Node がオブジェクトのエクスポートを実装する場合、コンストラクターを実装し、それに「メンバー関数」を追加し、最後にコンストラクターをクラス名としてエクスポートする必要があります。 Lua がオブジェクトのエクスポートを実装する場合、オブジェクトを作成するためのファクトリ関数も実装する必要があり、テーブルに「メンバー関数」を追加する必要もあります。最後に、ファクトリー関数をエクスポートします。

Node の js スクリプトには new キーワードがありますが、Lua にはありません。そのため、Lua はオブジェクトを作成するための外部オブジェクト ファクトリのみを提供しますが、Node はオブジェクト ファクトリまたはクラスのカプセル化を提供できます。

以上がこの記事の全内容です。皆様の学習のお役に立てれば幸いです。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

独自のJavaScriptライブラリを作成および公開するにはどうすればよいですか? 独自のJavaScriptライブラリを作成および公開するにはどうすればよいですか? Mar 18, 2025 pm 03:12 PM

記事では、JavaScriptライブラリの作成、公開、および維持について説明し、計画、開発、テスト、ドキュメント、およびプロモーション戦略に焦点を当てています。

ブラウザでのパフォーマンスのためにJavaScriptコードを最適化するにはどうすればよいですか? ブラウザでのパフォーマンスのためにJavaScriptコードを最適化するにはどうすればよいですか? Mar 18, 2025 pm 03:14 PM

この記事では、ブラウザでJavaScriptのパフォーマンスを最適化するための戦略について説明し、実行時間の短縮、ページの負荷速度への影響を最小限に抑えることに焦点を当てています。

フロントエンドのサーマルペーパーレシートのために文字化けしたコード印刷に遭遇した場合はどうすればよいですか? フロントエンドのサーマルペーパーレシートのために文字化けしたコード印刷に遭遇した場合はどうすればよいですか? Apr 04, 2025 pm 02:42 PM

フロントエンドのサーマルペーパーチケット印刷のためのよくある質問とソリューションフロントエンド開発におけるチケット印刷は、一般的な要件です。しかし、多くの開発者が実装しています...

誰がより多くのPythonまたはJavaScriptを支払われますか? 誰がより多くのPythonまたはJavaScriptを支払われますか? Apr 04, 2025 am 12:09 AM

スキルや業界のニーズに応じて、PythonおよびJavaScript開発者には絶対的な給与はありません。 1. Pythonは、データサイエンスと機械学習でさらに支払われる場合があります。 2。JavaScriptは、フロントエンドとフルスタックの開発に大きな需要があり、その給与もかなりです。 3。影響要因には、経験、地理的位置、会社の規模、特定のスキルが含まれます。

ブラウザ開発者ツールを使用してJavaScriptコードを効果的にデバッグするにはどうすればよいですか? ブラウザ開発者ツールを使用してJavaScriptコードを効果的にデバッグするにはどうすればよいですか? Mar 18, 2025 pm 03:16 PM

この記事では、ブラウザ開発者ツールを使用した効果的なJavaScriptデバッグについて説明し、ブレークポイントの設定、コンソールの使用、パフォーマンスの分析に焦点を当てています。

ソースマップを使用して、マイナイドJavaScriptコードをデバッグするにはどうすればよいですか? ソースマップを使用して、マイナイドJavaScriptコードをデバッグするにはどうすればよいですか? Mar 18, 2025 pm 03:17 PM

この記事では、ソースマップを使用して、元のコードにマッピングすることにより、Minified JavaScriptをデバッグする方法について説明します。ソースマップの有効化、ブレークポイントの設定、Chrome DevtoolsやWebpackなどのツールの使用について説明します。

JavaScriptを使用して、同じIDを持つArray要素を1つのオブジェクトにマージする方法は? JavaScriptを使用して、同じIDを持つArray要素を1つのオブジェクトにマージする方法は? Apr 04, 2025 pm 05:09 PM

同じIDを持つ配列要素をJavaScriptの1つのオブジェクトにマージする方法は?データを処理するとき、私たちはしばしば同じIDを持つ必要性に遭遇します...

javascriptの分解:それが何をするのか、なぜそれが重要なのか javascriptの分解:それが何をするのか、なぜそれが重要なのか Apr 09, 2025 am 12:07 AM

JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

See all articles