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.

Reply via email to