>웹 프론트엔드 >JS 튜토리얼 >Node.js의 다양한 확장 메서드 코드 예제 요약

Node.js의 다양한 확장 메서드 코드 예제 요약

伊谢尔伦
伊谢尔伦원래의
2017-07-24 11:55:291555검색

Node.js 확장

Init 메서드

Node.js 확장을 생성하려면 node::ObjectWrap을 상속하는 C++ 클래스를 작성해야 합니다. ObjectWrap은 Javascript와 더 쉽게 상호 작용할 수 있도록 하는 공용 메서드를 구현합니다.

먼저 클래스의 기본 프레임워크를 작성해 보겠습니다.

#include <v8.h> // v8 is the Javascript engine used by QNode
#include <node.h>
// We will need the following libraries for our GTK+ notification
#include <string>
#include <gtkmm.h>
#include <libnotifymm.h>
 
using namespace v8;
 
class Gtknotify : node::ObjectWrap {
 private:
 public:
  Gtknotify() {}
  ~Gtknotify() {}
  static void Init(Handle<Object> target) {
   // This is what Node will call when we load the extension through require(), see boilerplate code below.
  }
};
 
/*
 * WARNING: Boilerplate code ahead.
 * Thats it for actual interfacing with v8, finally we need to let Node.js know how to dynamically load our code.
 * Because a Node.js extension can be loaded at runtime from a shared object, we need a symbol that the dlsym function can find,
 * so we do the following: 
 */
 
v8::Persistent<FunctionTemplate> Gtknotify::persistent_function_template;
extern "C" { // Cause of name mangling in C++, we use extern C here
 static void init(Handle<Object> target) {
  Gtknotify::Init(target);
 }
 NODE_MODULE(gtknotify, init);
}

이제 Init() 메서드에 다음 코드를 작성해야 합니다.

생성자를 선언합니다. 그리고 이를 목표 변수에 바인딩합니다. var n = require("notification"); 알림()을 n:n.notification().

// Wrap our C++ New() method so that it&#39;s accessible from Javascript
  // This will be called by the new operator in Javascript, for example: new notification();
  v8::Local<FunctionTemplate> local_function_template = v8::FunctionTemplate::New(New);
   
  // Make it persistent and assign it to persistent_function_template which is a static attribute of our class.
  Gtknotify::persistent_function_template = v8::Persistent<FunctionTemplate>::New(local_function_template);
   
  // Each JavaScript object keeps a reference to the C++ object for which it is a wrapper with an internal field.
  Gtknotify::persistent_function_template->InstanceTemplate()->SetInternalFieldCount(1); // 1 since a constructor function only references 1 object
  // Set a "class" name for objects created with our constructor
  Gtknotify::persistent_function_template->SetClassName(v8::String::NewSymbol("Notification"));
   
  // Set the "notification" property of our target variable and assign it to our constructor function
  target->Set(String::NewSymbol("notification"), Gtknotify::persistent_function_template->GetFunction());

에 바인딩합니다. 속성 선언: n.title 및 n.icon.

  // Set property accessors
  // SetAccessor arguments: Javascript property name, C++ method that will act as the getter, C++ method that will act as the setter
  Gtknotify::persistent_function_template->InstanceTemplate()->SetAccessor(String::New("title"), GetTitle, SetTitle);
  Gtknotify::persistent_function_template->InstanceTemplate()->SetAccessor(String::New("icon"), GetIcon, SetIcon);
  // For instance, n.title = "foo" will now call SetTitle("foo"), n.title will now call GetTitle()

프로토타입 메서드 선언: n . send()

  // This is a Node macro to help bind C++ methods to Javascript methods (see https://github.com/joyent/node/blob/v0.2.0/src/node.h#L34)
  // Arguments: our constructor function, Javascript method name, C++ method name
  NODE_SET_PROTOTYPE_METHOD(Gtknotify::persistent_function_template, "send", Send);

이제 Init() 메서드는 다음과 같아야 합니다.

// Our constructor
static v8::Persistent<FunctionTemplate> persistent_function_template;
 
static void Init(Handle<Object> target) {
 v8::HandleScope scope; // used by v8 for garbage collection
 
 // Our constructor
 v8::Local<FunctionTemplate> local_function_template = v8::FunctionTemplate::New(New);
 Gtknotify::persistent_function_template = v8::Persistent<FunctionTemplate>::New(local_function_template);
 Gtknotify::persistent_function_template->InstanceTemplate()->SetInternalFieldCount(1); // 1 since this is a constructor function
 Gtknotify::persistent_function_template->SetClassName(v8::String::NewSymbol("Notification"));
 
 // Our getters and setters
 Gtknotify::persistent_function_template->InstanceTemplate()->SetAccessor(String::New("title"), GetTitle, SetTitle);
 Gtknotify::persistent_function_template->InstanceTemplate()->SetAccessor(String::New("icon"), GetIcon, SetIcon);
 
 // Our methods
 NODE_SET_PROTOTYPE_METHOD(Gtknotify::persistent_function_template, "send", Send);
 
 // Binding our constructor function to the target variable
 target->Set(String::NewSymbol("notification"), Gtknotify::persistent_function_template->GetFunction());
}

남은 일은 Init 메서드에서 사용하는 C++ 메서드(New, GetTitle, SetTitle, GetIcon, SetIcon,Send
)를 작성하는 것입니다.

생성자 메소드: New()

New() 메소드는 사용자 정의 클래스(Gtknotify 객체)의 새 인스턴스를 생성하고 일부 초기 값을 설정한 다음 객체의 JavaScript 처리를 반환합니다. 이는 new 연산자를 사용하여 생성자를 호출하는 JavaScript의 예상되는 동작입니다.

 std::string title;
std::string icon;
 
// new notification()
static Handle<Value> New(const Arguments& args) {
 HandleScope scope;
 Gtknotify* gtknotify_instance = new Gtknotify();
 // Set some default values
 gtknotify_instance->title = "Node.js";
 gtknotify_instance->icon = "terminal";
 
 // Wrap our C++ object as a Javascript object
 gtknotify_instance->Wrap(args.This());
 
 return args.This();
}
getters 和 setters: GetTitle(), SetTitle(), GetIcon(), SetIcon()

다음은 대부분 C++와 JavaScript(v8) 간의 값 변환으로 귀결되는 상용구 코드입니다.

// this.title
static v8::Handle<Value> GetTitle(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
 // Extract the C++ request object from the JavaScript wrapper.
 Gtknotify* gtknotify_instance = node::ObjectWrap::Unwrap<Gtknotify>(info.Holder());
 return v8::String::New(gtknotify_instance->title.c_str());
}
// this.title=
static void SetTitle(Local<String> property, Local<Value> value, const AccessorInfo& info) {
 Gtknotify* gtknotify_instance = node::ObjectWrap::Unwrap<Gtknotify>(info.Holder());
 v8::String::Utf8Value v8str(value);
 gtknotify_instance->title = *v8str;
}
// this.icon
static v8::Handle<Value> GetIcon(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
 // Extract the C++ request object from the JavaScript wrapper.
 Gtknotify* gtknotify_instance = node::ObjectWrap::Unwrap<Gtknotify>(info.Holder());
 return v8::String::New(gtknotify_instance->icon.c_str());
}
// this.icon=
static void SetIcon(Local<String> property, Local<Value> value, const AccessorInfo& info) {
 Gtknotify* gtknotify_instance = node::ObjectWrap::Unwrap<Gtknotify>(info.Holder());
 v8::String::Utf8Value v8str(value);
 gtknotify_instance->icon = *v8str;
}

프로토타입 메서드: Send()

먼저 C++ 개체의 참조를 추출한 다음 개체의 속성을 사용하여 알림을 작성하고 표시합니다.

// this.send()
static v8::Handle<Value> Send(const Arguments& args) {
 v8::HandleScope scope;
 // Extract C++ object reference from "this"
 Gtknotify* gtknotify_instance = node::ObjectWrap::Unwrap<Gtknotify>(args.This());
 
 // Convert first argument to V8 String
 v8::String::Utf8Value v8str(args[0]);
 
 // For more info on the Notify library: http://library.gnome.org/devel/libnotify/0.7/NotifyNotification.html
 Notify::init("Basic");
 // Arguments: title, content, icon
 Notify::Notification n(gtknotify_instance->title.c_str(), *v8str, gtknotify_instance->icon.c_str()); // *v8str points to the C string it wraps
 // Display the notification
 n.show();
 // Return value
 return v8::Boolean::New(true);
}

Compile Extensions

node-waf는 waf의 기본 패키지인 Node Extensions를 컴파일하는 데 사용되는 빌드 도구입니다. 빌드 프로세스는 wscript라는 파일을 통해 구성할 수 있습니다.

def set_options(opt):
 opt.tool_options("compiler_cxx")
 
def configure(conf):
 conf.check_tool("compiler_cxx")
 conf.check_tool("node_addon")
 # This will tell the compiler to link our extension with the gtkmm and libnotifymm libraries.
 conf.check_cfg(package=&#39;gtkmm-2.4&#39;, args=&#39;--cflags --libs&#39;, uselib_store=&#39;LIBGTKMM&#39;)
 conf.check_cfg(package=&#39;libnotifymm-1.0&#39;, args=&#39;--cflags --libs&#39;, uselib_store=&#39;LIBNOTIFYMM&#39;)
 
def build(bld):
 obj = bld.new_task_gen("cxx", "shlib", "node_addon")
 obj.cxxflags = ["-g", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE", "-Wall"]
 # This is the name of our extension.
 obj.target = "gtknotify"
 obj.source = "src/node_gtknotify.cpp"
 obj.uselib = [&#39;LIBGTKMM&#39;, &#39;LIBNOTIFYMM&#39;]

이제 빌드를 시작할 준비가 되었습니다. 최상위 디렉터리에서 다음 명령을 실행하세요.

node-wafconfigure && node-waf build

모든 것이 순조롭게 진행되면 다음 위치에 컴파일된 확장 프로그램이 생성됩니다. ./ build/default/gtknotify.node, 시도해 보세요:

$ node
> var notif = require(&#39;./build/default/gtknotify.node&#39;);
> n = new notif.notification();
{ icon: &#39;terminal&#39;, title: &#39;Node.js&#39; }
> n.send("Hello World!");
true

위 코드는 화면 오른쪽 상단에 알림 메시지를 표시합니다.

npm 패키지로 빌드하세요

정말 멋지네요. 그런데 노력의 결과를 Node 커뮤니티와 어떻게 공유하시나요? 이것이 npm의 주요 목적입니다: 확장 및 배포를 더 쉽게 만드는 것입니다.

npm 확장 패키지 빌드는 매우 간단합니다. 확장에 대한 정보가 포함된 package.json 파일을 최상위 디렉터리에 생성하기만 하면 됩니다.

{
 // 扩展的名称 (不要在名称中包含node 或者 js, 这是隐式关键字).
 // 这是通过require() 导入扩展的名称.
 
 "name" : "notify",
 
 // Version should be http://semver.org/ compliant
 
 "version" : "v0.1.0"
 
 // 这些脚本将在调用npm安装和npm卸载的时候运行.
 
 , "scripts" : {
   "preinstall" : "node-waf configure && node-waf build"
   , "preuninstall" : "rm -rf build/*"
  }
 
 // 这是构建我们扩展的相对路径.
 
 , "main" : "build/default/gtknotify.node"
 
 // 以下是可选字段:
 
 , "description" : "Description of the extension...."
 , "homepage" : "https://github.com/olalonde/node-notify"
 , "author" : {
   "name" : "Olivier Lalonde"
   , "email" : "olalonde@gmail.com"
   , "url" : "http://www.syskall.com/"
  }
 , "repository" : {
   "type" : "git"
   , "url" : "https://github.com/olalonde/node-notify.git"
  }
}

package.json 형식에 대한 자세한 내용은 npm을 통해 확인할 수 있습니다. help json 문서. 대부분의 필드는 선택 사항입니다.

이제 최상위 디렉터리에서 npm install을 실행하여 새 npm 패키지를 설치할 수 있습니다. 모든 작업이 제대로 진행되면 확장 프로그램을 로드하기만 하면 됩니다. require('패키지 이름');. 또 다른 유용한 필수 npm 링크입니다. 이 명령을 사용하면 개발 디렉터리에 대한 링크를 만들 수 있으므로 코드가 변경될 때마다 설치할 필요가 없습니다. 멋진 확장 프로그램을 작성했다고 가정하고 중앙 npm 저장소에 온라인으로 게시하고 싶을 수도 있습니다. 먼저 계정을 생성해야 합니다.

$ npm adduser
다음으로 루트 코딩 디렉터리로 돌아가서 다음을 실행합니다.
 $ npm publish

그렇습니다. 이제 패키지 이름과 함께 npm install 명령을 사용하여 누구나 패키지를 설치할 수 있습니다.

위 내용은 Node.js의 다양한 확장 메서드 코드 예제 요약의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.