Thanks Nate - doesn't that still have the issue as above though, where the user can do this:
var object = new MyObject(); var myData = object.myData(); object = null; And now `object` will get GC-ed, and that pointer will no longer be valid, so if the user tries to access myData the program will segfault? Also, this is creating a persistent handle every single time someone calls object.myData(); - what is the right way to make sure those get cleaned up? I have no way of knowing when the user will throw away their reference to myData On Thursday, December 12, 2013 9:51:44 PM UTC-8, Nathan Rajlich wrote: > > 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<https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2FTooTallNate%2Fref%2Fblob%2F44665a4e99d721910d29bbecc1f45b3b1ef7fb14%2Fsrc%2Fbinding.cc%23L101-L120&sa=D&sntz=1&usg=AFQjCNEpv9tX0bXNjZbmu26yKcdOX21Jaw> > > > On Thu, Dec 12, 2013 at 8:18 PM, AT <[email protected] <javascript:>>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]<javascript:> >> To unsubscribe from this group, send email to >> [email protected] <javascript:> >> 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] <javascript:>. >> 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.
