Jump to content

  • Log In with Google      Sign In   
  • Create Account


We have 4 x Pro Licences (valued at $59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.

Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!


Member Since 03 Jun 2007
Offline Last Active Apr 14 2014 06:33 AM

Posts I've Made

In Topic: Ownership problem of Funcdefs.

11 October 2013 - 04:54 PM

Thanks for the quick responses.

I got it to work now :) with the type ID from the scriptModule.
The CScriptWeakRef also assumes it gets an handle that was reffed when it was passed, so it releases it as to not keep the strong.

So to make sure the object didn't get destroyed because of that I had to pass the object reffed (so add another ref)


Anywayz, glad to finally get it to work.

Oh btw, I looked at the documentation regarding asBEHAVE_GET_WEAKREF_FLAG, and it looked like a whole lot to take in.
Our application though, is fully aware of refcounting on application-registered objects, whether they were reffed/created by script or by the application.
We have our own set of smart pointers, much like the ones in boost, that count strong as well as weak references. Ref-objects expose addRef and Release functions that share the same use/ref count, which we use for the behaviours in script.


So basically I could write my own template specialization for weakref<T> instead of adding the WEAKREF_FLAG behavior I guess?
If I use template specialization for all Application types, and use CScriptWeakRef for everything else, I don't have to deal with the shared boolean, and can use our existing weakref methods.  I'll try that later :)

Well thanks again!



In Topic: Ownership problem of Funcdefs.

10 October 2013 - 02:51 PM

I tried the GetTypeIdByDecl() approach before I commented, but that just returns asINVALID_TYPE for anything other than Application classes. The function is invoked by script, so it is compiled and other types should be available at the point of the call.


Thanks for telling me about the asBEHAVE_GET_WEAKREF_FLAG. Can't believe I've missed that :-)



In Topic: Ownership problem of Funcdefs.

10 October 2013 - 01:11 PM

Hi Andreas, 

Thank you for your tips. Sorry for my late response. I was on holiday for a bit :)


The example you gave me still doesn't work. The main problem being that GetObjectTypeByDecl doesn't exist :)

I tried to make it work with GetObjectTypeByName, but that function just returns NULL unless I ask for a Class name registered by the application.
So on both "weakref<Foo>" and "Foo" it just returns NULL. "Control" for instance, does work.


I did some hacking right before I went, and managed to get it to work in a (probably) ugly way, by just skipping the ReleaseScriptObject calls, and passing Type in cases where getSubType returned NULL. (when I still constructed the weakref with objectype instead of weakref<Foo> type.

This seemed to work but I had no idea if I broke anything else.

So far it's obvious to me that the weakref was written with script binding in mind ;-)
What I was wondering about though, is since there is no interface that communicates the refcount of objects of application registered types, weakrefs in script will probably be set to null while the application still holds refs, meaning the weakref will become null while the object is not destroyed. Is this assumption correct ?

It would really be wonderful in angelscript could support weakrefs better. callbacks could default to no-op when objects decay so they no longer ref the object they are holding. addRef/release functions could return the refcount so the scriptengine would be aware of the objects refcount, even when the object comes from the application.


Anyway, I could probably throw something together based on the weakref implementation that would work, but ofcourse it would be nice to have something that is also supported in future releases :)


What do you recommend?






In Topic: Ownership problem of Funcdefs.

03 October 2013 - 02:33 PM

Hi Andreas,

So I finally got around to implementing this, and I noticed a problem with the CScriptWeakRef.

The code you showed me for weakreffing the object in the engine throws an exception when I pass it a script object.

void FuncReceivingDelegate(asIScriptFunction *delegate)
   // Get the object pointer from the delegate
   if( delegate->GetFuncType() == asFUNC_DELEGATE )
     void *obj = delegate->GetDelegateObject();
     asIObjectType *objType = delegate->GetDelegateObjectType();
     asIScriptFunction *method = delegate->GetDelegateFunction();
     // Create a weak ref to keep the pointer to the object
     CScriptWeakRef *weakRefToDelegatedObject = new CScriptWeakRef(obj, objType);
     // Store the weak ref and the method instead of the original delegate
The constructor for the CScriptWeakRef throws an exception on this line:
// Release the handle that was received, since the weakref isn't suppose to prevent the object from being destroyed
m_type->GetEngine()->ReleaseScriptObject(m_ref, m_type->GetSubType());

As far as I can see, GetSubType returns 0 if the object is not templated?
So it passes 0 as subtype here, and crashes in "ReleaseScriptObject" upon trying to access this null-pointer.


I've tried passing m_type instead of subtype when subtype was null, but that messes up the ref-count and destroys my object when it is still in scope.

adding another m_type->AddRef() didn't solve that.

Since I don't know exactly what I'm doing, I thought I'd ask ;-)


Here's my script:

Timer@ timer;

class Foo
  void bar()
   	echo ("Called bar...\n");
  	echo ("Foo destroyed\n");

Foo@ f;

void main(Control@ control)
  @f = Foo();
  @timer = control.createTimer(1000, true);
  timer.elapsed += Action(f.bar);





In Topic: Ownership problem of Funcdefs.

15 September 2013 - 04:03 PM

OK, I've tried some more things, and then realized that what I was asking is probably something weird smile.png
I thought about how other languages solve this problem, and I just realized that unregistering callbacks is always a bit awkward smile.png


I thought this could be handled with the lifespan of the function handle, but this is not usually the case in other languages. So I reckon this might not be the best way to go, and is perhaps not always what you want, as it requires the user to keep the thing alive/in scope some how.


You did help me a great deal in understanding what is going on, and have given me a couple of options to solve this. At least now I know how to let the App know when the delegate CANNOT be called (and the user forgot to unregister the callback). I particularly like the callback function option, as it eliminates inactive objects that stay there simply because the didn't get called. smile.png


The Object weakref is nice to make sure I don't take ownership of the object. 


I think I will go with the C# way of deregistering callbacks, by passing the delegate once for register, and another time to unregister it.

So perhaps something like:


//Or perhaps I can even go full C# and make this work :)

timer.event += timerCallback(myObject.myFunction);
timer.event -= timerCallback(myObject.myFunction);

I noticed that when a function handle is passed it is the same, even when stored in different handle instances, and the delegates are not, but I can use GetDelegateFunction in that case. I'll use the function pointers to identify which callback to remove, and use the userdata callback to clean up callbacks that are no longer valid.

Thank you very much for the information, and taking the time of helping me with this.