AngelScript <-> C++ binder class.

Started by
45 comments, last by NickGalko 10 years, 4 months ago
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/
Advertisement
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.
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 &in, &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 - Tower - free puzzle game

[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 &in, &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?
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 - Tower - free puzzle game

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?

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)
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


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. :)
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. :D

<edit>
License?
</edit>

Too many projects; too much time

This topic is closed to new replies.

Advertisement