{"id":2717,"date":"2016-10-16T16:46:00","date_gmt":"2016-10-16T14:46:00","guid":{"rendered":"https:\/\/blog.risingstack.com\/?p=2717"},"modified":"2024-07-04T10:11:20","modified_gmt":"2024-07-04T08:11:20","slug":"using-buffers-node-js-c-plus-plus","status":"publish","type":"post","link":"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/","title":{"rendered":"Using Buffers to share data between Node.js and C++"},"content":{"rendered":"\n<\/p>\n\n\n\n<p>One of the best things about developing with <span class=\"glossary-tooltip glossary-term-2994\" tabindex=\"0\"><span class=\"glossary-link\"><a href=\"https:\/\/blog.risingstack.com\/glossary\/node-js\/\" target=\"_blank\" class=\"glossary-only-link\">Node.js<\/a><\/span><span class=\"hidden glossary-tooltip-content clearfix\"><span class=\"glossary-tooltip-text\">Node.js is an asynchronous event-driven JavaScript runtime and is the most effective when building scalable network applications. Node.js is free of locks, so there's no chance to dead-lock any process.<\/span><\/span><\/span> is the ability to move fairly seamlessly between JavaScript and native C++ code &#8211; thanks to the V8&#8217;s add-on API. The ability to move into C++ is sometimes driven by processing speed, but more often because we already have C++ code and we just want to be able to use it from JavaScript.<\/p>\n\n\n\n<p>We can categorize the different use cases for add-ons along (at least) two axes &#8211; (1) amount of processing time we&#8217;ll spend in the C++ code, and (2) the amount of data flowing between C++ and JavaScript.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img fetchpriority=\"high\" decoding=\"async\" width=\"465\" height=\"367\" src=\"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/quadrant.png\" alt=\"quadrant\" class=\"wp-image-2718\" srcset=\"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/quadrant.png 465w, https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/quadrant-300x237.png 300w\" sizes=\"(max-width: 465px) 100vw, 465px\" \/><\/figure>\n\n\n\n<p>Most articles discussing C++ add-ons for Node.js are focusing on the differences between the left and right quadrants. If you are in the left quadrants (short processing time), your add-on can possibly be synchronous &#8211; meaning the C++ code that executes is running directly in the Node.js event loop when called.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Node.js allows us to move fairly seamlessly between JavaScript and native C++ code.<\/p><\/blockquote>\n\n\n\n<p>In this case, the add-on function is blocks and waits for the return value, meaning no other operations can be done in the meantime. In the right quadrants, you would almost certainly design the add-on using the asynchronous pattern. In an asynchronous add-on function, the calling JavaScript code returns immediately. The calling code passes a callback function to the add-on, and the add-on does its work in a separate worker thread. This avoids locking up the Node.js event loop, as the add-on function does not block.<\/p>\n\n\n\n<p>The difference between the top and bottom quadrants is often overlooked, however they can be just as important.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"v8vscmemoryanddata\">V8 vs. C++ memory and data<\/h1>\n\n\n\n<p>If you are new to writing native add-ons, one of the first things you must master is the differences between V8-owned data (which you&nbsp;<strong>can<\/strong>&nbsp;access from C++ add-ons) and normal C++ memory allocations.<\/p>\n\n\n\n<p>When we say &#8220;V8-owned&#8221;, we are referring to the storage cells that hold JavaScript data.<\/p>\n\n\n\n<p>These storage cells are accessible through V8&#8217;s C++ API, but they aren&#8217;t ordinary C++ variables since they can only be accessed in limited ways. While your add-on&nbsp;<em>could<\/em>&nbsp;restrict itself to ONLY using V8 data, it will more likely create it&#8217;s own variables too &#8211; in plain old C++. These could be stack or heap variables, and of course are completely independent of V8.<\/p>\n\n\n\n<p>In JavaScript, primitives (numbers, strings, booleans, etc.) are&nbsp;<em>immutable<\/em>, and a C++ add-on can not alter storage cells associated with primitive JavaScript variables. The primitive JavaScript variables can be reassigned to&nbsp;<em>new storage cells<\/em>&nbsp;created by C++ &#8211; but this means that changing data will always result in&nbsp;<em>new<\/em>&nbsp;memory allocation.<\/p>\n\n\n\n<p>In the upper quadrant (low data transfer), this really isn&#8217;t a big deal. If you are designing an add-on that doesn&#8217;t have a lot of data exchange, then the overhead of all the new memory allocation probably doesn&#8217;t mean much. As your add-ons move closer to the lower quadrant, the cost of allocation \/ copying will start to hurt you.<\/p>\n\n\n\n<p>For one, it costs you in terms of peak memory usage, and&nbsp;<strong>it also costs you in performance<\/strong>!<\/p>\n\n\n\n<p>The time cost of copying all this data between JavaScript (V8 storage cells) to C++ (and back) usually kills the performance benefits you might be getting from running C++ in the first place!For add-ons in the lower left quadrant (low processing, high data usage), the latency associated with data copying can push your add-on towards the right &#8211; forcing you to consider an asynchronous design.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"v8memoryandasynchronousaddons\">V8 memory and asynchronous add-ons<\/h1>\n\n\n\n<p>In asynchronous add-ons we execute the bulk of our C++ processing code in a worker thread. If you are unfamiliar with asynchronous callbacks, you might want to check out a few tutorials (like&nbsp;<a href=\"http:\/\/blog.scottfrees.com\/building-an-asynchronous-c-addon-for-node-js-using-nan\">here<\/a>&nbsp;and&nbsp;<a href=\"http:\/\/blog.scottfrees.com\/c-processing-from-node-js-part-4-asynchronous-addons\">here<\/a>).<\/p>\n\n\n\n<p>A central tenant of asynchronous add-ons is that&nbsp;<em>you can&#8217;t access V8 (JavaScript) memory outside the event-loop&#8217;s thread<\/em>. This leads us to our next problem. If we have lots of data, that data must be copied out of V8 memory and into your add-on&#8217;s native address space&nbsp;<em>from the event loop&#8217;s thread<\/em>, before the worker thread starts. Likewise, any data produced or modified by the worker thread must be copied back into V8 by code executing in the event loop (in the callback). If you are interested in creating high throughput Node.js applications, you should avoid spending lots of time in the event loop copying data!<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"720\" height=\"540\" src=\"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/copying.gif\" alt=\"copying\" class=\"wp-image-2719\"\/><\/figure>\n\n\n\n<p>Ideally, we&#8217;d prefer a way to do this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"720\" height=\"540\" src=\"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/inplace.gif\" alt=\"inplace\" class=\"wp-image-2720\"\/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"nodejsbufferstotherescue\">Node.js Buffers to the rescue<\/h1>\n\n\n\n<p>So, we have two somewhat related problems.<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>When working with synchronous add-ons, unless we aren&#8217;t changing\/producing data, it&#8217;s likely we&#8217;ll need to spend a lot of time moving our data between V8 storage cells and plain old C++ variables &#8211; which costs us.<\/li><li>When working with asynchronous add-ons, we ideally should spend as little time in the event loop as possible. This is why we still have a problem &#8211; since we&nbsp;<em>must<\/em>&nbsp;do our data copying in the event loop&#8217;s thread due to V8&#8217;s multi-threaded restrictions.<\/li><\/ol>\n\n\n\n<p>This is where an often overlooked feature of Node.js helps us with add-on development &#8211; the&nbsp;<code>Buffer<\/code>. Quoting the&nbsp;<a href=\"https:\/\/nodejs.org\/api\/buffer.html\">Node.js official documentation<\/a>,<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Instances of the Buffer class are similar to arrays of integers but correspond to fixed-sized, raw memory allocations outside the V8 heap.<\/p><\/blockquote>\n\n\n\n<p>This is exactly what we are looking for &#8211; because the data inside a Buffer is&nbsp;<em>not stored in a V8 storage cell<\/em>, it is not subjected to the multi-threading rules of V8. This means that we can interact with it&nbsp;<strong>in place<\/strong>&nbsp;from a C++ worker thread started by an asynchronous add-on.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"howbufferswork\">How Buffers work<\/h2>\n\n\n\n<p>Buffers store raw binary data, and they can be found in the Node.js API for reading files and other I\/O devices.<\/p>\n\n\n\n<p>Borrowing from some examples in the Node.js documentation, we can create initialized buffers of a specified size, buffers pre-set with a specified value, buffers from arrays of bytes, and buffers from strings.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ buffer with size 10 bytes\n<strong>const<\/strong> buf1 = Buffer.alloc(10);\n\n\/\/ buffer filled with 1's (10 bytes)\n<strong>const<\/strong> buf2 = Buffer.alloc(10, 1);\n\n\/\/buffer containing &#091;0x1, 0x2, 0x3]\n<strong>const<\/strong> buf3 = Buffer.from(&#091;1, 2, 3]); \n\n\/\/ buffer containing ASCII bytes &#091;0x74, 0x65, 0x73, 0x74].\n<strong>const<\/strong> buf4 = Buffer.from('test');\n\n\/\/ buffer containing bytes from a file\n<strong>const<\/strong> buf5 = fs.readFileSync(\"some file\");\n<\/code><\/pre>\n\n\n\n<p>Buffers can be turned back into traditional JavaScript data (strings) or written back out to files, databases, or other I\/O devices.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"howtoaccessbuffersinc\">How to access Buffers in C++<\/h2>\n\n\n\n<p>When building an add-on for Node.js, the best place to start is by making use of the NAN (Native Abstractions for Node.js) API rather than directly using the V8 API &#8211; which can be a moving target. There are many tutorials on the web for getting started with NAN add-ons &#8211; including&nbsp;<a href=\"https:\/\/github.com\/nodejs\/nan#example\">examples<\/a>&nbsp;in NAN&#8217;s code base itself. I&#8217;ve written a bit about it&nbsp;<a href=\"http:\/\/blog.scottfrees.com\/building-an-asynchronous-c-addon-for-node-js-using-nan\">here<\/a>, and it&#8217;s also covered in a lot of depth in my&nbsp;<a href=\"https:\/\/scottfrees.com\/ebooks\/nodecpp\/\">ebook<\/a>.<\/p>\n\n\n\n<p>First, let\u2019s see how an add-on can access a Buffer sent to it from JavaScript. We&#8217;ll start with a simple JS program that requires an add-on that we&#8217;ll create in a moment:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>'use strict';\n\/\/ Requiring the add-on that we'll build in a moment...\n<strong>const<\/strong> addon = <strong>require<\/strong>('.\/build\/Release\/buffer_example');\n\n\/\/ Allocates memory holding ASCII \"ABC\" outside of V8.\n<strong>const<\/strong> buffer = Buffer.from(\"ABC\");\n\n\/\/ synchronous, rotates each character by +13\naddon.rotate(buffer, buffer.length, 13);\n\n<strong>console<\/strong>.log(buffer.toString('ascii'));\n<\/code><\/pre>\n\n\n\n<p>The expected output is &#8220;NOP&#8221;, the ASCII rotation by 13 of &#8220;ABC&#8221;. Let&#8217;s take a look the add-on! It consists of three files (in the same directory, for simplicity):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ binding.gyp\n{\n  \"targets\": &#091;\n    {\n        \"target_name\": \"buffer_example\",\n        \"sources\": &#091; \"buffer_example.cpp\" ], \n        \"include_dirs\" : &#091;\"&lt;!(node -e \\\"require('nan')\\\")\"]\n    }\n  ]\n}\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/package.json\n{\n  \"name\": \"buffer_example\",\n  \"version\": \"0.0.1\",\n  \"private\": true,\n  \"gypfile\": true,\n  \"scripts\": {\n    \"start\": \"node index.js\"\n  },\n  \"dependencies\": {\n  \t\"nan\": \"*\"\n  }\n}\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ buffer_example.cpp\n#<strong>include<\/strong> &lt;nan.h&gt;\n<strong>using<\/strong> <strong>namespace<\/strong> Nan;\n<strong>using<\/strong> <strong>namespace<\/strong> v8;\n\nNAN_METHOD(rotate) {\n    <strong>char<\/strong>* buffer = (<strong>char<\/strong>*) node::Buffer::Data(info&#091;0]-&gt;ToObject());\n    <strong>unsigned<\/strong> <strong>int<\/strong> size = info&#091;1]-&gt;Uint32Value();\n    <strong>unsigned<\/strong> <strong>int<\/strong> rot = info&#091;2]-&gt;Uint32Value();\n   \n    <strong>for<\/strong>(<strong>unsigned<\/strong> <strong>int<\/strong> i = 0; i &lt; size; i++ ) {\n        buffer&#091;i] += rot;\n    }   \n}\n\nNAN_MODULE_INIT(Init) {\n   Nan::Set(target, New&lt;String&gt;(\"rotate\").ToLocalChecked(),\n        GetFunction(New&lt;FunctionTemplate&gt;(rotate)).ToLocalChecked());\n}\n\nNODE_MODULE(buffer_example, Init)\n<\/code><\/pre>\n\n\n\n<p>The most interesting file is&nbsp;<code>buffer_example.cpp<\/code>. Notice that we&#8217;ve used&nbsp;<code>node::Buffer<\/code>&#8216;s&nbsp;<code>Data<\/code>&nbsp;method to convert the first parameter sent to the add-on to a character array. This is now free for us to use in any way we see fit. In this case, we just perform an ASCII rotation of the text. Notice that there is no return value, the memory associated with the Buffer has been modified&nbsp;<strong>in place<\/strong>.<\/p>\n\n\n\n<p>We can build the add-on by just typing&nbsp;<code>npm install<\/code>. The&nbsp;<code>package.json<\/code>&nbsp;tells <span class=\"glossary-tooltip glossary-term-2996\" tabindex=\"0\"><span class=\"glossary-link\"><a href=\"https:\/\/blog.risingstack.com\/glossary\/npm\/\" target=\"_blank\" class=\"glossary-only-link\">npm<\/a><\/span><span class=\"hidden glossary-tooltip-content clearfix\"><span class=\"glossary-tooltip-text\">npm is a software registry that serves over 1.3 million packages. npm is used by open source developers from all around the world to share and borrow code, as well as many businesses. There are three components to npm: the website the Command Line Interface (CLI) the registry Use the website to discover and download packages, create user profiles, and...<\/span><\/span><\/span> to download NAN and build the add-on using the&nbsp;<code>binding.gyp<\/code>&nbsp;file. Running it will give us the &#8220;NOP&#8221; output we expect.<\/p>\n\n\n\n<p>We can also create&nbsp;<em>new<\/em>&nbsp;buffers while inside the add-on. Let&#8217;s modify the rotate function to increment the input, but return another buffer containing the string resulting from a decrement operation:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAN_METHOD(rotate) {\n    <strong>char<\/strong>* buffer = (<strong>char<\/strong>*) node::Buffer::Data(info&#091;0]-&gt;ToObject());\n    <strong>unsigned<\/strong> <strong>int<\/strong> size = info&#091;1]-&gt;Uint32Value();\n    <strong>unsigned<\/strong> <strong>int<\/strong> rot = info&#091;2]-&gt;Uint32Value();\n   \n    <strong>char<\/strong> * retval = <strong>new<\/strong> <strong>char<\/strong>&#091;size];\n    <strong>for<\/strong>(<strong>unsigned<\/strong> <strong>int<\/strong> i = 0; i &lt; size; i++ ) {\n        retval&#091;i] = buffer&#091;i] - rot;\n        buffer&#091;i] += rot;\n    }   \n    \n   info.GetReturnValue().Set(Nan::NewBuffer(retval, size).ToLocalChecked());\n}\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>var<\/strong> result = addon.rotate(buffer, buffer.length, 13);\n\n<strong>console<\/strong>.log(buffer.toString('ascii'));\n<strong>console<\/strong>.log(result.toString('ascii'));\n<\/code><\/pre>\n\n\n\n<p>Now the resulting buffer will contain &#8216;456&#8217;. Note the use of NAN&#8217;s&nbsp;<code>NewBuffer<\/code>&nbsp;function, which wraps the dynamically allocated&nbsp;<code>retval<\/code>&nbsp;array in a Node buffer. Doing so&nbsp;<em>transfers ownership<\/em>&nbsp;of this memory to Node.js, so the memory associated with&nbsp;<code>retval<\/code>&nbsp;will be reclaimed (by calling&nbsp;<code>free<\/code>) when the buffer goes out of scope in JavaScript. More on this issue later &#8211; as we don&#8217;t always want to have it happen this way!<\/p>\n\n\n\n<p>You can find additional information about how NAN handles buffers&nbsp;<a href=\"https:\/\/github.com\/nodejs\/nan\/blob\/master\/doc\/buffers.md\">here<\/a>.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"examplepngandbmpimageprocessing\">Example: PNG and BMP Image Processing<\/h1>\n\n\n\n<p>The example above is pretty basic and not particularly exciting. Let&#8217;s turn to a more practical example &#8211; image processing with C++. If you want to get the full source code for both the example above and the image processing code below, you can head over to my&nbsp;<code>nodecpp-demo<\/code>&nbsp;repository at&nbsp;<a href=\"https:\/\/github.com\/freezer333\/nodecpp-demo\">https:\/\/github.com\/freezer333\/nodecpp-demo<\/a>, the code is in the &#8220;buffers&#8221; directory.<\/p>\n\n\n\n<p>Image processing is a good candidate for C++ add-ons, as it can often be time-consuming, CPU intensive, and some processing techniques have parallelism that C++ can exploit well. In the example we&#8217;ll look at now, we&#8217;ll simply convert png formatted data into bmp formatted data .<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Converting a png to bmp is&nbsp;<em>not<\/em>&nbsp;particularly time consuming and it&#8217;s probably overkill for an add-on, but it&#8217;s good for demonstration purposes. If you are looking for a pure JavaScript implementation of image processing (including much more than png to bmp conversion), take a look at JIMP at&nbsp;<a href=\"https:\/\/community.risingstack.com\/using-buffers-node-js-c-plus-plus\/\">https:\/\/www.npmjs.com\/package\/jimp<\/a><a href=\"https:\/\/www.npmjs.com\/package\/jimp\">https:\/\/www.npmjs.com\/package\/jimp<\/a>.<\/p><\/blockquote>\n\n\n\n<p>There are a good number of open source C++ libraries that can help us with this task. I&#8217;m going to use LodePNG as it is dependency free and quite simple to use. LodePNG can be found at&nbsp;<a href=\"http:\/\/lodev.org\/lodepng\/\">http:\/\/lodev.org\/lodepng\/<\/a>, and it&#8217;s source code is at&nbsp;<a href=\"https:\/\/github.com\/lvandeve\/lodepng\">https:\/\/github.com\/lvandeve\/lodepng<\/a>. Many thanks to the developer, Lode Vandevenne for providing such an easy to use library!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"settinguptheaddon\">Setting up the add-on<\/h2>\n\n\n\n<p>For this add-on, we&#8217;ll create the following directory structure, which includes source code downloaded from&nbsp;<a href=\"https:\/\/github.com\/lvandeve\/lodepng\">https:\/\/github.com\/lvandeve\/lodepng<\/a>, namely&nbsp;<code>lodepng.h<\/code>&nbsp;and&nbsp;<code>lodepng.cpp<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/png2bmp\n | \n |--- binding.gyp\n |--- package.json\n |--- png2bmp.cpp  # the add-on\n |--- index.js     # program to test the add-on\n |--- sample.png   # input (will be converted to bmp)\n |--- lodepng.h    # from lodepng distribution\n |--- lodepng.cpp  # From loadpng distribution\n<\/code><\/pre>\n\n\n\n<p><code>lodepng.cpp<\/code>&nbsp;contains all the necessary code for doing image processing, and I will not discuss it&#8217;s working in detail. In addition, the lodepng distribution contains sample code that allows you to specifically convert between png and bmp. I&#8217;ve adapted it slightly and will put it in the add-ons source code file&nbsp;<code>png2bmp.cpp<\/code>&nbsp;which we will take a look at shortly.<\/p>\n\n\n\n<p>Let&#8217;s look at what the actual JavaScript program looks like before diving into the add-on code itself:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>'use strict';\n<strong>const<\/strong> fs = <strong>require<\/strong>('fs');\n<strong>const<\/strong> path = <strong>require<\/strong>('path');\n<strong>const<\/strong> png2bmp = <strong>require<\/strong>('.\/build\/Release\/png2bmp');\n\n<strong>const<\/strong> png_file = process.argv&#091;2];\n<strong>const<\/strong> bmp_file = path.basename(png_file, '.png') + \".bmp\";\n<strong>const<\/strong> png_buffer = fs.readFileSync(png_file);\n\n<strong>const<\/strong> bmp_buffer = png2bmp.getBMP(png_buffer, png_buffer.length);\nfs.writeFileSync(bmp_file, bmp_buffer);\n<\/code><\/pre>\n\n\n\n<p>The program uses a filename for a png image as a command line option. It calls an add-on function&nbsp;<code>getBMP<\/code>&nbsp;which accepts a buffer containing the png file and its length. This add-on is&nbsp;<em>synchronous<\/em>, but we&#8217;ll take a look at the asynchronous version later on too.<\/p>\n\n\n\n<p>Here&#8217;s the&nbsp;<code>package.json<\/code>, which is setting up&nbsp;<code>npm start<\/code>&nbsp;to invoke the&nbsp;<code>index.js<\/code>&nbsp;program with a command line argument of&nbsp;<code>sample.png<\/code>. It&#8217;s a pretty generic image:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"name\": \"png2bmp\",\n  \"version\": \"0.0.1\",\n  \"private\": true,\n  \"gypfile\": true,\n  \"scripts\": {\n    \"start\": \"node index.js sample.png\"\n  },\n  \"dependencies\": {\n  \t\"nan\": \"*\"\n  }\n}\n<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"600\" src=\"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/sample.png\" alt=\"sample\" class=\"wp-image-2721\" srcset=\"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/sample.png 600w, https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/sample-300x300.png 300w, https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/sample-150x150.png 150w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/figure>\n\n\n\n<p>Here is the&nbsp;<code>binding.gyp<\/code>&nbsp;file &#8211; which is fairly standard, other than a few compiler flags needed to compile lodepng. It also includes the requisite references to NAN.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"targets\": &#091;\n    {\n      \"target_name\": \"png2bmp\",\n      \"sources\": &#091; \"png2bmp.cpp\", \"lodepng.cpp\" ], \n      \"cflags\": &#091;\"-Wall\", \"-Wextra\", \"-pedantic\", \"-ansi\", \"-O3\"],\n      \"include_dirs\" : &#091;\"&lt;!(node -e \\\"require('nan')\\\")\"]\n    }\n  ]\n}\n<\/code><\/pre>\n\n\n\n<p><code>png2bmp.cpp<\/code>&nbsp;will mostly contain V8\/NAN code. However, it does have one image processing utility function &#8211;&nbsp;<code>do_convert<\/code>, adopted from lodepng&#8217;s png to bmp example code.<\/p>\n\n\n\n<p>The function accepts a&nbsp;<code>vector&lt;unsigned char&gt;<\/code>&nbsp;containing input data (png format) and a&nbsp;<code>vector&lt;unsigned char&gt;<\/code>&nbsp;to put its output (bmp format) data into. That function, in turn, calls&nbsp;<code>encodeBMP<\/code>, which is straight from the lodepng examples.<\/p>\n\n\n\n<p>Here is the full code listing of these two functions. The details are not important to the understanding of the add-ons&nbsp;<code>Buffer<\/code>&nbsp;objects but are included here for completeness. Our add-on entry point(s) will call&nbsp;<code>do_convert<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>~~~~~~~~~~{#binding-hello .cpp}\n\/*\nALL LodePNG code in this file is adapted from lodepng's \nexamples, found at the following URL:\n<a href=\"https:\/\/github.com\/lvandeve\/lodepng\/blob\/\">https:\/\/github.com\/lvandeve\/lodepng\/blob\/<\/a>\nmaster\/examples\/example_bmp2png.cpp'\n*\/\n\n<strong>void<\/strong> <strong>encodeBMP<\/strong>(<strong>std<\/strong>::<strong>vector<\/strong>&lt;<strong>unsigned<\/strong> <strong>char<\/strong>&gt;&amp; bmp, \n  <strong>const<\/strong> <strong>unsigned<\/strong> <strong>char<\/strong>* image, <strong>int<\/strong> w, <strong>int<\/strong> h)\n{\n  \/\/3 bytes per pixel used for both input and output.\n  <strong>int<\/strong> inputChannels = 3;\n  <strong>int<\/strong> outputChannels = 3;\n  \n  \/\/bytes 0-13\n  bmp.push_back('B'); bmp.push_back('M'); \/\/0: bfType\n  bmp.push_back(0); bmp.push_back(0); \n  bmp.push_back(0); bmp.push_back(0); \n  bmp.push_back(0); bmp.push_back(0); \/\/6: bfReserved1\n  bmp.push_back(0); bmp.push_back(0); \/\/8: bfReserved2\n  bmp.push_back(54 % 256); \n  bmp.push_back(54 \/ 256); \n  bmp.push_back(0); bmp.push_back(0); \n\n  \/\/bytes 14-53\n  bmp.push_back(40); bmp.push_back(0); \n  bmp.push_back(0); bmp.push_back(0);  \/\/14: biSize\n  bmp.push_back(w % 256); \n  bmp.push_back(w \/ 256); \n  bmp.push_back(0); bmp.push_back(0); \/\/18: biWidth\n  bmp.push_back(h % 256); \n  bmp.push_back(h \/ 256); \n  bmp.push_back(0); bmp.push_back(0); \/\/22: biHeight\n  bmp.push_back(1); bmp.push_back(0); \/\/26: biPlanes\n  bmp.push_back(outputChannels * 8); \n  bmp.push_back(0); \/\/28: biBitCount\n  bmp.push_back(0); bmp.push_back(0); \n  bmp.push_back(0); bmp.push_back(0);  \/\/30: biCompression\n  bmp.push_back(0); bmp.push_back(0); \n  bmp.push_back(0); bmp.push_back(0);  \/\/34: biSizeImage\n  bmp.push_back(0); bmp.push_back(0); \n  bmp.push_back(0); bmp.push_back(0);  \/\/38: biXPelsPerMeter\n  bmp.push_back(0); bmp.push_back(0); \n  bmp.push_back(0); bmp.push_back(0);  \/\/42: biYPelsPerMeter\n  bmp.push_back(0); bmp.push_back(0); \n  bmp.push_back(0); bmp.push_back(0);  \/\/46: biClrUsed\n  bmp.push_back(0); bmp.push_back(0); \n  bmp.push_back(0); bmp.push_back(0);  \/\/50: biClrImportant\n \n  <strong>int<\/strong> imagerowbytes = outputChannels * w;\n  \/\/must be multiple of 4\n  imagerowbytes = imagerowbytes % 4 == 0 ? imagerowbytes : \n            imagerowbytes + (4 - imagerowbytes % 4); \n  \n  <strong>for<\/strong>(<strong>int<\/strong> y = h - 1; y &gt;= 0; y--) \n  {\n    <strong>int<\/strong> c = 0;\n    <strong>for<\/strong>(<strong>int<\/strong> x = 0; x &lt; imagerowbytes; x++)\n    {\n      <strong>if<\/strong>(x &lt; w * outputChannels)\n      {\n        <strong>int<\/strong> inc = c;\n        \/\/Convert RGB(A) into BGR(A)\n        <strong>if<\/strong>(c == 0) inc = 2;\n        <strong>else<\/strong> <strong>if<\/strong>(c == 2) inc = 0;\n        bmp.push_back(image&#091;inputChannels \n            * (w * y + x \/ outputChannels) + inc]);\n      }\n      <strong>else<\/strong> bmp.push_back(0);\n      c++;\n      <strong>if<\/strong>(c &gt;= outputChannels) c = 0;\n    }\n  }\n\n  \/\/ Fill in the size\n  bmp&#091;2] = bmp.size() % 256;\n  bmp&#091;3] = (bmp.size() \/ 256) % 256;\n  bmp&#091;4] = (bmp.size() \/ 65536) % 256;\n  bmp&#091;5] = bmp.size() \/ 16777216;\n}\n\n<strong>bool<\/strong> <strong>do_convert<\/strong>(\n  <strong>std<\/strong>::<strong>vector<\/strong>&lt;<strong>unsigned<\/strong> <strong>char<\/strong>&gt; &amp; input_data, \n  <strong>std<\/strong>::<strong>vector<\/strong>&lt;<strong>unsigned<\/strong> <strong>char<\/strong>&gt; &amp; bmp)\n{\n  <strong>std<\/strong>::<strong>vector<\/strong>&lt;<strong>unsigned<\/strong> <strong>char<\/strong>&gt; image; \/\/the raw pixels\n  <strong>unsigned<\/strong> width, height;\n  <strong>unsigned<\/strong> error = lodepng::decode(image, width, \n    height, input_data, LCT_RGB, 8);\n  <strong>if<\/strong>(error) {\n    <strong>std<\/strong>::<strong>cout<\/strong> &lt;&lt; \"error \" &lt;&lt; error &lt;&lt; \": \" \n              &lt;&lt; lodepng_error_text(error) \n              &lt;&lt; <strong>std<\/strong>::endl;\n    <strong>return<\/strong> false;\n  }\n  encodeBMP(bmp, &amp;image&#091;0], width, height);\n  <strong>return<\/strong> true;\n}\n~~~~~~~~~~\n<\/code><\/pre>\n\n\n\n<p>Sorry&#8230; that listing was long, but it&#8217;s important to see what&#8217;s actually going on! Let&#8217;s get to work bridging all this code to JavaScript.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"synchronousbufferprocessing\">Synchronous Buffer Processing<\/h2>\n\n\n\n<p>The png image data is actually read when we are in JavaScript, so it&#8217;s passed in as a Node.js&nbsp;<code>Buffer<\/code>. We&#8217;ll use NAN to access the buffer itself. Here&#8217;s the complete code for the synchronous version:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAN_METHOD(GetBMP) {\n<strong>unsigned<\/strong> <strong>char<\/strong>*buffer = (<strong>unsigned<\/strong> <strong>char<\/strong>*) node::Buffer::Data(info&#091;0]-&gt;ToObject());\n    <strong>unsigned<\/strong> <strong>int<\/strong> size = info&#091;1]-&gt;Uint32Value();\n   \n    <strong>std<\/strong>::<strong>vector<\/strong>&lt;<strong>unsigned<\/strong> <strong>char<\/strong>&gt; png_data(buffer, buffer + size);\n    <strong>std<\/strong>::<strong>vector<\/strong>&lt;<strong>unsigned<\/strong> <strong>char<\/strong>&gt; bmp;\n     \n    <strong>if<\/strong> ( do_convert(png_data, bmp)) {\n        info.GetReturnValue().Set(\n            NewBuffer((<strong>char<\/strong> *)bmp.data(), bmp.size()\/*, buffer_delete_callback, bmp*\/).ToLocalChecked());\n    }\n}  \n\nNAN_MODULE_INIT(Init) {\n   Nan::Set(target, New&lt;String&gt;(\"getBMP\").ToLocalChecked(),\n        GetFunction(New&lt;FunctionTemplate&gt;(GetBMP)).ToLocalChecked());\n}\n\nNODE_MODULE(png2bmp, Init)\n<\/code><\/pre>\n\n\n\n<p>In&nbsp;<code>GetBMP<\/code>, we use the familiar&nbsp;<code>Data<\/code>&nbsp;method to unwrap the buffer so we can work with it like a normal character array. Next, we build a&nbsp;<code>vector<\/code>&nbsp;around the input so we can pass it to our&nbsp;<code>do_convert<\/code>&nbsp;function listed above. Once the&nbsp;<code>bmp<\/code>&nbsp;vector is filled in by&nbsp;<code>do_convert<\/code>, we wrap it up in a&nbsp;<code>Buffer<\/code>&nbsp;and return to JavaScript.<\/p>\n\n\n\n<p>So&nbsp;<em>here is the problem<\/em>&nbsp;with this code: The data contained in the buffer we return is likely deleted before our JavaScript gets to use it. Why? Because the&nbsp;<code>bmp<\/code>&nbsp;vector is going to go out of scope as our&nbsp;<code>GetBMP<\/code>&nbsp;function returns. C++ vector semantics hold that when the vector goes out of scope, the vector&#8217;s destructor deletes all data within the vector &#8211; in our case, our bmp data will be deleted as well! This is a huge problem since the&nbsp;<code>Buffer<\/code>&nbsp;we send back to JavaScript will have it&#8217;s data deleted out from under it. You might get away with this (race conditions are fun right?), but it will eventually cause your program to crash.<\/p>\n\n\n\n<p>Luckily,&nbsp;<code>NewBuffer<\/code>&nbsp;has an optional third and fourth parameter to give us some more control.<\/p>\n\n\n\n<p>The third parameter is a callback which ends up being called when the&nbsp;<code>Buffer<\/code>&nbsp;gets garbage collected by V8. Remember that&nbsp;<code>Buffer<\/code>s are JavaScript objects, whose data is stored outside of V8, but the object itself is under V8&#8217;s control.<\/p>\n\n\n\n<p>From this perspective, it should make sense that a callback would be handy. When V8 destroys the buffer, we need some way of freeing up the data we have created &#8211; which is passed into the callback as its first parameter. The signature of the callback is defined by NAN &#8211;&nbsp;<code>Nan::FreeCallback()<\/code>. The fourth parameter is a hint to aid in deallocation, and we can use it however we want.<\/p>\n\n\n\n<p>Since our problem is that the vector containing bitmap data goes out of scope, we can&nbsp;<em>dynamically<\/em>&nbsp;allocate the vector itself instead, and pass it into the free callback where it can be properly deleted when the&nbsp;<code>Buffer<\/code>&nbsp;has been garbage collected.<\/p>\n\n\n\n<p>Below is the new&nbsp;<code>delete_callback<\/code>, along with the new call to&nbsp;<code>NewBuffer<\/code>. I&#8217;m sending the actual pointer to the vector as the hint, so it can be deleted directly.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>void<\/strong> <strong>buffer_delete_callback<\/strong>(<strong>char<\/strong>* data, <strong>void<\/strong>* the_vector) {\n  <strong>delete<\/strong> <strong>reinterpret_cast<\/strong>&lt;<strong>vector<\/strong>&lt;<strong>unsigned<\/strong> <strong>char<\/strong>&gt; *&gt; (the_vector);\n}\n\nNAN_METHOD(GetBMP) {\n    \n  <strong>unsigned<\/strong> <strong>char<\/strong>*buffer =  (<strong>unsigned<\/strong> <strong>char<\/strong>*) node::Buffer::Data(info&#091;0]-&gt;ToObject());\n  <strong>unsigned<\/strong> <strong>int<\/strong> size = info&#091;1]-&gt;Uint32Value();\n   \n  <strong>std<\/strong>::<strong>vector<\/strong>&lt;<strong>unsigned<\/strong> <strong>char<\/strong>&gt; png_data(buffer, buffer + size); \n  <strong>std<\/strong>::<strong>vector<\/strong>&lt;<strong>unsigned<\/strong> <strong>char<\/strong>&gt; * bmp = <strong>new<\/strong> <strong>vector<\/strong>&lt;<strong>unsigned<\/strong> <strong>char<\/strong>&gt;();\n     \n  <strong>if<\/strong> ( do_convert(png_data, *bmp)) {\n      info.GetReturnValue().Set(\n          NewBuffer(\n            (<strong>char<\/strong> *)bmp-&gt;data(), \n            bmp-&gt;size(), \n            buffer_delete_callback, \n            bmp)\n            .ToLocalChecked());\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>Run this program by doing an&nbsp;<code>npm install<\/code>&nbsp;and then an&nbsp;<code>npm start<\/code>&nbsp;and you&#8217;ll see a&nbsp;<code>sample.bmp<\/code>&nbsp;generated in your directory that looks eerily similar to&nbsp;<code>sample.png<\/code>&nbsp;&#8211; just a whole lot bigger (because bmp compression is far less efficient than png).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"asynchronousbufferprocessing\">Asynchronous Buffer Processing<\/h2>\n\n\n\n<p>Let&#8217;s develop an asynchronous version of the png to bitmap converter. We&#8217;ll perform the actual conversion in a C++ worker thread, using&nbsp;<code>Nan::AsyncWorker<\/code>. By using&nbsp;<code>Buffer<\/code>&nbsp;objects, we can avoid copying the png data, so we will only need to hold a pointer to the underlying data such that our worker thread can access it. Likewise, the data produced by the worker thread (the&nbsp;<code>bmp<\/code>&nbsp;vector) can be used to create a new&nbsp;<code>Buffer<\/code>&nbsp;without copying data.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> <strong>class<\/strong> PngToBmpWorker : <strong>public<\/strong> AsyncWorker {\n    <strong>public<\/strong>:\n    PngToBmpWorker(Callback * callback, \n        v8::Local&lt;v8::Object&gt; &amp;pngBuffer, <strong>int<\/strong> size) \n        : AsyncWorker(callback) {\n        <strong>unsigned<\/strong> <strong>char<\/strong>*buffer = \n          (<strong>unsigned<\/strong> <strong>char<\/strong>*) node::Buffer::Data(pngBuffer);\n\n        <strong>std<\/strong>::<strong>vector<\/strong>&lt;<strong>unsigned<\/strong> <strong>char<\/strong>&gt; tmp(\n          buffer, \n          buffer +  (<strong>unsigned<\/strong> <strong>int<\/strong>) size);\n\n        png_data = tmp;\n    }\n    <strong>void<\/strong> <strong>Execute<\/strong>() {\n       bmp = <strong>new<\/strong> <strong>vector<\/strong>&lt;<strong>unsigned<\/strong> <strong>char<\/strong>&gt;();\n       do_convert(png_data, *bmp);\n    }\n    <strong>void<\/strong> <strong>HandleOKCallback<\/strong> () {\n        Local&lt;Object&gt; bmpData = \n               NewBuffer((<strong>char<\/strong> *)bmp-&gt;data(), \n               bmp-&gt;size(), buffer_delete_callback, \n               bmp).ToLocalChecked();\n        Local&lt;Value&gt; argv&#091;] = { bmpData };\n        callback-&gt;Call(1, argv);\n    }\n\n    <strong>private<\/strong>:\n        <strong>vector<\/strong>&lt;<strong>unsigned<\/strong> <strong>char<\/strong>&gt; png_data;\n        <strong>std<\/strong>::<strong>vector<\/strong>&lt;<strong>unsigned<\/strong> <strong>char<\/strong>&gt; * bmp;\n};\n\nNAN_METHOD(GetBMPAsync) {\n    <strong>int<\/strong> size = To&lt;<strong>int<\/strong>&gt;(info&#091;1]).FromJust();\n    v8::Local&lt;v8::Object&gt; pngBuffer = \n      info&#091;0]-&gt;ToObject();\n\n    Callback *callback = \n      <strong>new<\/strong> Callback(info&#091;2].As&lt;Function&gt;());\n\n    AsyncQueueWorker(\n      <strong>new<\/strong> PngToBmpWorker(callback, pngBuffer , size));\n}\n<\/code><\/pre>\n\n\n\n<p>Our new&nbsp;<code>GetBMPAsync<\/code>&nbsp;add-on function first unwraps the input buffer sent from JavaScript and then initializes and queues a new&nbsp;<code>PngToBmpWorker<\/code>&nbsp;worker , using NAN&#8217;s API. The worker object&#8217;s&nbsp;<code>Execute<\/code>&nbsp;method is called by&nbsp;<code>libuv<\/code>&nbsp;inside a worker thread where the conversion is done. When the&nbsp;<code>Execute<\/code>&nbsp;function returns,&nbsp;<code>libuv<\/code>&nbsp;calls the&nbsp;<code>HandleOKCallback<\/code>&nbsp;in the Node.js event loop thread, which creates the buffer and invokes the callback sent from JavaScript.<\/p>\n\n\n\n<p>Now we can utilize this add-on function in JavaScript like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>png2bmp.getBMPAsync(png_buffer, \n  png_buffer.length,\n  <strong>function<\/strong>(bmp_buffer) {\n    fs.writeFileSync(bmp_file, bmp_buffer);\n}); \n<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"summary\">Summary<\/h1>\n\n\n\n<p>There were two core takeaways in this post:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>You can&#8217;t ignore the costs of copying data between V8 storage cells and C++ variables. If you aren&#8217;t careful, you can easily kill the performance boost you might have thought you were getting by dropping into C++ to perform your work!<\/li><li>Buffers offer a way to work with the same data in both JavaScript and C++, thus avoiding the need to create copies.<\/li><\/ol>\n\n\n\n<p>Using buffers in your add-ons can be pretty painless. I hope I&#8217;ve been able to show you this through a simple demo application that rotates ASCII text, along with more practical synchronous and asynchronous image conversion examples Hopefully, this post helps you boost the performance of your own add-ons!<\/p>\n\n\n\n<p>A reminder, all the code from this post can be found at&nbsp;<a href=\"https:\/\/github.com\/freezer333\/nodecpp-demo\">https:\/\/github.com\/freezer333\/nodecpp-demo<\/a>, the code is in the &#8220;buffers&#8221; directory.<\/p>\n\n\n\n<p>If you are looking for more tips on how to design Node.js C++ add-ons, please check out my&nbsp;<a href=\"https:\/\/scottfrees.com\/ebooks\/nodecpp\/\">ebook on C++ and Node.js Integration<\/a>.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><strong>This article is written by Scott Frees. The author&#8217;s bio:<br><\/strong><em>&#8220;I&#8217;m a freelance software developer and consultant &#8211; specialized in custom application development, workflow automation and software integration. More info: https:\/\/scottfrees.com\/&#8221;<\/em><\/p><\/blockquote>\n\n\n\n<p>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[],"class_list":["post-2717","post","type-post","status-publish","format-standard","hentry","category-devops"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Using Buffers to share data between Node.js and C++ - RisingStack Engineering<\/title>\n<meta name=\"description\" content=\"Learn how you can share data between Node.js and C++ using Buffers - in order to work with the same data in both languages, in a performant way.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using Buffers to share data between Node.js and C++ - RisingStack Engineering\" \/>\n<meta property=\"og:description\" content=\"Learn how you can share data between Node.js and C++ using Buffers - in order to work with the same data in both languages, in a performant way.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/\" \/>\n<meta property=\"og:site_name\" content=\"RisingStack Engineering\" \/>\n<meta property=\"article:published_time\" content=\"2016-10-16T14:46:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-07-04T08:11:20+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/quadrant.png\" \/>\n<meta name=\"author\" content=\"RisingStack Engineering\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"RisingStack Engineering\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"17 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/using-buffers-node-js-c-plus-plus\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/using-buffers-node-js-c-plus-plus\\\/\"},\"author\":{\"name\":\"RisingStack Engineering\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#\\\/schema\\\/person\\\/7cd795f2e5173258661ba604144b0b22\"},\"headline\":\"Using Buffers to share data between Node.js and C++\",\"datePublished\":\"2016-10-16T14:46:00+00:00\",\"dateModified\":\"2024-07-04T08:11:20+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/using-buffers-node-js-c-plus-plus\\\/\"},\"wordCount\":2875,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/using-buffers-node-js-c-plus-plus\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blog.risingstack.com\\\/wp-content\\\/uploads\\\/2022\\\/03\\\/quadrant.png\",\"articleSection\":[\"DevOps\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/blog.risingstack.com\\\/using-buffers-node-js-c-plus-plus\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/using-buffers-node-js-c-plus-plus\\\/\",\"url\":\"https:\\\/\\\/blog.risingstack.com\\\/using-buffers-node-js-c-plus-plus\\\/\",\"name\":\"Using Buffers to share data between Node.js and C++ - RisingStack Engineering\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/using-buffers-node-js-c-plus-plus\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/using-buffers-node-js-c-plus-plus\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blog.risingstack.com\\\/wp-content\\\/uploads\\\/2022\\\/03\\\/quadrant.png\",\"datePublished\":\"2016-10-16T14:46:00+00:00\",\"dateModified\":\"2024-07-04T08:11:20+00:00\",\"description\":\"Learn how you can share data between Node.js and C++ using Buffers - in order to work with the same data in both languages, in a performant way.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/using-buffers-node-js-c-plus-plus\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blog.risingstack.com\\\/using-buffers-node-js-c-plus-plus\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/using-buffers-node-js-c-plus-plus\\\/#primaryimage\",\"url\":\"https:\\\/\\\/blog.risingstack.com\\\/wp-content\\\/uploads\\\/2022\\\/03\\\/quadrant.png\",\"contentUrl\":\"https:\\\/\\\/blog.risingstack.com\\\/wp-content\\\/uploads\\\/2022\\\/03\\\/quadrant.png\",\"width\":465,\"height\":367},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/using-buffers-node-js-c-plus-plus\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/blog.risingstack.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using Buffers to share data between Node.js and C++\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#website\",\"url\":\"https:\\\/\\\/blog.risingstack.com\\\/\",\"name\":\"RisingStack Engineering\",\"description\":\"Node.js Tutorials &amp; Resources\",\"publisher\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blog.risingstack.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#organization\",\"name\":\"RisingStack Engineering\",\"url\":\"https:\\\/\\\/blog.risingstack.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/blog.risingstack.com\\\/wp-content\\\/uploads\\\/2021\\\/05\\\/logo-white-f0fca36fce94ceacd3d608caa6649361-1.svg\",\"contentUrl\":\"https:\\\/\\\/blog.risingstack.com\\\/wp-content\\\/uploads\\\/2021\\\/05\\\/logo-white-f0fca36fce94ceacd3d608caa6649361-1.svg\",\"width\":180,\"height\":45,\"caption\":\"RisingStack Engineering\"},\"image\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#\\\/schema\\\/person\\\/7cd795f2e5173258661ba604144b0b22\",\"name\":\"RisingStack Engineering\",\"url\":\"https:\\\/\\\/blog.risingstack.com\\\/author\\\/coolsp\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Using Buffers to share data between Node.js and C++ - RisingStack Engineering","description":"Learn how you can share data between Node.js and C++ using Buffers - in order to work with the same data in both languages, in a performant way.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/","og_locale":"en_US","og_type":"article","og_title":"Using Buffers to share data between Node.js and C++ - RisingStack Engineering","og_description":"Learn how you can share data between Node.js and C++ using Buffers - in order to work with the same data in both languages, in a performant way.","og_url":"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/","og_site_name":"RisingStack Engineering","article_published_time":"2016-10-16T14:46:00+00:00","article_modified_time":"2024-07-04T08:11:20+00:00","og_image":[{"url":"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/quadrant.png","type":"","width":"","height":""}],"author":"RisingStack Engineering","twitter_card":"summary_large_image","twitter_misc":{"Written by":"RisingStack Engineering","Est. reading time":"17 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/#article","isPartOf":{"@id":"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/"},"author":{"name":"RisingStack Engineering","@id":"https:\/\/blog.risingstack.com\/#\/schema\/person\/7cd795f2e5173258661ba604144b0b22"},"headline":"Using Buffers to share data between Node.js and C++","datePublished":"2016-10-16T14:46:00+00:00","dateModified":"2024-07-04T08:11:20+00:00","mainEntityOfPage":{"@id":"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/"},"wordCount":2875,"commentCount":0,"publisher":{"@id":"https:\/\/blog.risingstack.com\/#organization"},"image":{"@id":"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/quadrant.png","articleSection":["DevOps"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/","url":"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/","name":"Using Buffers to share data between Node.js and C++ - RisingStack Engineering","isPartOf":{"@id":"https:\/\/blog.risingstack.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/#primaryimage"},"image":{"@id":"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/quadrant.png","datePublished":"2016-10-16T14:46:00+00:00","dateModified":"2024-07-04T08:11:20+00:00","description":"Learn how you can share data between Node.js and C++ using Buffers - in order to work with the same data in both languages, in a performant way.","breadcrumb":{"@id":"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/#primaryimage","url":"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/quadrant.png","contentUrl":"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2022\/03\/quadrant.png","width":465,"height":367},{"@type":"BreadcrumbList","@id":"https:\/\/blog.risingstack.com\/using-buffers-node-js-c-plus-plus\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.risingstack.com\/"},{"@type":"ListItem","position":2,"name":"Using Buffers to share data between Node.js and C++"}]},{"@type":"WebSite","@id":"https:\/\/blog.risingstack.com\/#website","url":"https:\/\/blog.risingstack.com\/","name":"RisingStack Engineering","description":"Node.js Tutorials &amp; Resources","publisher":{"@id":"https:\/\/blog.risingstack.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.risingstack.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/blog.risingstack.com\/#organization","name":"RisingStack Engineering","url":"https:\/\/blog.risingstack.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.risingstack.com\/#\/schema\/logo\/image\/","url":"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2021\/05\/logo-white-f0fca36fce94ceacd3d608caa6649361-1.svg","contentUrl":"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2021\/05\/logo-white-f0fca36fce94ceacd3d608caa6649361-1.svg","width":180,"height":45,"caption":"RisingStack Engineering"},"image":{"@id":"https:\/\/blog.risingstack.com\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/blog.risingstack.com\/#\/schema\/person\/7cd795f2e5173258661ba604144b0b22","name":"RisingStack Engineering","url":"https:\/\/blog.risingstack.com\/author\/coolsp\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/posts\/2717","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/comments?post=2717"}],"version-history":[{"count":1,"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/posts\/2717\/revisions"}],"predecessor-version":[{"id":4225,"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/posts\/2717\/revisions\/4225"}],"wp:attachment":[{"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/media?parent=2717"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/categories?post=2717"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/tags?post=2717"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}