{
  "source": "addons.markdown",
  "modules": [
    {
      "textRaw": "Addons插件",
      "name": "addons插件",
      "desc": "<p>Addons are dynamically linked shared objects. They can provide glue to C and\nC++ libraries. The API (at the moment) is rather complex, involving\nknowledge of several libraries:\n\n</p>\n<p>Addons插件就是动态连接库。它类似胶水，将c、c++和Node粘贴起来。它的API（目前来说）相当复杂，涉及到了几个类库的知识。\n\n</p>\n<ul>\n<li><p>V8 JavaScript, a C++ library. Used for interfacing with JavaScript:\ncreating objects, calling functions, etc.  Documented mostly in the\n<code>v8.h</code> header file (<code>deps/v8/include/v8.h</code> in the Node source\ntree), which is also available\n<a href=\"http://izs.me/v8-docs/main.html\">online</a>.</p>\n</li>\n<li><p>V8 JavaScript引擎,一个 C++ 类库. 用于和JavaScript进行交互的接口。\n创建对象, 调用函数等. 文档大部分在这里：\n<code>v8.h</code> 头文件 (<code>deps/v8/include/v8.h</code>在Node源代码目录里), 也有可用的线上文档\n<a href=\"http://izs.me/v8-docs/main.html\">线上</a>.\n（译者：想要学习c++的addons插件编写，必须先了解v8的接口）</p>\n</li>\n<li><p><a href=\"https://github.com/joyent/libuv\">libuv</a>, C event loop library.\nAnytime one needs to wait for a file descriptor to become readable,\nwait for a timer, or wait for a signal to be received one will need\nto interface with libuv. That is, if you perform any I/O, libuv will\nneed to be used.</p>\n</li>\n<li><p><a href=\"https://github.com/joyent/libuv\">libuv</a>, C语言编写的事件循环类库。任何时候需要等待一个文件描述符变为可读状态，等待一个定时器，或者等待一个接受信号都需要使用libuv类库的接口。也就是说，如果你执行任何I/O操作，libuv类库将会被用到。</p>\n</li>\n<li><p>Internal Node libraries. Most importantly is the <code>node::ObjectWrap</code>\nclass which you will likely want to derive from.</p>\n</li>\n<li><p>内部 Node 类库.最重要的接口就是 <code>node::ObjectWrap</code> 类，这个类你应该是最可能想要派生的。</p>\n</li>\n<li><p>Others. Look in <code>deps/</code> for what else is available.</p>\n</li>\n<li><p>其他.请参阅 <code>deps/</code> 获得更多可用类库。</p>\n</li>\n</ul>\n<p>Node statically compiles all its dependencies into the executable.\nWhen compiling your module, you don&apos;t need to worry about linking to\nany of these libraries.\n\n</p>\n<p>Node 静态编译了所有依赖到它的可执行文件中去了。当编译你的模块时，你不必担心无法连接上述那些类库。\n（译者：换而言之，你在编译自己的addons插件时，只管在头部 #include <uv.h>，不必在binding.gyp中声明）\n\n</p>\n<p>All of the following examples are available for\n<a href=\"https://github.com/rvagg/node-addon-examples\">download</a> and may be\nused as a starting-point for your own Addon.\n\n</p>\n<p>下面所有的例子都可以下载到：\n<a href=\"https://github.com/rvagg/node-addon-examples\">下载</a> \n这或许能成为你学习和创作自己addon插件的起点。\n\n</p>\n",
      "modules": [
        {
          "textRaw": "Hello world（世界你好）",
          "name": "hello_world（世界你好）",
          "desc": "<p>To get started let&apos;s make a small Addon which is the C++ equivalent of\nthe following JavaScript code:\n\n</p>\n<p>作为开始，让我们用编写一个小的addon插件，这个addon插件的c++代码相当于下面的JavaScript代码。\n\n</p>\n<pre><code>module.exports.hello = function() { return &apos;world&apos;; };</code></pre>\n<p>First we create a file <code>hello.cc</code>:\n\n</p>\n<p>首先我们创建一个 <code>hello.cc</code>文件:\n\n</p>\n<pre><code>NODE_MODULE(hello, init)//译者：将addon插件名hello和上述init函数关联输出</code></pre>\n<p>Note that all Node addons must export an initialization function:\n\n</p>\n<p>注意所有Node的addons插件都必须输出一个初始化函数：\n\n</p>\n<pre><code>void Initialize (Handle&lt;Object&gt; exports);\nNODE_MODULE(module_name, Initialize)</code></pre>\n<p>There is no semi-colon after <code>NODE_MODULE</code> as it&apos;s not a function (see\n<code>node.h</code>).\n\n</p>\n<p>在<code>NODE_MODULE</code>之后没有分号，因为它不是一个函数（请参阅<code>node.h</code>）\n\n</p>\n<p>The <code>module_name</code> needs to match the filename of the final binary (minus the\n.node suffix).\n\n</p>\n<p>这个<code>module_name</code>（模块名）需要和最后编译生成的2进制文件名（减去.node后缀名）相同。\n\n</p>\n<p>The source code needs to be built into <code>hello.node</code>, the binary Addon. To\ndo this we create a file called <code>binding.gyp</code> which describes the configuration\nto build your module in a JSON-like format. This file gets compiled by\n<a href=\"https://github.com/TooTallNate/node-gyp\">node-gyp</a>.\n\n</p>\n<p>源代码需要生成在<code>hello.node</code>，这个2进制addon插件中。\n需要做到这些，我们要创建一个名为<code>binding.gyp</code>的文件，它描述了创建这个模块的配置，并且它的格式是类似JSON的。\n文件将被命令：<a href=\"https://github.com/TooTallNate/node-gyp\">node-gyp</a> 编译。\n\n</p>\n<pre><code>{\n  &quot;targets&quot;: [\n    {\n      &quot;target_name&quot;: &quot;hello&quot;, //译者：addon插件名，注意这里的名字必需和上面NODE_MODULE中的一致\n      &quot;sources&quot;: [ &quot;hello.cc&quot; ]  //译者：这是需要编译的源文件\n    }\n  ]\n}</code></pre>\n<p>The next step is to generate the appropriate project build files for the\ncurrent platform. Use <code>node-gyp configure</code> for that.\n\n</p>\n<p>下一步是根据当前的操作系统平台，利用<code>node-gyp configure</code>命令，生成合适的项目文件。\n\n</p>\n<p>Now you will have either a <code>Makefile</code> (on Unix platforms) or a <code>vcxproj</code> file\n(on Windows) in the <code>build/</code> directory. Next invoke the <code>node-gyp build</code>\ncommand.\n\n</p>\n<p>现在你会有一个<code>Makefile</code> (在Unix平台) 或者一个 <code>vcxproj</code> file\n(在Windows上)，它们都在<code>build/</code> 文件夹中. \n然后执行命令 <code>node-gyp build</code>进行编译。\n（译者：当然你可以执行 <code>node-gyp rebuild</code>一步搞定）\n\n</p>\n<p>Now you have your compiled <code>.node</code> bindings file! The compiled bindings end up\nin <code>build/Release/</code>.\n\n</p>\n<p>现在你已经有了编译好的 <code>.node</code> 文件了，这个编译好的绑定文件会在目录 <code>build/Release/</code>下\n\n</p>\n<p>You can now use the binary addon in a Node project <code>hello.js</code> by pointing\n<code>require</code> to the recently built <code>hello.node</code> module:\n\n</p>\n<p>现在你可以使用这个2进制addon插件在Node项目<code>hello.js</code> 中了，通过指明<code>require</code>这个刚刚创建的<code>hello.node</code>模块使用它。\n\n</p>\n<pre><code>console.log(addon.hello()); // &apos;world&apos;</code></pre>\n<p>Please see patterns below for further information or\n</p>\n<p><a href=\"https://github.com/arturadib/node-qt\">https://github.com/arturadib/node-qt</a> for an example in production.\n\n</p>\n<p>请阅读下面的内容获得更多详情或者访问<a href=\"https://github.com/arturadib/node-qt\">https://github.com/arturadib/node-qt</a>获取一个生产环境的例子。\n\n</p>\n",
          "type": "module",
          "displayName": "Hello world（世界你好）"
        },
        {
          "textRaw": "Addon patterns（插件方式）",
          "name": "addon_patterns（插件方式）",
          "desc": "<p>Below are some addon patterns to help you get started. Consult the online\n<a href=\"http://izs.me/v8-docs/main.html\">v8 reference</a> for help with the various v8\ncalls, and v8&apos;s <a href=\"http://code.google.com/apis/v8/embed.html\">Embedder&apos;s Guide</a>\nfor an explanation of several concepts used such as handles, scopes,\nfunction templates, etc.\n\n</p>\n<p>下面是一些帮助你开始编写addon插件的方式。参考这个在线的<a href=\"http://izs.me/v8-docs/main.html\">v8 手册</a>用来帮助你调用各种v8接口， 然后是v8的 <a href=\"http://code.google.com/apis/v8/embed.html\">嵌入式开发向导</a> ，解释几个概念，如 handles, scopes,function templates等。\n\n\n</p>\n<p>In order to use these examples you need to compile them using <code>node-gyp</code>.\nCreate the following <code>binding.gyp</code> file:\n\n</p>\n<p>为了能跑起来这些例子，你必须用 <code>node-gyp</code> 来编译他们。\n创建一个<code>binding.gyp</code> 文件：\n\n</p>\n<pre><code>{\n  &quot;targets&quot;: [\n    {\n      &quot;target_name&quot;: &quot;addon&quot;,\n      &quot;sources&quot;: [ &quot;addon.cc&quot; ]\n    }\n  ]\n}</code></pre>\n<p>In cases where there is more than one <code>.cc</code> file, simply add the file name to\nthe <code>sources</code> array, e.g.:\n\n</p>\n<p>事实上可以有多个  <code>.cc</code> 文件, 就简单的在 <code>sources</code>  数组里加上即可，例子：\n\n</p>\n<pre><code>&quot;sources&quot;: [&quot;addon.cc&quot;, &quot;myexample.cc&quot;]</code></pre>\n<p>Now that you have your <code>binding.gyp</code> ready, you can configure and build the\naddon:\n\n</p>\n<p>现在你有了你的<code>binding.gyp</code>文件了，你可要开始执行configure 和 build 命令构建你的addon插件了\n\n</p>\n<pre><code>$ node-gyp configure build</code></pre>\n",
          "modules": [
            {
              "textRaw": "Function arguments（函数参数）",
              "name": "function_arguments（函数参数）",
              "desc": "<p>The following pattern illustrates how to read arguments from JavaScript\nfunction calls and return a result. This is the main and only needed source\n<code>addon.cc</code>:\n\n</p>\n<p>下面的部分说明了如何从JavaScript的函数调用获得参数然后返回一个值。这是主要的内容并且仅需要源代码<code>addon.cc</code>。\n\n</p>\n<pre><code>NODE_MODULE(addon, Init)</code></pre>\n<p>You can test it with the following JavaScript snippet:\n\n</p>\n<p>你可以使用下面的JavaScript代码片段来测试它\n\n</p>\n<pre><code>console.log( &apos;This should be eight:&apos;, addon.add(3,5) );</code></pre>\n",
              "type": "module",
              "displayName": "Function arguments（函数参数）"
            },
            {
              "textRaw": "Callbacks（回调）",
              "name": "callbacks（回调）",
              "desc": "<p>You can pass JavaScript functions to a C++ function and execute them from\nthere. Here&apos;s <code>addon.cc</code>:\n\n</p>\n<p>你可以传递JavaScript functions 到一个C++ function 并且执行他们，这里是 <code>addon.cc</code>文件:\n\n</p>\n<pre><code>NODE_MODULE(addon, Init)</code></pre>\n<p>Note that this example uses a two-argument form of <code>Init()</code> that receives\nthe full <code>module</code> object as the second argument. This allows the addon\nto completely overwrite <code>exports</code> with a single function instead of\nadding the function as a property of <code>exports</code>.\n\n</p>\n<p>注意这个例子对<code>Init()</code>使用了两个参数，将完整的 <code>module</code> 对象作为第二个参数传入。这允许addon插件完全的重写 <code>exports</code>，这样就可以用一个函数代替多个函数作为<code>exports</code>的属性了。\n\n</p>\n<p>To test it run the following JavaScript snippet:\n\n</p>\n<p>你可以使用下面的JavaScript代码片段来测试它\n\n</p>\n<pre><code>addon(function(msg){\n  console.log(msg); // &apos;hello world&apos;\n});</code></pre>\n",
              "type": "module",
              "displayName": "Callbacks（回调）"
            },
            {
              "textRaw": "Object factory（对象工厂）",
              "name": "object_factory（对象工厂）",
              "desc": "<p>You can create and return new objects from within a C++ function with this\n<code>addon.cc</code> pattern, which returns an object with property <code>msg</code> that echoes\nthe string passed to <code>createObject()</code>:\n\n</p>\n<p>在这个<code>addon.cc</code>文件里用一个c++函数，你可以创建并且返回一个新的对象，这个新的对象拥有一个msg的属性，它的值是通过createObject()方法传入的\n\n</p>\n<pre><code>NODE_MODULE(addon, Init)</code></pre>\n<p>To test it in JavaScript:\n\n</p>\n<p>在js中测试如下:\n\n</p>\n<pre><code>var obj1 = addon(&apos;hello&apos;);\nvar obj2 = addon(&apos;world&apos;);\nconsole.log(obj1.msg+&apos; &apos;+obj2.msg); // &apos;hello world&apos;</code></pre>\n",
              "type": "module",
              "displayName": "Object factory（对象工厂）"
            },
            {
              "textRaw": "Function factory（函数工厂）",
              "name": "function_factory（函数工厂）",
              "desc": "<p>This pattern illustrates how to create and return a JavaScript function that\nwraps a C++ function:\n\n</p>\n<p>这次将展示如何创建并返回一个JavaScript function函数，这个函数其实是通过c++包装的。\n\n</p>\n<pre><code>NODE_MODULE(addon, Init)</code></pre>\n<p>To test:\n\n</p>\n<p>测试它:\n\n</p>\n<pre><code>var fn = addon();\nconsole.log(fn()); // &apos;hello world&apos;</code></pre>\n",
              "type": "module",
              "displayName": "Function factory（函数工厂）"
            },
            {
              "textRaw": "Wrapping C++ objects（包装c++对象）",
              "name": "wrapping_c++_objects（包装c++对象）",
              "desc": "<p>Here we will create a wrapper for a C++ object/class <code>MyObject</code> that can be\ninstantiated in JavaScript through the <code>new</code> operator. First prepare the main\nmodule <code>addon.cc</code>:\n\n</p>\n<p>这里将创建一个被c++包裹的对象或类<code>MyObject</code>，它是可以在JavaScript中通过<code>new</code>操作符实例化的。\n首先我们要准备主要的模块文件<code>addon.cc</code>:\n\n</p>\n<pre><code>NODE_MODULE(addon, InitAll)</code></pre>\n<p>Then in <code>myobject.h</code> make your wrapper inherit from <code>node::ObjectWrap</code>:\n\n</p>\n<p>然后在<code>myobject.h</code>文件中创建你的包装类，它继承自 <code>node::ObjectWrap</code>:\n\n</p>\n<pre><code>#endif</code></pre>\n<p>And in <code>myobject.cc</code> implement the various methods that you want to expose.\nHere we expose the method <code>plusOne</code> by adding it to the constructor&apos;s\nprototype:\n\n</p>\n<p>在文件 <code>myobject.cc</code> 可以实施各种你想要暴露给js的方法。 \n这里我们暴露方法名为 <code>plusOne</code>给就是，它表示将构造函数的属性加1.\n\n</p>\n<pre><code>  return scope.Close(Number::New(obj-&gt;counter_));\n}</code></pre>\n<p>Test it with:\n\n</p>\n<p>测试它:\n\n</p>\n<pre><code>var obj = new addon.MyObject(10);\nconsole.log( obj.plusOne() ); // 11\nconsole.log( obj.plusOne() ); // 12\nconsole.log( obj.plusOne() ); // 13</code></pre>\n",
              "type": "module",
              "displayName": "Wrapping C++ objects（包装c++对象）"
            },
            {
              "textRaw": "Factory of wrapped objects（工厂包装对象）",
              "name": "factory_of_wrapped_objects（工厂包装对象）",
              "desc": "<p>This is useful when you want to be able to create native objects without\nexplicitly instantiating them with the <code>new</code> operator in JavaScript, e.g.\n\n</p>\n<p>这是非常有用的，当你想创建原生的JavaScript对象时，又不想明确的使用JavaScript的<code>new</code>操作符。\n\n</p>\n<pre><code>var obj = addon.createObject();\n// 用上面的方式代替下面的:\n// var obj = new addon.Object();</code></pre>\n<p>Let&apos;s register our <code>createObject</code> method in <code>addon.cc</code>:\n\n</p>\n<p>让我们注册在 <code>addon.cc</code> 文件中注册<code>createObject</code>方法:\n\n</p>\n<pre><code>NODE_MODULE(addon, InitAll)</code></pre>\n<p>In <code>myobject.h</code> we now introduce the static method <code>NewInstance</code> that takes\ncare of instantiating the object (i.e. it does the job of <code>new</code> in JavaScript):\n\n</p>\n<p>在<code>myobject.h</code>文件中，我们现在介绍静态方法NewInstance<code>，它能够实例化对象（举个例子，它的工作就像是 在JavaScript中的</code>new` 操作符。）\n\n</p>\n<pre><code>#endif</code></pre>\n<p>The implementation is similar to the above in <code>myobject.cc</code>:\n\n</p>\n<p>这里的处理方式和上面的 <code>myobject.cc</code>很像:\n\n</p>\n<pre><code>  return scope.Close(Number::New(obj-&gt;counter_));\n}</code></pre>\n<p>Test it with:\n\n</p>\n<p>测试它:\n\n</p>\n<pre><code>var obj2 = createObject(20);\nconsole.log( obj2.plusOne() ); // 21\nconsole.log( obj2.plusOne() ); // 22\nconsole.log( obj2.plusOne() ); // 23</code></pre>\n",
              "type": "module",
              "displayName": "Factory of wrapped objects（工厂包装对象）"
            },
            {
              "textRaw": "Passing wrapped objects around（传递包装的对象）",
              "name": "passing_wrapped_objects_around（传递包装的对象）",
              "desc": "<p>In addition to wrapping and returning C++ objects, you can pass them around\nby unwrapping them with Node&apos;s <code>node::ObjectWrap::Unwrap</code> helper function.\nIn the following <code>addon.cc</code> we introduce a function <code>add()</code> that can take on two\n<code>MyObject</code> objects:\n\n</p>\n<p>除了包装和返回c++对象以外，你可以传递他们并且通过Node的<code>node::ObjectWrap::Unwrap</code>帮助函数解包装他们。\n在下面的<code>addon.cc</code> 文件中，我们介绍了一个函数<code>add()</code>，它能够获取2个<code>MyObject</code>对象。\n\n</p>\n<pre><code>NODE_MODULE(addon, InitAll)</code></pre>\n<p>To make things interesting we introduce a public method in <code>myobject.h</code> so we\ncan probe private values after unwrapping the object:\n\n</p>\n<p>为了使事情变得有趣，我们在 <code>myobject.h</code> 采用一个公共的方法，所以我们能够在unwrapping解包装对象之后使用私有成员的值。\n\n</p>\n<pre><code>#endif</code></pre>\n<p>The implementation of <code>myobject.cc</code> is similar as before:\n\n</p>\n<p><code>myobject.cc</code>文件的处理方式和前面类似\n\n</p>\n<pre><code>  return scope.Close(instance);\n}</code></pre>\n<p>Test it with:\n\n</p>\n<p>测试它:\n\n</p>\n<pre><code>var obj1 = addon.createObject(10);\nvar obj2 = addon.createObject(20);\nvar result = addon.add(obj1, obj2);\n\nconsole.log(result); // 30\n\n\nconsole.log(result); // 30</code></pre>\n",
              "type": "module",
              "displayName": "Passing wrapped objects around（传递包装的对象）"
            }
          ],
          "type": "module",
          "displayName": "Addon patterns（插件方式）"
        }
      ],
      "type": "module",
      "displayName": "Addons插件"
    }
  ]
}