Sounds to me like you want the Buffer to use an existing external pointer without copying the data. i.e. *use* the existing pointer. This is possible by passing a "weak callback function" as the third argument to Buffer::New(). For an example, see here: https://github.com/TooTallNate/ref/blob/44665a4e99d721910d29bbecc1f45b3b1ef7fb14/src/binding.cc#L101-L120
On Thu, Dec 12, 2013 at 8:18 PM, AT <[email protected]> wrote: > Thanks Andrew! That is all very helpful. I'm still having a little bit of > trouble on the buffers. The object that I'm wrapping has a field on it > which is a std::vector<uint8_t>, and a method which returns that vector to > me. This is one of the methods that I'm exposing to JS, and I would like it > to return a Buffer, which I'm doing like this simplified example (in > v0.10.23): > > v8::HandleScope scope; > MyObject* object = node::ObjectWrap::Unwrap<MyObject>(args.This()); > std::vector<uint8_t> my_data = object->my_data(); > v8::Handle<v8::Object> buffer = > node::Buffer::New(reinterpret_cast<char*>(my_data.data()), > my_data.size()).handle_; > return scope.Close(buffer); > > However when I do this I'm actually getting a SlowBuffer. In node_buffer.h > it says I can construct a fast buffer by invoking New with a > v8::Handle<v8::String>, but I believe this would mean copying over the > data? Is that the only way to construct a fast (sliced) buffer? > > Also this is returning a persistent handle, and I don't think I fully > understand how to make sure those get cleaned up correctly - I just want > the data to get collected when the user decides to throw away the reference > to the buffer returned to them in javascript. Does that mean I have to make > the reference weak, and supply a callback to be invoked when only weak > references are held to the object? If that's the case, then it seems like I > actually need to delete (in the C++ sense) the backing node::Buffer*, but > since the callback only provides the char* data pointed at, I can't do that? > > Last but not least - if the user does this in JS: > var object = new MyObject(); > var myData = object.myData(); > object = null; > > Then object is eligible to get garbage collected, but myData has a pointer > into data held by object. Does this mean, again, that I have to make a copy > of the data every time someone calls myData()? Is there a more efficient > method (shared pointers? something else?) > > Sorry if some of that doesn't make sense - I'm having a hard time figuring > out the proper way to do this. > > Thanks! > > > On Thursday, December 12, 2013 9:43:29 AM UTC-8, Andrew Kelley wrote: >> >> I can't answer all of your questions but I can help with a couple: >> >> 2. setInternalFieldCount. See this page of v8 docs: >> http://izs.me/v8-docs/classv8_1_1Object.html# >> a94e24494687ea499471d41e914eeb90d >> >> My understanding of this is that you setInternalFieldCount to some >> integer (such as 3) and then you have that many slots with which to put >> stuff in. You can then use SetInternalField(0, someValue) and >> GetInternalField(0) where 0 is the index of the internal field. I think >> that the node::ObjectWrap helper thing uses internal field index 0 under >> the covers. So the fact that you have to setInternalFieldCount even though >> you never use it is a leaky abstraction. I could be wrong; I haven't >> actually looked at the node objectwrap code. >> >> >> 3. buffers. >> >> Here's a chat log of trevnorris helping me out with buffers: >> https://gist.github.com/superjoe30/7198261 >> >> 4. packaging >> >> It's generally considered convenient to bundle C library dependencies >> with your node module. So you'd compile your depending library along with >> your wrapper code all together, that way the user of your module does not >> actually need that library installed on their system. This is not required >> however, and if the dependency is huge and heavy it would probably make >> more sense to depend on it dynamically instead of bundling it. >> >> 5. general tips >> >> Look at existing node addons for reference. TooTallNate specifically has >> a bunch of good examples available on github to look at. >> For what it's worth here's a module I made: https://github.com/ >> superjoe30/node-groove >> It should by no means be taken as a perfect example; it's the first and >> only addon I've made, but maybe it can help anyway. >> >> good luck! >> >> On Tuesday, December 10, 2013 5:39:59 PM UTC-5, AT wrote: >>> >>> Hey all, >>> >>> I'm just starting to write my first C++ addon for node and I'm finding >>> that the documentation can be a little sparse at times. I had a few >>> beginner questions for you all, in no particular order: >>> >>> 1) v8::Signatures - It seems like they're supposed to validate that >>> functions are invoked on objects which can respond to that function, in >>> case people use call/apply. A common pattern in the node code is to use >>> NODE_SET_PROTOTYPE_METHOD macro to automatically use the correct signature, >>> but it generates multiple signature objects that I believe are all >>> identical, since they're based only on the template being supplied. So, >>> instead of doing: >>> >>> NODE_SET_PROTOTYPE_METHOD(tpl, "function1", Function1) >>> NODE_SET_PROTOTYPE_METHOD(tpl, "function2", Function2) >>> NODE_SET_PROTOTYPE_METHOD(tpl, "function3", Function3) >>> >>> I could do: >>> >>> v8::Local<v8::Signature> signature = v8::Signature::New(tpl); >>> tpl->PrototypeTemplate()->Set(v8::String::NewSymbol("function1"), >>> v8::FunctionTemplate::New(Function1, v8::Handle<v8::Value>(), >>> signature)); >>> tpl->PrototypeTemplate()->Set(v8::String::NewSymbol("function2"), >>> v8::FunctionTemplate::New(Function2, v8::Handle<v8::Value>(), >>> signature)); >>> tpl->PrototypeTemplate()->Set(v8::String::NewSymbol("function3"), >>> v8::FunctionTemplate::New(Function3, v8::Handle<v8::Value>(), >>> signature)); >>> >>> Is it correct to reuse the signature like this? Is it not worth doing so >>> because of the extra verbosity? >>> >>> Also, what is the second parameter (`data`) passed in to >>> FunctionTemplate::New? I took a look at v8.h but it was not described. >>> >>> 2) SetInternalFieldCount. I took at look at the following: >>> http://stackoverflow.com/questions/16600735/what-is-an- >>> internal-field-count-and-what-is-setinternalfieldcount-used-for >>> https://groups.google.com/forum/#!searchin/v8-users/ >>> SetInternalFieldCount/v8-users/2LyzMXilUiM/OVQpWehDm9MJ >>> >>> and I still don't fully understand this. It seems like SetInternalField >>> lets me associate arbitrary C++ objects with my JS objects, and >>> SetInternalFieldCount just makes space for that many (void *)'s, but I >>> don't think I understand the use case for this. In the node examples here: >>> http://nodejs.org/api/addons.html >>> >>> they call SetInternalFieldCount even though they don't set any internal >>> fields. Indeed, when I run some of my own code and omit the >>> SetInternalFieldCount(1) call, I get the following: >>> .node-gyp/0.10.16/src/node_object_wrap.h:71: void >>> node::ObjectWrap::Wrap(v8::Handle<v8::Object>): Assertion >>> `handle->InternalFieldCount() >0 ' failed. >>> >>> Why does this need to be a minimum of 1 if I have no internal fields? If >>> I want to implement my own JS objects it seems cleaner to me to have my >>> class which inherits from node::ObjectWrap to just have the necessary >>> members on it there, instead of having them set as internal fields? >>> >>> 3) Buffers. >>> >>> The first result on google for making a Node buffer in C++ land is the >>> following: >>> http://www.samcday.com.au/blog/2011/03/03/creating-a- >>> proper-buffer-in-a-node-c-addon/ >>> >>> This post is from 2011 - is it still accurate? Looking through the Node >>> source it seems that the structure is still the same as described in the >>> article (slow buffer implemented in node_buffers.h, regular buffer >>> implemented in JS land via buffer.js), but it seems so hacky to construct >>> buffers this way. What if someone changes the global Buffer? >>> >>> One of the comments an the article alludes to Buffer::MakeFastBuffer() >>> but I don't see this function in master. What I do see is SetupBufferJS: >>> https://github.com/joyent/node/blob/master/src/node_buffer.cc#L598 >>> which looks like it takes a C++ land buffer and makes it more >>> "node-like", but the methods it adds are different than the plain Buffer >>> interface provided in buffer.js, so I don't think that's what I want either. >>> >>> 4) Packaging >>> >>> What are the packaging conventions / how do I ship my addon which >>> depends on other libraries being present. >>> >>> For users who want to build from source: >>> >>> Should my library include the source of my dependency, and its >>> dependencies, and so on, so that users who try to compile will get the >>> versions that I'm building against? >>> >>> Should my library include none of my dependencies, and just include >>> instructions (before running node-gyp, install xxx >= 1.0.0, install yyy <= >>> 1.5.0, etc) >>> >>> For users who want to install from npm: >>> >>> Should my addon include pre-built binaries for the platforms that I plan >>> on supporting? >>> >>> Should it just give instructions (have the following libs available, >>> etc), and I can dynamically load those libraries? >>> >>> Sorry for the lengthy post - thanks in advance for all the help! >>> >> -- > -- > Job Board: http://jobs.nodejs.org/ > Posting guidelines: > https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines > You received this message because you are subscribed to the Google > Groups "nodejs" group. > To post to this group, send email to [email protected] > To unsubscribe from this group, send email to > [email protected] > For more options, visit this group at > http://groups.google.com/group/nodejs?hl=en?hl=en > > --- > You received this message because you are subscribed to the Google Groups > "nodejs" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/groups/opt_out. > -- -- Job Board: http://jobs.nodejs.org/ Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines You received this message because you are subscribed to the Google Groups "nodejs" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/nodejs?hl=en?hl=en --- You received this message because you are subscribed to the Google Groups "nodejs" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/groups/opt_out.
