Wrapped C++ objects so instanceof operator works

477 views
Skip to first unread message

Martin Cohen

unread,
Jun 7, 2010, 10:45:12 AM6/7/10
to v8-users
Hello guys,

I'm trying to "wrap" a C++ object to JavaScript with this notorious
technique:

//------------------------------------------------------------------------
/// Wraps C++ instance to JS object.
v8::Persistent<v8::Object> wrap( T * object )
//------------------------------------------------------------------------
{
// Make sure we have only one JS object per C++ instance.
Instances::iterator it = m_instances.find( object );
if( it != m_instances.end() )
return it->second;
// Create an instance of JS object
v8::Persistent<v8::Object>
js_object( v8::Persistent<v8::Object>::New(m_t_object->GetFunction()-
>NewInstance()) );
// Make the handle weak
js_object.MakeWeak( object, &TClass<W,T>::destructorCall );
// Register the JS object with the C++ instance
m_instances.insert( std::make_pair( object, js_object ) );
// Set the internal field value to the C++ object
js_object->SetInternalField( 0, v8::External::New( object ) );
return js_object;
}

However a returned object has no class name set, so the "instanceof"
operator does not work. From what I've learned, the "instanceof"
operator works using the object.prototype.constructor property, though
I'm not sure how to correctly set it up in this wrap function.

Any ideas?

Stephan Beal

unread,
Jun 7, 2010, 4:08:30 PM6/7/10
to v8-u...@googlegroups.com
On Mon, Jun 7, 2010 at 4:45 PM, Martin Cohen <martin....@gmail.com> wrote:
       m_instances.insert( std::make_pair( object, js_object ) );
       // Set the internal field value to the C++ object
       js_object->SetInternalField( 0, v8::External::New( object ) );
       return js_object;
...
 
However a returned object has no class name set, so the "instanceof"
operator does not work. From what I've learned, the "instanceof"
operator works using the object.prototype.constructor property, though
I'm not sure how to correctly set it up in this wrap function.

If you want to skip a lot of trial and error, and jump right into your coding, i strongly recommend using one of the several 3rd-party libs which take care of those bits for you.

A partial list (the ones i know about):


Slapping a single class binding together isn't too much work (once you've done it a few times), but if you want to bind more than a couple classes, a generic framework for doing so is in order. The above libraries provide such features, each with varying strengths and weaknesses.

--
----- stephan beal
http://wanderinghorse.net/home/stephan/

Martin "Cohen" Balazik

unread,
Jun 7, 2010, 4:37:35 PM6/7/10
to v8-u...@googlegroups.com

Thanks Stephan. I've already looked at your v8-juice. But I was slightly afraid of it's experimental state and few comments inside.

Though before I jump to something as clever as v8-juice and v8, I'd really love to know how the thing works and what it does for me. Therefore I'm trying to put together something simple myself.

I looked into juice to see how you do this particular thingie, but was unable to find it. That fact proves that I'm not ready to use it. :)

Can you, please, point me where to look?

On 7 Jun 2010 22:08, "Stephan Beal" <sgb...@googlemail.com> wrote:

On Mon, Jun 7, 2010 at 4:45 PM, Martin Cohen <martin....@gmail.com> wrote:
>

>        m_instance...

If you want to skip a lot of trial and error, and jump right into your coding, i strongly recommend using one of the several 3rd-party libs which take care of those bits for you.

A partial list (the ones i know about):


Slapping a single class binding together isn't too much work (once you've done it a few times), but if you want to bind more than a couple classes, a generic framework for doing so is in order. The above libraries provide such features, each with varying strengths and weaknesses.



--
v8-users mailing list
v8-u...@googlegroups.com
http://groups.google.com/group/v8-users

Stephan Beal

unread,
Jun 7, 2010, 5:52:41 PM6/7/10
to v8-u...@googlegroups.com
On Mon, Jun 7, 2010 at 10:37 PM, Martin "Cohen" Balazik <martin....@gmail.com> wrote:

Thanks Stephan. I've already looked at your v8-juice. But I was slightly afraid of it's experimental state and few comments inside.


"Experimental" is probably the wrong description now (though it does say that on the web page, i admit - that was well over a year ago). The core API has been stable for some time, and it's been used in at least one high-profile product which i'm aware of (i'm under NDA, though, so "no comment"), and i get good use out of it in my own projects.

Though before I jump to something as clever as v8-juice and v8, I'd really love to know how the thing works and what it does for me.

That's why i wrote v8-juice ;), despite the other libraries i mentioned already existing. Despite the conceptual simplicity of v8, learning to use it effectively can be like learning libcurses: lots of experimentation and lots of cursing.
 

I looked into juice to see how you do this particular thingie, but was unable to find it. That fact proves that I'm not ready to use it. :)

If you'll contact me off-list i'll be happy to help you out with it.

Can you, please, point me where to look?

i need to know what that thingie is, first :). Please contact me off-list, though - that'd be off-topic here. (If there's general interest i'll start a google group, but so far there's only been a handful of intermittent emails.)

PS: it's about midnight here (CET), so i might not get back to you until tomorrow night.

Matthias Ernst

unread,
Jun 8, 2010, 1:27:20 AM6/8/10
to v8-u...@googlegroups.com
On Mon, Jun 7, 2010 at 4:45 PM, Martin Cohen <martin....@gmail.com> wrote:

instanceof should work out of the box. instanceof(object, function) is
defined in terms of searching for "function.prototype" along the
object's prototype chain, not in terms of class name. Have you
exported "m_t_object->GetFunction()" to javascript, used it in the
instanceof expression and it is broken for you?

In any case, you can set the class name on the function:
FunctionTemplate::SetClassName(). In V8, this only influences
toString, though.

Matthias

>
> Any ideas?

avasilev

unread,
Nov 28, 2011, 3:28:34 PM11/28/11
to v8-u...@googlegroups.com
I have the same problem:

var http = new HttpClient;

(http instanceof HttpClient) returns false
(http instanceof Object) returns true;

Here is now I expose the constructor in C++:
    Handle<FunctionTemplate> ctor = FunctionTemplate::New(jsCtorCallback, External::New(userdata));
    ctor->SetClassName(String::New(T.typeName));
    objTempl = ctor->PrototypeTemplate();
    customizeObjectTemplate(objTempl);
    global->Set(String::New(T.typeName), ctor->GetFunction());

Any ideas?
Thanks in advance
Alex

Matthias Ernst

unread,
Nov 29, 2011, 12:16:21 PM11/29/11
to v8-u...@googlegroups.com
This works for me:

#include "v8.h"
using namespace v8;

int main(int argc, char* argv[]) {
  HandleScope locals;

  Persistent<Context> context = Context::New();
  Context::Scope context_scope(context);

  Handle<FunctionTemplate> ctor = FunctionTemplate::New();
  context->Global()->Set(String::New("T"), ctor->GetFunction());

  Local<Value> result = Script::Compile(String::New("(new T) instanceof T"))->Run();
  String::AsciiValue ascii(result);
  printf("%s\n", *ascii);
  return 0;
}


--

avasilev

unread,
Dec 5, 2011, 1:48:51 PM12/5/11
to v8-users
Hmmm, yes, I confirm your code works. Thanks a lot for the reply. So
it must be something in the details.
Reply all
Reply to author
Forward
0 new messages