Note that there are some explanatory texts on larger screens.

plurals
  1. POCalling a function that uses a wrapped object as an argument in Node.js and v8
    primarykey
    data
    text
    <p>I would like to do something like the following in node.js...</p> <p>var a = new A(); var b = new B();</p> <p>//onTick should be a function that takes an instance of B as an argument</p> <p>a.onTick = function(bInst){ .... }</p> <p>a.loop();</p> <p>meaning that A has a property "onTick" which is a function that gets called inside the loop. Note that A and B are defined as C++ wrapped functions, here are the definitions</p> <pre><code>void AClass::Init(Handle&lt;Object&gt; target) { Local&lt;FunctionTemplate&gt; tpl = FunctionTemplate::New(New); tpl-&gt;SetClassName(String::NewSymbol("A")); tpl-&gt;InstanceTemplate()-&gt;SetInternalFieldCount(1); tpl-&gt;PrototypeTemplate()-&gt;Set(String::NewSymbol("tick"), FunctionTemplate::New(Tick)-&gt;GetFunction()); tpl-&gt;PrototypeTemplate()-&gt;Set(String::NewSymbol("loop"), FunctionTemplate::New(Loop)-&gt;GetFunction()); constructor = Persistent&lt;Function&gt;::New(tpl-&gt;GetFunction()); constructor-&gt;InstanceTemplate()-&gt;SetAccessor(String::New("onTick"), GetOnTick, SetOnTick); target-&gt;Set(String::NewSymbol("A"), constructor); } Handle&lt;Value&gt; AClass::New(const v8::Arguments &amp;args) { HandleScope scope; AClass* acls = new AClass(); WrappedAClass* wrappedA = new WrappedAClass(); acls-&gt;wrappedAInst_ = wrappedA; window-&gt;Wrap(args.This()); return args.This(); } Handle&lt;Value&gt; AClass::Loop(const Arguments &amp;args) { HandleScope scope; AClass* acls = ObjectWrap::Unwrap&lt;AClass&gt;(args.This()); acls-&gt;wrappedInst_-&gt;loop(); return scope.Close(Undefined()); } </code></pre> <p>I believe this is how you set the getter and setter of a property</p> <pre><code>Handle&lt;Function&gt; GetOnTick(Local&lt;String&gt; property, const AccessorInfo&amp; info) { AClass* acls = ObjectWrap::Unwrap&lt;AClass&gt;(info.Holder()); return acls-&gt;onTick_; } void SetOnTick(Local&lt;String&gt; property, Local&lt;Function&gt; value, const AccessorInfo&amp; info) { AClass* acls = ObjectWrap::Unwrap&lt;AClass&gt;(info.Holder()); acls-&gt;onTick_ = Persistent&lt;Function&gt;::New(value); //Here's where I know I'm doing it wrong void func(WrappedClassB* wcb) { const unsigned argc = 1; Local&lt;Value&gt; argv[argc] = { Local&lt;Value&gt;::New(BClass::Instantiate(wcb)) }; acls-&gt;onTick_-&gt;Call(Context::GetCurrent()-&gt;Global(), argc, argv); } acls-&gt;wrappedAInst_-&gt;setTickFunc(func); } </code></pre> <p>What I am trying to do is take the function from setting onTick (which takes an instance of Class B) and wrap it inside a function that instatiates a new BClass.</p> <p>Anyways heres the definition for BClass</p> <pre><code>Persistent&lt;Function&gt; BClass::constructor; BClass::BClass() { } BClass::~BClass() { } void BClass::Init(Handle&lt;Object&gt; target) { Local&lt;FunctionTemplate&gt; tpl = FunctionTemplate::New(New); tpl-&gt;SetClassName(String::NewSymbol("B")); tpl-&gt;InstanceTemplate()-&gt;SetInternalFieldCount(1); constructor = Persistent&lt;Function&gt;::New(tpl-&gt;GetFunction()); target-&gt;Set(String::NewSymbol("B"), constructor); } Handle&lt;Value&gt; BClass::New(const v8::Arguments &amp;args) { HandleScope scope; BClass* bcls = new BClass(); bcls-&gt;Wrap(args.This()); WrappedBClass* wrappedB = new WrappedBClass(); bcls-&gt;wrappedBInst_ = wrappedB; return args.This(); } Handle&lt;Value&gt; BClass::Instantiate(const WrappedBClass &amp;wbc) { HandleScope scope; //I know the following is wrong but it shows what I am trying to do BClass* bcls = new BClass(); bcls-&gt;wrappedBInst_ = wbc; return scope.Close(Local&lt;v8::Value&gt;::New(bcls)); } </code></pre> <p>Both AClass and BClass use another C++ class and save the instance as a property (wrappedBInst, wrappedAInst) I believe I need the Instantiate function for when I need to convert an instance of the WrappedBClass into a BClass.</p> <p>WrappedBClass doesn't do anything special but WrappedAClass inherits a class which has a loop and an onTick function, and the onTick function is where I need to call my Javascript function, so in WrappedAClass I overrode onTick and added a setTickFunc function.</p> <pre><code>class WrappedAClass : public InheritedClass{ public: void setTickFunc(void (*func)(WrappedBClass*)){ tickFunc = func; } protected: void tickFunc; virtual void onTick(WrappedBClass* wbc){ if(tickFunc){ tickFunc(wbc); } } } </code></pre> <p>So the only way I think that I can get into the loop and use a javascript function as the onTick function is to first wrap the javascript function into a c++ function and then set that function by calling setTickFunc(). Am I going about this the right way?</p> <p>I'm a decent programmer but just recently started working with C++ so excuse my obvious mistakes, the biggest one is most likely this:</p> <pre><code>void SetOnTick(Local&lt;String&gt; property, Local&lt;Function&gt; value, const AccessorInfo&amp; info) { AClass* acls = ObjectWrap::Unwrap&lt;AClass&gt;(info.Holder()); acls-&gt;onTick_ = Persistent&lt;Function&gt;::New(value); //Here's where I know I'm doing it wrong void func(WrappedClassB* wcb) { const unsigned argc = 1; Local&lt;Value&gt; argv[argc] = { Local&lt;Value&gt;::New(BClass::Instantiate(wcb)) }; acls-&gt;onTick_-&gt;Call(Context::GetCurrent()-&gt;Global(), argc, argv); } acls-&gt;wrappedAInst_-&gt;setTickFunc(func); } </code></pre> <p>I'm still trying to figure out how to create an anonymous function that holds on to the value of a variable from the outside (acls). I don't think closures are valid here, the key is that this function only have one argument (WrappedClassB* wcb) because it needs to be set as the OnTick function.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload