Ok, this helped me get back on track.  As suggested, I replaced the call to 
WrapPoint in the ConstructPoint method with this:

args.This()->SetInternalField(0, External::New(point));


At runtime, this yielded the following error:

# Fatal error in v8::Object::SetInternalField()
> # Internal field out of bounds


because I needed the following line in the DoStuff method:

constructor->InstanceTemplate()->SetInternalFieldCount(1);


In other words, I was doing things to *pointTemplate's *InstanceTemplate 
that I should have been doing to the *constructor's* InstanceTemplate.  I 
think I got this idea from some outdated postings about maintaining two 
templates instead of one, although there is plenty of newer info out there 
to suggest otherwise (shrug).  In any case, this makes a lot of sense and 
ties back to my original suspicion about the pointTemplate variable (and 
its InstanceTemplate) not really "going anywhere".

Thank you all very much for setting me straight.  The full updated code 
snippets are below.  I will update again if/when I get a Point function 
working as well.

//The Point C++ class
> class Point {
>    public:
>     Point(int x, int y) : x_(x), y_(y) { }
>     int x_, y_;
>   };

 

> //The method where I start doing V8 things.  Set up an Isolate, Context, 
> etc.  Only the relevant parts are shown here.
> bool MyTest::DoStuff(...)
> {
> ...
>   Local<FunctionTemplate> constructor = 
> FunctionTemplate::New(ConstructPoint);
>   constructor->InstanceTemplate()->SetInternalFieldCount(1);  //Set the 
> InternalFieldCount on the CONSTRUCTOR'S InstanceTemplate
>   constructor->InstanceTemplate()->SetAccessor(String::New("x"), 
> GetPointX);  //Same goes for the Accessor
>   context->Global()->Set(String::New("Point"), constructor->GetFunction());
> ...
> }

 

> //The Point constructor function
> void MyTest::ConstructPoint(const FunctionCallbackInfo<Value>& args)
> {
> //start a handle scope
> HandleScope handle_scope;
>  
> //get an x and y
> int x = args[0]->Int32Value();
> int y = args[1]->Int32Value();
>  
> //generate a new point
> Point *point = new Point(x, y);
>  
> //Set the C++ point to the JS point
> args.This()->SetInternalField(0, External::New(point));
> }

 

> //The getter function for "somePoint.x" in Javascript.  Sadly, I am never 
> getting here!
> void MyTest::GetPointX(Local<String> name, const 
> PropertyCallbackInfo<Value>& info)
> {
>     Local<Object> self = info.Holder();
>     Local<External> wrap = 
> Local<External>::Cast(self->GetInternalField(0));
>     void* ptr = wrap->Value();
>     int value = static_cast<Point*>(ptr)->x_;
> info.GetReturnValue().Set(Number::New(value));
> }



On Monday, July 8, 2013 2:35:53 AM UTC-5, Lyndsey wrote:
>
> I know that others have posted questions about this here and elsewhere. 
>  However, I generally find either the question or the answer (or both) to 
> be either too vague or too old (or both).
>
> I simply want to wrap a C++ class so that it can be exposed in Javascript, 
> like so:
>
> var myPoint = new Point(3,4);
>> print(myPoint.x);  //Assume print is defined and works splendidly
>
>
> The Point example, of course, is taken directly from the V8 Embedder's 
> Guide <https://developers.google.com/v8/embed>.  However, I had to tweak 
> it significantly just to get it to compile and run (Win x64 Debug).  I also 
> used a 2009 blog post by Alex 
> Iskander<http://create.tpsitulsa.com/blog/2009/01/29/v8-objects/>. 
>  This StackOverflow 
> posting<http://stackoverflow.com/questions/3066833/how-do-you-expose-a-c-class-in-the-v8-javascript-engine-so-it-can-be-created-u>that
>  referred me there offers a little clarification but not much.
>
> The specific problem I'm having is that a Point can be constructed fine 
> but its member, x, cannot be accessed.  I set breakpoints in the C++ getter 
> function called GetPointX but they are never reached.  The Javascript 
> snippet above prints "undefined" instead of "3" as desired.  I think I must 
> be missing something simple.  Perhaps I'm not associating pointTemplate 
> or instance_templ back to something else, like the Point constructor or 
> the global context?
>
> Note: At the moment, I am not interested in memory management or even the 
> ability to *set *x.  Or y.  I just want to get this part working as a 
> minimal proof-of-concept.  Maybe a function (rather than a property) on the 
> Point class would be my next step (i.e. myPoint.inverse() where x and y 
> are swapped or something).  But I'm not there yet.
>
> I've included as much code as I think is necessary below.  Please let me 
> know if more is needed and I'd be happy to supply it.  Thanks in advance 
> for your help!
>
> //The Point C++ class
>> class Point {
>>    public:
>>     Point(int x, int y) : x_(x), y_(y) { }
>>     int x_, y_;
>>   };
>>
>  
>
>> //The method where I start doing V8 things.  Set up an Isolate, Context, 
>> etc.  Only the relevant parts are shown here.
>> bool MyTest::DoStuff(...)
>> {
>> ...
>> Local<FunctionTemplate> constructor = 
>> FunctionTemplate::New(ConstructPoint);
>> context->Global()->Set(String::New("Point"), constructor->GetFunction());
>>
>  
>
>> pointTemplate = FunctionTemplate::New();
>> Local<ObjectTemplate> instance_templ = pointTemplate->InstanceTemplate();
>> instance_templ->SetInternalFieldCount(1);
>> instance_templ->SetAccessor(String::New("x"), GetPointX);
>> ...
>> }
>>
>  
>
>> //The Point constructor function
>> void MyTest::ConstructPoint(const FunctionCallbackInfo<Value>& args)
>> {
>> //start a handle scope
>> HandleScope handle_scope;
>>  
>> //get an x and y
>> int x = args[0]->Int32Value();
>> int y = args[1]->Int32Value();
>>  
>> //generate a new point
>> Point *point = new Point(x, y);
>>  
>> //return the wrapped point
>> WrapPoint(point);
>> }
>>
>  
>
>> //The wrapper function
>> Handle<Object> MyTest::WrapPoint(Point *pointToWrap) 
>> {
>>     //enter a handle scope
>>     HandleScope handle_scope;
>>  
>>     //create a new point instance
>>     Local<Object> point_instance = 
>> pointTemplate->GetFunction()->NewInstance();
>>  
>>     //set that internal field
>>     point_instance->SetInternalField(0, External::New(pointToWrap));
>>  
>>     //to prevent the point_instance from being destroyed when its
>>     //scope handle_scope is, use the Close() function
>>     return handle_scope.Close(point_instance);
>> }
>>
>  
>
>> //The getter function for "somePoint.x" in Javascript.  The guts of this 
>> could be wrong.  Sadly, I am never getting here at all!
>> void MyTest::GetPointX(Local<String> name, const 
>> PropertyCallbackInfo<Value>& info)
>> {
>>     Local<Object> self = info.Holder();
>>     Local<External> wrap = 
>> Local<External>::Cast(self->GetInternalField(0));
>>     void* ptr = wrap->Value();
>>     int value = static_cast<Point*>(ptr)->x_;
>>     info.GetReturnValue().Set(Number::New(value));
>> }
>
>
>  
>

-- 
-- 
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users
--- 
You received this message because you are subscribed to the Google Groups 
"v8-users" 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