Advertisement

Delegates are fully working now

Started by April 07, 2013 08:52 PM
12 comments, last by saejox 11 years, 7 months ago

I've just checked in the last changes to get delegates fully working in the AngelScript library.

If you're interested in trying it out, then you'll need to download revision 1613 from the SVN.

The solution builds upon the existing function pointers in AngelScript, and the syntax for creating delegates is similar to C#'s delegates.


class Foo
{
  void Bar() { counter++; }
  void counter = 0;
}
 
 
// Declare a funcdef, which is basically the desired signature for the delegates
funcdef void CALLBACK();
 
void main()
{
  Foo f;
 
  // Create the delegate as a construct call for the funcdef
  // Observe that the single argument gives the object reference and the name of the method
  CALLBACK @callback = CALLBACK(f.Bar);
 
  // Invoke the callback like a normal function
  callback();
}

The delegate is an actual object instance, which is slightly different from function pointers to global functions that doesn't create any new object instances. Even so delegates and function pointers are interchangeable as long as the function signature is identical.

Delegates cannot be created for value types as the delegate need to be able to hold on to a reference to the object. Currently it is not possible to create delegates for global functions either, but I'll probably have that implemented in the near future.

I hope you like the new enhancement. And please let me know if you find any problems with the implementation, so I can preferably have them fixed before the next release.

Regards,

Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Nice.

Question:

How do i register functions accepting delegates as parameters.


funcdef void CALLBACK();
class Foo
{
  void Bar() { counter++; }
  void counter = 0;
}

events.Add(CALLBACK(f.Bar));

How does RegisterObjectMethod look?

Does it accept asIScriptFunction*? Do i have to increase refcount myself?

Advertisement
You register it the same way as was done with function pointers before, i.e first register a funcdef to name the callback type, then register the object method as taking a handle of that type.

The method should be implemented to receive a pointer to a asIScriptFunction. The ref count should be updated the same way as is done for any handles.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Calling the delegate works. :)

Other questions:

asIScriptFunction has objForDelegate but no public method to get it. In some cases i would prefer to hold method pointer and object pointer separately.

objForDelegate has refCount of 2. Wouldn't it need to be 3? ( gc, script scope, delegate)


class Object
{
  void Method(){}
  int a = 1;
}

int main()
{
  Object @obj = Object();
  GetFunctionPtr(@Callback(obj.Method));
  obj.a++;
  return 1;
}
 


Holy cow, I didn't see this coming for a while yet! Awesome news, Andreas! I think this fulfills the last requirement to make Angelscript my favorite language ever. :)

@saejox: I haven't made any interface changes for 2.26.3, but I plan to add methods for inspecting the object pointer and method in 2.27.0. There will also be a new method for creating delegates from the application side. For the refCount, at what exact moment did you inspect the refCount? In the script above, the Object is not garbage collected, so the only references are the local variable and the delegate.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

Ok, i forgot not all script objects needs to be GC'd. unsure.png

I have crash during compilation caused by overloaded methods:


class Object
{
  void Method(Object @obj){obj.a++;}
  void Method(){}
  int a = 1;
}

int main()
{
  Object @obj = Object();
  GetFunctionPtr(@Callback(obj.Method));
  obj.a++;
  return 1;
}

Registration:


void GetFunctionPtr(asIScriptFunction *func) {...}
r = engine->RegisterFuncdef("void Callback()"); assert(r>=0);
r = engine->RegisterGlobalFunction("void GetFunctionPtr(Callback@)", asFUNCTION(GetFunctionPtr), asCALL_CDECL);
assert(r>=0);

Crashing in module compilation. at line 8122 as_compiler.cpp. bestMethod is null.

The scenario should work. The compiler is supposed to pick the right overload. Looks like I missed something. I'll look into it. Thanks.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

The fix is simple. The if condition on line 8122 needs to check if bestMethod is not null before checking if the constness is correct. I'll have the check-in done as soon as I get home.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

That works. Thank you.


First multiple subtypes, now delegates. AngelScript started 2013 very strongly.

I need to rewrite significant portion of my game now. :)

This topic is closed to new replies.

Advertisement