Search code examples
c++node.jsv8node-modules

passing data between c++ and nodejs


The following code snippet is causing issued after upgrading node from v0.12 to v6.11

vector<char> buf;
// code that populates the vector

Local<Object> nbuf = Buffer::New(args.GetIsolate(), &buf[0], buf.size());

//return buffer to node    
args.GetReturnValue().Set(scope.Escape(nbuf));

The node upgrade implied having to change:

Local<Object> nbuf = Buffer::New(args.GetIsolate(), &buf[0], buf.size());

to:

Local<Object> nbuf = Buffer::New(args.GetIsolate(), &buf[0], buf.size()).ToLocalChecked());

The problem is that when printing out the content of the buffer in node the contents are not the same. So the questions is: how can I get the same behaviour as I had in node v0.12 when using node v6.11?

UPDATE: after some research I found the underlying problem - Buffer:New calls ArrayBuffer::New which builds an arrayBuffer on top of the exiting memory buffer, so when that goes out of scope the buffer only contains whatever is on the stack. In node-v0.12 Buffer:New was creating a copy of the data which it owned. The problem is I still don't know how to get the same behaviour using node-v6


Solution

  • posting this just in case anyone ever comes across the same issue:

    the issue is that between node 0.12 and node v6 the implementation of Buffer::New(...)

    MaybeLocal<Object> New(Isolate* isolate, const char* data, size_t length)
    

    has changed: in node 0.12 it used to call memcpy while for node v6 is just calls ArrayBuffer::New(env->isolate(), data, length) and this does not copy the data. According to the documentation:

    static Local v8::ArrayBuffer::New ( Isolate * isolate, void * data, size_t byte_length )

    Create a new ArrayBuffer over an existing memory block. The created array buffer is immediately in externalized state. The memory block will not be reclaimed when a created ArrayBuffer is garbage- collected.

    So the the locally created vector which the ArrayBuffer was built on top of, goes out of scope you are left with whatever is on the stack...which was pretty much what I saw.

    Solution: call Buffer::Copy(args.GetIsolate(), &buf[0], buf.size());