AngelScript <-> C++ binder class.

Started by
45 comments, last by NickGalko 10 years, 5 months ago

Updates!
  • Script functions can be called now without any pain laugh.gif


Nice! I've been thinking of implementing a helper add-on for doing this myself for sometime.


One thing you need to think about, is how this would work with shared asIScriptContext's. Ideally the application would only allocate one asIScriptContext for each script function that runs in parallel. If all script functions are executed in sequence then only one asIScriptContext should be used by all executions, otherwise you would be wasting resources if all function objects hold their own asIScriptContext, or have a performance impact if a new asIScriptContext is allocated for each execution.

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
Alright, I've fixed some things on function import.
Now I've managed to add a function "decomposition" too to find the functions by it's declaration, not only the name. biggrin.gif
So now you can import overloaded functions from script.

Like this:


Function<int(int,int)> sumi = module->getFunction<int(int,int)>("sum");
sumi(10, 20); // sum ints

Function<float(float,float)> sumf = module->getFunction<float(float,float)>("sum");
sumf(10.4f, 14.3f); // sum floats
[/quote]


Here is an example. Suppose that you have a game object class called GameObject. In your implementation, you want to be able to inherit from this object and add new features to it, such as and Enemy that can ShootAtPlayer.

The current solution is something like the following, assuming GameObject is registered as Core_GameObject with the functions AddModel and SomeOtherMethod.

// Angelscript

class GameObject
{
GameObject()
{
m_Core = Core_GameObject();
}

GameObject( const Core_GameObject@ obj)
{
@m_Core = obj;
}

// Let's assume that ScenegraphNode is doing the same thing as this class.

ScenegraphNode@ AddModel(const string@ resource)
{
return ScenegraphNode(m_Core.AddModel(resource));
}

void SomeOtherMethod()
{
m_Core.SomeOtherMethod();
}

private Core_GameObject@ m_Core;
};

// Then your enemy class.

class Enemy : GameObject
{
void ShootAtPlayer()
{
// Implementation here.
}
};




It's a possibility. I'll push that feature into the queue (laugh.gif) since it needs some "investigation"



[quote name='WoLfezito' timestamp='1315467495' post='4858947']
Updates!
Script functions can be called now without any pain


Nice! I've been thinking of implementing a helper add-on for doing this myself for sometime.


One thing you need to think about, is how this would work with shared asIScriptContext's. Ideally the application would only allocate one asIScriptContext for each script function that runs in parallel. If all script functions are executed in sequence then only one asIScriptContext should be used by all executions, otherwise you would be wasting resources if all function objects hold their own asIScriptContext, or have a performance impact if a new asIScriptContext is allocated for each execution.
[/quote]

What you mean? I'm currently creating a new context for each call and then releasing it with asIScriptContext::Release()... should I create only one context for each function? Now I'm confused on how to handle this. huh.gif
Contexts are pretty expensive to be constantly creating and destroying. You would probably be better served using a context pool where you can automatically manage the lifetime of context instances. I do this for sharing contexts between scripted game entities in my engine so that I can parallelize the updating of entities and not have to allocate a context for each one.

Hope that helped a bit.

Contexts are pretty expensive to be constantly creating and destroying. You would probably be better served using a context pool where you can automatically manage the lifetime of context instances. I do this for sharing contexts between scripted game entities in my engine so that I can parallelize the updating of entities and not have to allocate a context for each one.

Hope that helped a bit.



Sure it helped. I'll write the context pool then. tongue.gif
BTW, I'll need to thread-lock the instance being used by a call until its "release", right?

--- EDIT ---
Holy crap! I did 150.000 calls to calculate the "time" with the current algorithm and it took 300ms avg. Then I've implemented the context pool, and it took 15~20ms! Btw, you will be able to set the contextpool's object count into the engine :)

I'll commit the changes right now!

biggrin.gif
You could also make the size of the pool dynamic if you wanted to. In my project, I wrap the script engine in another class that also implements the pool and listens to the update loop. It cleans up contexts that have been inactive for a certain time.

Other expensive operations you will want to watch out for:

* Getting function ID's.
* Getting type ID's.

Andreas, care to expand on this list? As far as the function ID's are concerned, I actually made a post about it here. (Note: my code doesn't suck as much now as it did when I made this post.)

You could also make the size of the pool dynamic if you wanted to. In my project, I wrap the script engine in another class that also implements the pool and listens to the update loop. It cleans up contexts that have been inactive for a certain time.

Other expensive operations you will want to watch out for:

* Getting function ID's.
* Getting type ID's.

Andreas, care to expand on this list? As far as the function ID's are concerned, I actually made a post about it here. (Note: my code doesn't suck as much now as it did when I made this post.)


I'll try changing the pool to a dynamic one... but a little different from your way.


About the function ID's... that's exactly why you must store the function "pointer" like this:

Function<void(int, float)> cached_function = module->getFunction<void(int, float)>("name");[/quote]

and avoid code like this:

module->getFunction<void(int, float)>("name")(1234, 12.34f)[/quote]
It will keep a reference to the engine (for getting the context from the pool) and it's own function id... avoiding the search each call you make. rolleyes.gif

Edit -----

I've updated the context pool class, it's now dynamic, creating a new context each time there's none available for usage. smile.gif

The updated version AngelBinder
https://bitbucket.org/nick_galko/angelbind/src

This topic is closed to new replies.

Advertisement