Skip to main content
GameDev.net gamedev.net
🔒 Locked

AngelScript <-> C++ binder class.

Started by WoLfuluss Aug 23, 2011 at 7:16 AM 45 replies 20.1k views
Original Post
WoLfuluss
WoLfuluss
Hello everyone,
I'm writing an addon for AngelScript to make an easy "binder" between AS and C++
The current implementation looks like this:


...
/// Global vars
int g_test1;
unsigned int g_test2;
float g_test3;
std::string g_test4;

/// Global functions
std::string __stdcall func1(float a1, double a2, int a3);
uint __cdecl func2(int a1, unsigned short a2);
void func3();

/// Usage
using namespace AngelBinder;

/// Type translation helpers. If you don't do this, you can end up with a register error later.
AB_TRANSLATE_TYPE(std::string, "string") // Any usage of "std::string" will result in "string" into AngelScript
AB_TRANSLATE_TYPE(Numbers, "numbers") // Same as above.

int main()
{

/// Declares the script class.
Script script("module_name");

/// Exports the global variables
Exporter::Export(script)
[
Exporter::Variables()
.def("global_int", &g_test1);
.def("global_uint", &g_test2);
.def("global_float", &g_test3);
.def("global_double", &g_test4);
];

/// Exports the global functions
Exporter::Export(script)
[
Exporter::Functions()
.def("f1", &func1);
.def("f2", &func2);
.def("f3", &func3);
];

return 0;

}
...


The project is hosted on Google Code:
https://code.google.com/p/angelbinder/
_orm_
_orm_
You could create a batch exporter that takes class information and functions and exposes a "Process" function that automatically registers the class methods. But in the end, it really is no different than calling the engine functions themselves.
WitchLord
WitchLord
This looks neat. But I have a question for you. How do you decide how a reference parameter or pointer in a C++ function should be registered in AngelScript? This cannot be done automatically in all scenarios. I mean a reference parameter may be registered as ∈, &out, or &inout depending on what the function is supposed to do. Likewise a pointer parameter may also have multiple translations, &out, @, etc.

As for classes. Unfortunately I do not believe there is any way of automatically detecting available methods and properties through meta-programming, so I think what you'll need to do is to expose methods to register the type, functions, and properties one by one.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - <a href="http://www.angelcode.com/tower" rel
WoLfuluss
WoLfuluss
[font="arial, verdana, tahoma, sans-serif"]

You could create a batch exporter that takes class information and functions and exposes a "Process" function that automatically registers the class methods. But in the end, it really is no different than calling the engine functions themselves.


[/font]What I'm trying to make is something like ChaiScript's bind system. For normal functions, it works fine... it detects calling conventions, parameter types and return types. I can change exported function prototypes without touching the export function. The problem is not exporting class functions at all, it's exporting all types of new objects. Since I need to manually put all the function prototypes by hand as string, that can be a real pain if prototype changes during the development.

[font="arial, verdana, tahoma, sans-serif"]

This looks neat. But I have a question for you. How do you decide how a reference parameter or pointer in a C++ function should be registered in AngelScript? This cannot be done automatically in all scenarios. I mean a reference parameter may be registered as ∈, &out, or &inout depending on what the function is supposed to do. Likewise a pointer parameter may also have multiple translations, &out, @, etc.

As for classes. Unfortunately I do not believe there is any way of automatically detecting available methods and properties through meta-programming, so I think what you'll need to do is to expose methods to register the type, functions, and properties one by one.


[/font][font="arial, verdana, tahoma, sans-serif"]The current algorithm parses the function generating it's associated string prototype. Examples: [/font][font="arial, verdana, tahoma, sans-serif"]I'll be using "test" as the name of the function I'd like to export, and if I pass it to the parser function like:[/font]
[font="arial, verdana, tahoma, sans-serif"]std::string GenPrototype<F>(F f)

int test()
GenPrototype(&test);
returns "int test()"

void test()
returns "void test()"

unsigned int test()
returns "uint test()"

long long test()
returns "int64 test()"

std::string test()
returns "string test()"

std::string* test()
returns "string@ test()"

MyType test()
returns "MyType test()"

MyType* test()
returns "MyType@ test()"

and so on... it works the same way for parameters:

void test(int, std::string, unsigned int)
returns "void test(int, string, uint)"

void test(MyType, MyType*)
returns "void test(MyType, MyType@)"
[/font]




If I understood you right, this can be done by using a helper struct template by making a template like:

void test(Param::In<int>, Param::Out<int>);

But I haven't tought about this yet, since I don't know all the string prototype scenarios... I'm working only on basic types for now.

I have other question:
When exporting object types that is managed by the application (cannot be instantied, instances will be set by the application into the global variable scope), what's the best way to do that?
Just skipping bind the constructor/destructor? Or there's a more reliable way to do that?
WitchLord
WitchLord
If the type should behave as a singleton and always referred to through a global property registered by the application, then you should register the type with the flags asOBJ_REF | asOBJ_NOHANDLE. Then AngelScript will know the type won't use the FACTORY, ADDREF, and RELEASE behaviours.

If you just do not want the script to instantiate new objects, then just omit registering the factory, but register the ADDREF and RELEASE behaviours anyway. Even if the application is responsible for doing the memory management, AngelScript still needs the ADDREF and RELEASE behaviours to work properly. However, if the application can guarantee the life time of the object without these, you may register them with a simple dummy function that doesn't do anything.

See also: Manual: Registering a single-reference type
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - <a href="http://www.angelcode.com/tower" rel
toukkapoukka
toukkapoukka
Hi!

Good luck with your experiments. I thought I'd like to share this very similar thing that I wrote up: ASBind.h
Maybe we can collaborate or exchange ideas on these?
WoLfuluss
WoLfuluss

Hi!

Good luck with your experiments. I thought I'd like to share this very similar thing that I wrote up: ASBind.h
Maybe we can collaborate or exchange ideas on these?


Its exactly the same idea of your code. But I'm using boost::function_types and boost::mpl for function decomposition.
I'll be posting the whole test project here. I'm just finishing some details.
Maybe we can put both "projects" together


If the type should behave as a singleton and always referred to through a global property registered by the application, then you should register the type with the flags asOBJ_REF | asOBJ_NOHANDLE. Then AngelScript will know the type won't use the FACTORY, ADDREF, and RELEASE behaviours.

If you just do not want the script to instantiate new objects, then just omit registering the factory, but register the ADDREF and RELEASE behaviours anyway. Even if the application is responsible for doing the memory management, AngelScript still needs the ADDREF and RELEASE behaviours to work properly. However, if the application can guarantee the life time of the object without these, you may register them with a simple dummy function that doesn't do anything.

See also: Manual: Registering a single-reference type


Thanks for the info! I think I missed that page on the docs sad.gif


The first version is here: http://dtex.com.br/d...ds/AsBinder.rar
You'll not be able to compile without SP1 of Visual Studio 2010. It uses some C++0x concepts that's only present/supported on SP1. wink.gif
and, I'll try to add toukkapoukka's classes in the next version.


BTW:
All dependencies are included. (boost and my own signal/slot library)
jacmoe
jacmoe
Interesting.
But really not my cup of tea, since you are relying on unsupported C++1x features.
I like Toukkapoukkas code better.
Too many projects; too much time
WoLfuluss
WoLfuluss

Interesting.
But really not my cup of tea, since you are relying on unsupported C++1x features.
I like Toukkapoukkas code better.


Yeah, I'll try updating to that way.
jacmoe
jacmoe
Didn't mean to discourage you - I'd love if you two got together and actually came up with a current and maintained Angelscript/C++ binder.


License?
Too many projects; too much time
WoLfuluss
WoLfuluss
I'll be putting this into google code. And it'll be probably a very liberal license, coz I hate when I find something useful and just can't use on closed source / private projects. wink.gif

this was just a prototype.
jacmoe
jacmoe
You can put that C++11 stuff back next year - just found out that C++0x was approved 10 days ago.
Lots of neat stuff there - c++ is going to get so much better.
Too many projects; too much time
WoLfuluss
WoLfuluss
I found a way to remake all the binder without using boost rolleyes.gif
it will be better this way... I was using it just for function decomposition and calling convention detection... but now I can't automatically set the calling convention... that's bad... I'll put it as an optional addon (set by #define)

BTW... I'll keep using typeid for type name conversion. I don't really know what compilers already support it since I use only MS stuff. rolleyes.gif
WitchLord
WitchLord
I've added a link to this thread on the wiki: http://angelscript.pbworks.com, to make it easier for others to find.


I'm not a big fan of automated bindings myself, but I do recognize that they do make the code look less intimidating to beginners. I'll gladly recommend a library like this to those who prefer it.


Also, if there is anything I can add to the AngelScript library to make it easier to automatize the binding, please do let me know.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - <a href="http://www.angelcode.com/tower" rel
toukkapoukka
toukkapoukka

Also, if there is anything I can add to the AngelScript library to make it easier to automatize the binding, please do let me know.


More options for automatic reference-counting. Our project is interfacing libRocket and Angelscript and one of the problems is that we can't directly export libRocket functions because their reference-counting methods differ. libRocket returns reference-counted objects without increasing the reference so we have to write a wrapper for each of these functions that call AddReference there. Also IIRC we needed to do something like this for reference-counted elements in function parameters.

We cant use autohandles (or what was it called) because of the binding library I posted that produces automatic prototype strings from C++ function/method definitions.

BTW, the asbind.h states GPL license but that is because we use it in our GPL project, but I can relicense a version with more liberal license
WoLfuluss
WoLfuluss
Alright guys! Big news...
I've created the google code project, and the new syntax I have 100% sure you guys know... laugh.gif
I tried to keep it simple to the max... also, if there's any suggestions, please let me know. rolleyes.gif
here's the link:
https://code.google.com/p/angelbinder/
WitchLord
WitchLord
We cant use autohandles (or what was it called) because of the binding library I posted that produces automatic prototype strings from C++ function/method definitions.


Autohandles is how I would solve this. This is one of the drawbacks with autobinding; it becomes difficult to bind functions that do not follow the expected pattern.

How do you suggest solving this, if not through autohandles?
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - <a href="http://www.angelcode.com/tower" rel
WoLfuluss
WoLfuluss
WitchLord, can you provide me a list of prototype strings that angelscript parses and when it's used??
I mean something like this:


int - by value
const int - constant variable
int@ - "pointer"
int& - "reference"

jacmoe
jacmoe
BTW, the asbind.h states GPL license but that is because we use it in our GPL project, but I can relicense a version with more liberal license


MIT is GPL compatible, so you can use that.
Or - if you want to be on the safe side - dual license (like jQuery): MIT and GPL.

@WoLfuluss:
Great news! Good luck with the project!
Too many projects; too much time

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.