On Wed, Apr 24, 2013 at 1:07 AM, Mike Moening <mike.moen...@gmail.com> wrote:
> Ben,
>
> Can you expand on your example?
> I'm sure this is piece of cake for you, but I'm not getting what you mean.
>
> All the samples I can find show using ObjectTemplate and the
> SetCallAsFunctionHandler() to handle construction from the C++ side.
>
> var o = new MyObject();
> var x = new MyObject();
> o.doSomething(x);
>
> In the above example doSomething() needs to simply validate its 1st argument
> is of type "MyObject".
> That's it.
>
> Apparently HasInstance() (from FunctionTemplate) is for this purpose.
> But ObjectTemplate doesn't have a HasInstance() method.
>
> My object has to do more than just be constructed.
> It's got other methods too.
> How can I fire a C++ constructor function with a FunctionTemplate and have
> other methods on the object?
> Without a more concrete example I'm lost.
>
> I do appreciate the willingness to help. THANK YOU.

This is in a nutshell how you use FunctionTemplate to create a
constructor + prototype methods:

  Local<FunctionTemplate> t = FunctionTemplate::New(MyObject::New);
  t->SetClassName(String::New("MyObject"));
  t->InstanceTemplate()->SetInternalFieldCount(1);
  Local<FunctionTemplate> fn = FunctionTemplate::New(MyObject::Foo);
  t->PrototypeTemplate()->Set(String::New("foo"), fn);
  my_object_template = Persistent<FunctionTemplate>::New(t);

The constructor looks something like this:

  Handle<Value> MyObject::New(const Arguments& args) {
    HandleScope handle_scope;
    if (args.IsConstructCall() === false) {
      // Handle non-constructor invocation, i.e. `MyObject()`
      Local<Function> constructor = my_object_template->GetFunction();
      return handle_scope.Close(constructor->NewInstance(0, NULL));
    }
    MyObject* instance = new MyObject;
    args.This()->SetAlignedPointerInInternalField(0, instance);
    return args.This();
  }

The foo() method:

  Handle<Value> MyObject::Foo(const Arguments& args) {
    HandleScope handle_scope;
    void* pointer = args.This()->GetAlignedPointerFromInternalField(0);
    MyObject* instance = static_cast<MyObject*>(pointer);
    // do whatever
    return handle_scope.Close(...);
  }

The trick I mentioned in my other post is that you add a second
internal field that points to some atom (usually a char
class_name_id[] = "MyClassName") that you check for in your prototype
methods so you can be sure that args.This() is what you expect it to
be.  Be sure to check args.This()->InternalFieldCount() as well.

We don't use that trick in node.js actually but that's because native
objects are not exposed directly, there's (almost) always some pure JS
object sitting in front of it.  It's a pretty good approach when
you're not operating in a hostile environment (running untrusted
code), it saves a lot of headaches.

-- 
-- 
v8-users mailing list
v8-users@googlegroups.com
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 v8-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to