Dre4m Shell
Server IP : 127.0.0.2  /  Your IP : 13.58.229.23
Web Server : Apache/2.4.18 (Ubuntu)
System :
User : www-data ( )
PHP Version : 7.0.33-0ubuntu0.16.04.16
Disable Function : disk_free_space,disk_total_space,diskfreespace,dl,exec,fpaththru,getmyuid,getmypid,highlight_file,ignore_user_abord,leak,listen,link,opcache_get_configuration,opcache_get_status,passthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,php_uname,phpinfo,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix,_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,posix_getsid,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_times,posix_ttyname,posix_uname,pclose,popen,proc_open,proc_close,proc_get_status,proc_nice,proc_terminate,shell_exec,source,show_source,system,virtual
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /usr/share/doc/nodejs/api/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME SHELL ]     

Current File : /usr/share/doc/nodejs/api/addons.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Addons Node.js v4.2.6 Manual &amp; Documentation</title>
  <link rel="stylesheet" href="assets/style.css">
  <link rel="stylesheet" href="assets/sh.css">
  <link rel="canonical" href="addons.html">
</head>
<body class="alt apidoc" id="api-section-addons">
  <div id="content" class="clearfix">
    <div id="column2" class="interior">
      <div id="intro" class="interior">
        <a href="/" title="Go back to the home page">
          Node.js (1)
        </a>
      </div>
      <ul>
<li><a class="nav-documentation" href="documentation.html">About these Docs</a></li>
<li><a class="nav-synopsis" href="synopsis.html">Synopsis</a></li>
<li><a class="nav-assert" href="assert.html">Assertion Testing</a></li>
<li><a class="nav-buffer" href="buffer.html">Buffer</a></li>
<li><a class="nav-addons active" href="addons.html">C/C++ Addons</a></li>
<li><a class="nav-child_process" href="child_process.html">Child Processes</a></li>
<li><a class="nav-cluster" href="cluster.html">Cluster</a></li>
<li><a class="nav-console" href="console.html">Console</a></li>
<li><a class="nav-crypto" href="crypto.html">Crypto</a></li>
<li><a class="nav-debugger" href="debugger.html">Debugger</a></li>
<li><a class="nav-dns" href="dns.html">DNS</a></li>
<li><a class="nav-domain" href="domain.html">Domain</a></li>
<li><a class="nav-errors" href="errors.html">Errors</a></li>
<li><a class="nav-events" href="events.html">Events</a></li>
<li><a class="nav-fs" href="fs.html">File System</a></li>
<li><a class="nav-globals" href="globals.html">Globals</a></li>
<li><a class="nav-http" href="http.html">HTTP</a></li>
<li><a class="nav-https" href="https.html">HTTPS</a></li>
<li><a class="nav-modules" href="modules.html">Modules</a></li>
<li><a class="nav-net" href="net.html">Net</a></li>
<li><a class="nav-os" href="os.html">OS</a></li>
<li><a class="nav-path" href="path.html">Path</a></li>
<li><a class="nav-process" href="process.html">Process</a></li>
<li><a class="nav-punycode" href="punycode.html">Punycode</a></li>
<li><a class="nav-querystring" href="querystring.html">Query Strings</a></li>
<li><a class="nav-readline" href="readline.html">Readline</a></li>
<li><a class="nav-repl" href="repl.html">REPL</a></li>
<li><a class="nav-stream" href="stream.html">Stream</a></li>
<li><a class="nav-string_decoder" href="string_decoder.html">String Decoder</a></li>
<li><a class="nav-timers" href="timers.html">Timers</a></li>
<li><a class="nav-tls" href="tls.html">TLS/SSL</a></li>
<li><a class="nav-tty" href="tty.html">TTY</a></li>
<li><a class="nav-dgram" href="dgram.html">UDP/Datagram</a></li>
<li><a class="nav-url" href="url.html">URL</a></li>
<li><a class="nav-util" href="util.html">Utilities</a></li>
<li><a class="nav-v8" href="v8.html">V8</a></li>
<li><a class="nav-vm" href="vm.html">VM</a></li>
<li><a class="nav-zlib" href="zlib.html">ZLIB</a></li>
</ul>

    </div>

    <div id="column1" data-id="addons" class="interior">
      <header>
        <h1>Node.js v4.2.6 Documentation</h1>
        <div id="gtoc">
          <p>
            <a href="index.html" name="toc">Index</a> |
            <a href="all.html">View on single page</a> |
            <a href="addons.json">View as JSON</a>
          </p>
        </div>
        <hr>
      </header>

      <div id="toc">
        <h2>Table of Contents</h2>
        <ul>
<li><a href="#addons_addons">Addons</a><ul>
<li><a href="#addons_hello_world">Hello world</a></li>
<li><a href="#addons_addon_patterns">Addon patterns</a><ul>
<li><a href="#addons_function_arguments">Function arguments</a></li>
<li><a href="#addons_callbacks">Callbacks</a></li>
<li><a href="#addons_object_factory">Object factory</a></li>
<li><a href="#addons_function_factory">Function factory</a></li>
<li><a href="#addons_wrapping_c_objects">Wrapping C++ objects</a></li>
<li><a href="#addons_factory_of_wrapped_objects">Factory of wrapped objects</a></li>
<li><a href="#addons_passing_wrapped_objects_around">Passing wrapped objects around</a></li>
<li><a href="#addons_atexit_hooks">AtExit hooks</a><ul>
<li><a href="#addons_void_atexit_callback_args">void AtExit(callback, args)</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

      </div>

      <div id="apicontent">
        <h1>Addons<span><a class="mark" href="#addons_addons" id="addons_addons">#</a></span></h1>
<p>Addons are dynamically-linked shared objects. They can provide glue to C and
C++ libraries. The API (at the moment) is rather complex, involving
knowledge of several libraries:

</p>
<ul>
<li><p>V8 JavaScript, a C++ library. Used for interfacing with JavaScript:
creating objects, calling functions, etc.  Documented mostly in the
<code>v8.h</code> header file (<code>deps/v8/include/v8.h</code> in the Node.js source
tree), which is also available <a href="https://v8docs.nodesource.com/">online</a>.</p>
</li>
<li><p><a href="https://github.com/libuv/libuv">libuv</a>, C event loop library. Anytime one needs to wait for a file
descriptor to become readable, wait for a timer, or wait for a signal
to be received, one will need to interface with libuv. That is, if you
perform any I/O, libuv will need to be used.</p>
</li>
<li><p>Internal Node.js libraries. The most important class is <code>node::ObjectWrap</code>
which you will likely want to derive from.</p>
</li>
<li><p>Others. Look in <code>deps/</code> for what else is available.</p>
</li>
</ul>
<p>Node.js statically compiles all its dependencies into the executable.
When compiling your module, you don&#39;t need to worry about linking to
any of these libraries.

</p>
<p>All of the following examples are available for <a href="https://github.com/nodejs/node-addon-examples">download</a> and may
be used as a starting-point for your own Addon.

</p>
<h2>Hello world<span><a class="mark" href="#addons_hello_world" id="addons_hello_world">#</a></span></h2>
<p>To get started, let&#39;s make a small Addon which is the C++ equivalent of
the following JavaScript code:

</p>
<pre><code>module.exports.hello = function() { return &#39;world&#39;; };</code></pre>
<p>First we create a file <code>hello.cc</code>:

</p>
<pre><code>// hello.cc
#include &lt;node.h&gt;

namespace demo {

using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

void Method(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  Isolate* isolate = args.GetIsolate();
  args.GetReturnValue().Set(String::NewFromUtf8(isolate, &quot;world&quot;));
}

void init(Local&lt;Object&gt; exports) {
  NODE_SET_METHOD(exports, &quot;hello&quot;, Method);
}

NODE_MODULE(addon, init)

}  // namespace demo</code></pre>
<p>Note that all Node.js addons must export an initialization function:

</p>
<pre><code>void Initialize(Local&lt;Object&gt; exports);
NODE_MODULE(module_name, Initialize)</code></pre>
<p>There is no semi-colon after <code>NODE_MODULE</code> as it&#39;s not a function (see
<code>node.h</code>).

</p>
<p>The <code>module_name</code> needs to match the filename of the final binary (excluding
the .node suffix).

</p>
<p>The source code needs to be built into <code>addon.node</code>, the binary Addon. To
do this, we create a file called <code>binding.gyp</code> which describes the configuration
to build your module in a JSON-like format. This file gets compiled by
<a href="https://github.com/nodejs/node-gyp">node-gyp</a>.

</p>
<pre><code>{
  &quot;targets&quot;: [
    {
      &quot;target_name&quot;: &quot;addon&quot;,
      &quot;sources&quot;: [ &quot;hello.cc&quot; ]
    }
  ]
}</code></pre>
<p>The next step is to generate the appropriate project build files for the
current platform. Use <code>node-gyp configure</code> for that.

</p>
<p>Now you will have either a <code>Makefile</code> (on Unix platforms) or a <code>vcxproj</code> file
(on Windows) in the <code>build/</code> directory. Next, invoke the <code>node-gyp build</code>
command.

</p>
<p>Now you have your compiled <code>.node</code> bindings file! The compiled bindings end up
in <code>build/Release/</code>.

</p>
<p>You can now use the binary addon in a Node.js project <code>hello.js</code> by pointing
<code>require</code> to the recently built <code>hello.node</code> module:

</p>
<pre><code>// hello.js
const addon = require(&#39;./build/Release/addon&#39;);

console.log(addon.hello()); // &#39;world&#39;</code></pre>
<p>Please see patterns below for further information or
</p>
<p><a href="https://github.com/arturadib/node-qt">https://github.com/arturadib/node-qt</a> for an example in production.


</p>
<h2>Addon patterns<span><a class="mark" href="#addons_addon_patterns" id="addons_addon_patterns">#</a></span></h2>
<p>Below are some addon patterns to help you get started. Consult the online
<a href="http://izs.me/v8-docs/main.html">v8 reference</a> for help with the various v8 calls, and v8&#39;s
<a href="https://code.google.com/apis/v8/embed.html">Embedder&#39;s Guide</a> for an explanation of several concepts used such as
handles, scopes, function templates, etc.

</p>
<p>In order to use these examples, you need to compile them using <code>node-gyp</code>.
Create the following <code>binding.gyp</code> file:

</p>
<pre><code>{
  &quot;targets&quot;: [
    {
      &quot;target_name&quot;: &quot;addon&quot;,
      &quot;sources&quot;: [ &quot;addon.cc&quot; ]
    }
  ]
}</code></pre>
<p>In cases where there is more than one <code>.cc</code> file, simply add the file name to
the <code>sources</code> array. For example:

</p>
<pre><code>&quot;sources&quot;: [&quot;addon.cc&quot;, &quot;myexample.cc&quot;]</code></pre>
<p>Now that you have your <code>binding.gyp</code> ready, you can configure and build the
addon:

</p>
<pre><code>$ node-gyp configure build</code></pre>
<h3>Function arguments<span><a class="mark" href="#addons_function_arguments" id="addons_function_arguments">#</a></span></h3>
<p>The following pattern illustrates how to read arguments from JavaScript
function calls and return a result. This is the main and only needed source
<code>addon.cc</code>:

</p>
<pre><code>// addon.cc
#include &lt;node.h&gt;

namespace demo {

using v8::Exception;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;

void Add(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  Isolate* isolate = args.GetIsolate();

  if (args.Length() &lt; 2) {
    isolate-&gt;ThrowException(Exception::TypeError(
        String::NewFromUtf8(isolate, &quot;Wrong number of arguments&quot;)));
    return;
  }

  if (!args[0]-&gt;IsNumber() || !args[1]-&gt;IsNumber()) {
    isolate-&gt;ThrowException(Exception::TypeError(
        String::NewFromUtf8(isolate, &quot;Wrong arguments&quot;)));
    return;
  }

  double value = args[0]-&gt;NumberValue() + args[1]-&gt;NumberValue();
  Local&lt;Number&gt; num = Number::New(isolate, value);

  args.GetReturnValue().Set(num);
}

void Init(Local&lt;Object&gt; exports) {
  NODE_SET_METHOD(exports, &quot;add&quot;, Add);
}

NODE_MODULE(addon, Init)

}  // namespace demo</code></pre>
<p>You can test it with the following JavaScript snippet:

</p>
<pre><code>// test.js
const addon = require(&#39;./build/Release/addon&#39;);

console.log( &#39;This should be eight:&#39;, addon.add(3,5) );</code></pre>
<h3>Callbacks<span><a class="mark" href="#addons_callbacks" id="addons_callbacks">#</a></span></h3>
<p>You can pass JavaScript functions to a C++ function and execute them from
there. Here&#39;s <code>addon.cc</code>:

</p>
<pre><code>// addon.cc
#include &lt;node.h&gt;

namespace demo {

using v8::Function;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Null;
using v8::Object;
using v8::String;
using v8::Value;

void RunCallback(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  Isolate* isolate = args.GetIsolate();
  Local&lt;Function&gt; cb = Local&lt;Function&gt;::Cast(args[0]);
  const unsigned argc = 1;
  Local&lt;Value&gt; argv[argc] = { String::NewFromUtf8(isolate, &quot;hello world&quot;) };
  cb-&gt;Call(Null(isolate), argc, argv);
}

void Init(Local&lt;Object&gt; exports, Local&lt;Object&gt; module) {
  NODE_SET_METHOD(module, &quot;exports&quot;, RunCallback);
}

NODE_MODULE(addon, Init)

}  // namespace demo</code></pre>
<p>Note that this example uses a two-argument form of <code>Init()</code> that receives
the full <code>module</code> object as the second argument. This allows the addon
to completely overwrite <code>exports</code> with a single function instead of
adding the function as a property of <code>exports</code>.

</p>
<p>To test it, run the following JavaScript snippet:

</p>
<pre><code>// test.js
const addon = require(&#39;./build/Release/addon&#39;);

addon(function(msg){
  console.log(msg); // &#39;hello world&#39;
});</code></pre>
<h3>Object factory<span><a class="mark" href="#addons_object_factory" id="addons_object_factory">#</a></span></h3>
<p>You can create and return new objects from within a C++ function with this
<code>addon.cc</code> pattern, which returns an object with property <code>msg</code> that echoes
the string passed to <code>createObject()</code>:

</p>
<pre><code>// addon.cc
#include &lt;node.h&gt;

namespace demo {

using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

void CreateObject(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  Isolate* isolate = args.GetIsolate();

  Local&lt;Object&gt; obj = Object::New(isolate);
  obj-&gt;Set(String::NewFromUtf8(isolate, &quot;msg&quot;), args[0]-&gt;ToString());

  args.GetReturnValue().Set(obj);
}

void Init(Local&lt;Object&gt; exports, Local&lt;Object&gt; module) {
  NODE_SET_METHOD(module, &quot;exports&quot;, CreateObject);
}

NODE_MODULE(addon, Init)

}  // namespace demo</code></pre>
<p>To test it in JavaScript:

</p>
<pre><code>// test.js
const addon = require(&#39;./build/Release/addon&#39;);

var obj1 = addon(&#39;hello&#39;);
var obj2 = addon(&#39;world&#39;);
console.log(obj1.msg+&#39; &#39;+obj2.msg); // &#39;hello world&#39;</code></pre>
<h3>Function factory<span><a class="mark" href="#addons_function_factory" id="addons_function_factory">#</a></span></h3>
<p>This pattern illustrates how to create and return a JavaScript function that
wraps a C++ function:

</p>
<pre><code>// addon.cc
#include &lt;node.h&gt;

namespace demo {

using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

void MyFunction(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  Isolate* isolate = args.GetIsolate();
  args.GetReturnValue().Set(String::NewFromUtf8(isolate, &quot;hello world&quot;));
}

void CreateFunction(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  Isolate* isolate = args.GetIsolate();

  Local&lt;FunctionTemplate&gt; tpl = FunctionTemplate::New(isolate, MyFunction);
  Local&lt;Function&gt; fn = tpl-&gt;GetFunction();

  // omit this to make it anonymous
  fn-&gt;SetName(String::NewFromUtf8(isolate, &quot;theFunction&quot;));

  args.GetReturnValue().Set(fn);
}

void Init(Local&lt;Object&gt; exports, Local&lt;Object&gt; module) {
  NODE_SET_METHOD(module, &quot;exports&quot;, CreateFunction);
}

NODE_MODULE(addon, Init)

}  // namespace demo</code></pre>
<p>To test:

</p>
<pre><code>// test.js
const addon = require(&#39;./build/Release/addon&#39;);

var fn = addon();
console.log(fn()); // &#39;hello world&#39;</code></pre>
<h3>Wrapping C++ objects<span><a class="mark" href="#addons_wrapping_c_objects" id="addons_wrapping_c_objects">#</a></span></h3>
<p>Here, we will create a wrapper for a C++ object/class <code>MyObject</code> that can be
instantiated in JavaScript through the <code>new</code> operator. First, prepare the main
module <code>addon.cc</code>:

</p>
<pre><code>// addon.cc
#include &lt;node.h&gt;
#include &quot;myobject.h&quot;

namespace demo {

using v8::Local;
using v8::Object;

void InitAll(Local&lt;Object&gt; exports) {
  MyObject::Init(exports);
}

NODE_MODULE(addon, InitAll)

}  // namespace demo</code></pre>
<p>Then, in <code>myobject.h</code>, make your wrapper inherit from <code>node::ObjectWrap</code>:

</p>
<pre><code>// myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H

#include &lt;node.h&gt;
#include &lt;node_object_wrap.h&gt;

namespace demo {

class MyObject : public node::ObjectWrap {
 public:
  static void Init(v8::Local&lt;v8::Object&gt; exports);

 private:
  explicit MyObject(double value = 0);
  ~MyObject();

  static void New(const v8::FunctionCallbackInfo&lt;v8::Value&gt;&amp; args);
  static void PlusOne(const v8::FunctionCallbackInfo&lt;v8::Value&gt;&amp; args);
  static v8::Persistent&lt;v8::Function&gt; constructor;
  double value_;
};

}  // namespace demo

#endif</code></pre>
<p>And in <code>myobject.cc</code>, implement the various methods that you want to expose.
Here we expose the method <code>plusOne</code> by adding it to the constructor&#39;s
prototype:

</p>
<pre><code>// myobject.cc
#include &quot;myobject.h&quot;

namespace demo {

using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::Persistent;
using v8::String;
using v8::Value;

Persistent&lt;Function&gt; MyObject::constructor;

MyObject::MyObject(double value) : value_(value) {
}

MyObject::~MyObject() {
}

void MyObject::Init(Local&lt;Object&gt; exports) {
  Isolate* isolate = exports-&gt;GetIsolate();

  // Prepare constructor template
  Local&lt;FunctionTemplate&gt; tpl = FunctionTemplate::New(isolate, New);
  tpl-&gt;SetClassName(String::NewFromUtf8(isolate, &quot;MyObject&quot;));
  tpl-&gt;InstanceTemplate()-&gt;SetInternalFieldCount(1);

  // Prototype
  NODE_SET_PROTOTYPE_METHOD(tpl, &quot;plusOne&quot;, PlusOne);

  constructor.Reset(isolate, tpl-&gt;GetFunction());
  exports-&gt;Set(String::NewFromUtf8(isolate, &quot;MyObject&quot;),
               tpl-&gt;GetFunction());
}

void MyObject::New(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  Isolate* isolate = args.GetIsolate();

  if (args.IsConstructCall()) {
    // Invoked as constructor: `new MyObject(...)`
    double value = args[0]-&gt;IsUndefined() ? 0 : args[0]-&gt;NumberValue();
    MyObject* obj = new MyObject(value);
    obj-&gt;Wrap(args.This());
    args.GetReturnValue().Set(args.This());
  } else {
    // Invoked as plain function `MyObject(...)`, turn into construct call.
    const int argc = 1;
    Local&lt;Value&gt; argv[argc] = { args[0] };
    Local&lt;Function&gt; cons = Local&lt;Function&gt;::New(isolate, constructor);
    args.GetReturnValue().Set(cons-&gt;NewInstance(argc, argv));
  }
}

void MyObject::PlusOne(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  Isolate* isolate = args.GetIsolate();

  MyObject* obj = ObjectWrap::Unwrap&lt;MyObject&gt;(args.Holder());
  obj-&gt;value_ += 1;

  args.GetReturnValue().Set(Number::New(isolate, obj-&gt;value_));
}

}  // namespace demo</code></pre>
<p>Test it with:

</p>
<pre><code>// test.js
const addon = require(&#39;./build/Release/addon&#39;);

var obj = new addon.MyObject(10);
console.log( obj.plusOne() ); // 11
console.log( obj.plusOne() ); // 12
console.log( obj.plusOne() ); // 13</code></pre>
<h3>Factory of wrapped objects<span><a class="mark" href="#addons_factory_of_wrapped_objects" id="addons_factory_of_wrapped_objects">#</a></span></h3>
<p>This is useful when you want to be able to create native objects without
explicitly instantiating them with the <code>new</code> operator in JavaScript. For
example:

</p>
<pre><code>var obj = addon.createObject();
// instead of:
// var obj = new addon.Object();</code></pre>
<p>Let&#39;s register our <code>createObject</code> method in <code>addon.cc</code>:

</p>
<pre><code>// addon.cc
#include &lt;node.h&gt;
#include &quot;myobject.h&quot;

namespace demo {

using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

void CreateObject(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  MyObject::NewInstance(args);
}

void InitAll(Local&lt;Object&gt; exports, Local&lt;Object&gt; module) {
  MyObject::Init(exports-&gt;GetIsolate());

  NODE_SET_METHOD(module, &quot;exports&quot;, CreateObject);
}

NODE_MODULE(addon, InitAll)

}  // namespace demo</code></pre>
<p>In <code>myobject.h</code>, we now introduce the static method <code>NewInstance</code> that takes
care of instantiating the object. In other words, it does the job of <code>new</code> in
JavaScript:

</p>
<pre><code>// myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H

#include &lt;node.h&gt;
#include &lt;node_object_wrap.h&gt;

namespace demo {

class MyObject : public node::ObjectWrap {
 public:
  static void Init(v8::Isolate* isolate);
  static void NewInstance(const v8::FunctionCallbackInfo&lt;v8::Value&gt;&amp; args);

 private:
  explicit MyObject(double value = 0);
  ~MyObject();

  static void New(const v8::FunctionCallbackInfo&lt;v8::Value&gt;&amp; args);
  static void PlusOne(const v8::FunctionCallbackInfo&lt;v8::Value&gt;&amp; args);
  static v8::Persistent&lt;v8::Function&gt; constructor;
  double value_;
};

}  // namespace demo

#endif</code></pre>
<p>The implementation is similar to the above in <code>myobject.cc</code>:

</p>
<pre><code>// myobject.cc
#include &lt;node.h&gt;
#include &quot;myobject.h&quot;

namespace demo {

using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::Persistent;
using v8::String;
using v8::Value;

Persistent&lt;Function&gt; MyObject::constructor;

MyObject::MyObject(double value) : value_(value) {
}

MyObject::~MyObject() {
}

void MyObject::Init(Isolate* isolate) {
  // Prepare constructor template
  Local&lt;FunctionTemplate&gt; tpl = FunctionTemplate::New(isolate, New);
  tpl-&gt;SetClassName(String::NewFromUtf8(isolate, &quot;MyObject&quot;));
  tpl-&gt;InstanceTemplate()-&gt;SetInternalFieldCount(1);

  // Prototype
  NODE_SET_PROTOTYPE_METHOD(tpl, &quot;plusOne&quot;, PlusOne);

  constructor.Reset(isolate, tpl-&gt;GetFunction());
}

void MyObject::New(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  Isolate* isolate = args.GetIsolate();

  if (args.IsConstructCall()) {
    // Invoked as constructor: `new MyObject(...)`
    double value = args[0]-&gt;IsUndefined() ? 0 : args[0]-&gt;NumberValue();
    MyObject* obj = new MyObject(value);
    obj-&gt;Wrap(args.This());
    args.GetReturnValue().Set(args.This());
  } else {
    // Invoked as plain function `MyObject(...)`, turn into construct call.
    const int argc = 1;
    Local&lt;Value&gt; argv[argc] = { args[0] };
    Local&lt;Function&gt; cons = Local&lt;Function&gt;::New(isolate, constructor);
    args.GetReturnValue().Set(cons-&gt;NewInstance(argc, argv));
  }
}

void MyObject::NewInstance(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  Isolate* isolate = args.GetIsolate();

  const unsigned argc = 1;
  Local&lt;Value&gt; argv[argc] = { args[0] };
  Local&lt;Function&gt; cons = Local&lt;Function&gt;::New(isolate, constructor);
  Local&lt;Object&gt; instance = cons-&gt;NewInstance(argc, argv);

  args.GetReturnValue().Set(instance);
}

void MyObject::PlusOne(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  Isolate* isolate = args.GetIsolate();

  MyObject* obj = ObjectWrap::Unwrap&lt;MyObject&gt;(args.Holder());
  obj-&gt;value_ += 1;

  args.GetReturnValue().Set(Number::New(isolate, obj-&gt;value_));
}

}  // namespace demo</code></pre>
<p>Test it with:

</p>
<pre><code>// test.js
const createObject = require(&#39;./build/Release/addon&#39;);

var obj = createObject(10);
console.log( obj.plusOne() ); // 11
console.log( obj.plusOne() ); // 12
console.log( obj.plusOne() ); // 13

var obj2 = createObject(20);
console.log( obj2.plusOne() ); // 21
console.log( obj2.plusOne() ); // 22
console.log( obj2.plusOne() ); // 23</code></pre>
<h3>Passing wrapped objects around<span><a class="mark" href="#addons_passing_wrapped_objects_around" id="addons_passing_wrapped_objects_around">#</a></span></h3>
<p>In addition to wrapping and returning C++ objects, you can pass them around
by unwrapping them with the Node.js helper function <code>node::ObjectWrap::Unwrap</code>.
In the following <code>addon.cc</code>, we introduce a function <code>add()</code> that can take on
two <code>MyObject</code> objects:

</p>
<pre><code>// addon.cc
#include &lt;node.h&gt;
#include &lt;node_object_wrap.h&gt;
#include &quot;myobject.h&quot;

namespace demo {

using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;

void CreateObject(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  MyObject::NewInstance(args);
}

void Add(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  Isolate* isolate = args.GetIsolate();

  MyObject* obj1 = node::ObjectWrap::Unwrap&lt;MyObject&gt;(
      args[0]-&gt;ToObject());
  MyObject* obj2 = node::ObjectWrap::Unwrap&lt;MyObject&gt;(
      args[1]-&gt;ToObject());

  double sum = obj1-&gt;value() + obj2-&gt;value();
  args.GetReturnValue().Set(Number::New(isolate, sum));
}

void InitAll(Local&lt;Object&gt; exports) {
  MyObject::Init(exports-&gt;GetIsolate());

  NODE_SET_METHOD(exports, &quot;createObject&quot;, CreateObject);
  NODE_SET_METHOD(exports, &quot;add&quot;, Add);
}

NODE_MODULE(addon, InitAll)

}  // namespace demo</code></pre>
<p>To make things interesting, we introduce a public method in <code>myobject.h</code> so we
can probe private values after unwrapping the object:

</p>
<pre><code>// myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H

#include &lt;node.h&gt;
#include &lt;node_object_wrap.h&gt;

namespace demo {

class MyObject : public node::ObjectWrap {
 public:
  static void Init(v8::Isolate* isolate);
  static void NewInstance(const v8::FunctionCallbackInfo&lt;v8::Value&gt;&amp; args);
  inline double value() const { return value_; }

 private:
  explicit MyObject(double value = 0);
  ~MyObject();

  static void New(const v8::FunctionCallbackInfo&lt;v8::Value&gt;&amp; args);
  static v8::Persistent&lt;v8::Function&gt; constructor;
  double value_;
};

}  // namespace demo

#endif</code></pre>
<p>The implementation of <code>myobject.cc</code> is similar to before:

</p>
<pre><code>// myobject.cc
#include &lt;node.h&gt;
#include &quot;myobject.h&quot;

namespace demo {

using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::Persistent;
using v8::String;
using v8::Value;

Persistent&lt;Function&gt; MyObject::constructor;

MyObject::MyObject(double value) : value_(value) {
}

MyObject::~MyObject() {
}

void MyObject::Init(Isolate* isolate) {
  // Prepare constructor template
  Local&lt;FunctionTemplate&gt; tpl = FunctionTemplate::New(isolate, New);
  tpl-&gt;SetClassName(String::NewFromUtf8(isolate, &quot;MyObject&quot;));
  tpl-&gt;InstanceTemplate()-&gt;SetInternalFieldCount(1);

  constructor.Reset(isolate, tpl-&gt;GetFunction());
}

void MyObject::New(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  Isolate* isolate = args.GetIsolate();

  if (args.IsConstructCall()) {
    // Invoked as constructor: `new MyObject(...)`
    double value = args[0]-&gt;IsUndefined() ? 0 : args[0]-&gt;NumberValue();
    MyObject* obj = new MyObject(value);
    obj-&gt;Wrap(args.This());
    args.GetReturnValue().Set(args.This());
  } else {
    // Invoked as plain function `MyObject(...)`, turn into construct call.
    const int argc = 1;
    Local&lt;Value&gt; argv[argc] = { args[0] };
    Local&lt;Function&gt; cons = Local&lt;Function&gt;::New(isolate, constructor);
    args.GetReturnValue().Set(cons-&gt;NewInstance(argc, argv));
  }
}

void MyObject::NewInstance(const FunctionCallbackInfo&lt;Value&gt;&amp; args) {
  Isolate* isolate = args.GetIsolate();

  const unsigned argc = 1;
  Local&lt;Value&gt; argv[argc] = { args[0] };
  Local&lt;Function&gt; cons = Local&lt;Function&gt;::New(isolate, constructor);
  Local&lt;Object&gt; instance = cons-&gt;NewInstance(argc, argv);

  args.GetReturnValue().Set(instance);
}

}  // namespace demo</code></pre>
<p>Test it with:

</p>
<pre><code>// test.js
const addon = require(&#39;./build/Release/addon&#39;);

var obj1 = addon.createObject(10);
var obj2 = addon.createObject(20);
var result = addon.add(obj1, obj2);

console.log(result); // 30</code></pre>
<h3>AtExit hooks<span><a class="mark" href="#addons_atexit_hooks" id="addons_atexit_hooks">#</a></span></h3>
<h4>void AtExit(callback, args)<span><a class="mark" href="#addons_void_atexit_callback_args" id="addons_void_atexit_callback_args">#</a></span></h4>
<ul>
<li><code>callback</code>: <code>void (*)(void*)</code> - A pointer to the function to call at exit.</li>
<li><code>args</code>: <code>void*</code> - A pointer to pass to the callback at exit.</li>
</ul>
<p>Registers exit hooks that run after the event loop has ended but before the VM
is killed.

</p>
<p>Callbacks are run in last-in first-out order. AtExit takes two parameters:
a pointer to a callback function to run at exit, and a pointer to untyped
context data to be passed to that callback.

</p>
<p>The file <code>addon.cc</code> implements AtExit below:

</p>
<pre><code>// addon.cc
#undef NDEBUG
#include &lt;assert.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;node.h&gt;

namespace demo {

using node::AtExit;
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::Object;

static char cookie[] = &quot;yum yum&quot;;
static int at_exit_cb1_called = 0;
static int at_exit_cb2_called = 0;

static void at_exit_cb1(void* arg) {
  Isolate* isolate = static_cast&lt;Isolate*&gt;(arg);
  HandleScope scope(isolate);
  Local&lt;Object&gt; obj = Object::New(isolate);
  assert(!obj.IsEmpty()); // assert VM is still alive
  assert(obj-&gt;IsObject());
  at_exit_cb1_called++;
}

static void at_exit_cb2(void* arg) {
  assert(arg == static_cast&lt;void*&gt;(cookie));
  at_exit_cb2_called++;
}

static void sanity_check(void*) {
  assert(at_exit_cb1_called == 1);
  assert(at_exit_cb2_called == 2);
}

void init(Local&lt;Object&gt; exports) {
  AtExit(sanity_check);
  AtExit(at_exit_cb2, cookie);
  AtExit(at_exit_cb2, cookie);
  AtExit(at_exit_cb1, exports-&gt;GetIsolate());
}

NODE_MODULE(addon, init);

}  // namespace demo</code></pre>
<p>Test in JavaScript by running:

</p>
<pre><code>// test.js
const addon = require(&#39;./build/Release/addon&#39;);</code></pre>

      </div>
    </div>
  </div>
  <script src="assets/sh_main.js"></script>
  <script src="assets/sh_javascript.min.js"></script>
  <script>highlight(undefined, undefined, 'pre');</script>
</body>
</html>


Anon7 - 2022
AnonSec Team