• Advertisement
  • entries
  • comments
  • views


Sign in to follow this  


I doubt anyone's used the original gmBind, my simple C++ binding library for GameMonkey Script. If you haven't, I'd recommend that you don't anyway as it was a pile of crap.

gmBind2 is coming along nicely and binds objects in a completely different way.

Take the example class:

class TestClass
TestClass() : m_int(900), m_string("test"), m_float(800.0f) { }

TestClass( int a_int, float a_float, const std::string &a_string ) : m_int(a_int), m_string(a_string), m_float(a_float) { }

void test_method() { std::cout << "test_method" << std::endl; }
int test_method0() { std::cout << "test_method0" << std::endl; return 100; }
int test_method1( int a_num ) { std::cout << "test_method1 " << a_num << std::endl; return a_num; }

int m_int;
float m_float;
std::string m_string;

Using the new gmBind, we bind it in a way similar to the following:-

gmMachine gm;

// define the class
Class< TestClass > gmTestClass( "TestClass" );
gmTestClass.cons( "construct" )
.cons< int, float, std::string >( "construct0" )
.var( "f", &TestClass::m_float )
.var( "i", &TestClass::m_int )
.var( "s", &TestClass::m_string )
.func( "test_method", &TestClass::test_method )
.func( "test_method0", &TestClass::test_method0 )
.func( "test_method1", &TestClass::test_method1 )

// bind it
gmTestClass.bind( &gm );

From here you can use the class within GameMonkey Scripts with ease:-

test = TestClass.construct();
// show default values
print( test.f, test.s, test.i );
// change values
test.f = 100.6;
test.s = "string";
test.i = 999;
// show changed values
print( test.f, test.s, test.i );

// Call bound methods:-
print ( test.test_method0() );
print ( test.test_method1( 700 ) );

Works a charm.

Now, the tricky part is when we start having multiple bound classes and types which then have members of exotic types. The issue here is that we need to have a way of figuring out that a type of "int", "float", "MyClass", "AnotherClass" relates to a given gmType number in the gmMachine. For this, I'm experimenting with a simple trick I found.

template< typename T >
struct TypeInfo
static size_t get_hash() { return (size_t)&TypeInfo< T >::get_hash; }

This returns the address of the get_hash() function within that templated struct. Because it's templated, we have a different address for each type we compile it with. If you do a bit more template magic, you can determine the type of a given variable:-

template< typename T >
inline size_t get_type_hash( T a ) { return TypeInfo< T >::get_hash(); }

Calling it using int i = 70; get_type_hash( i ); returns the address of the int-typed TypeInfo member. Pretty neat.

So using this method, I should, in theory, be able to correlate types within a user's program to gmType variables that GameMonkey uses.

NOTE: RTTI isn't a option here

Along with this, I have some additional features planned for gmBind2. The first is the virtual type 'namespace' (eg table) that contains a bunch of useful functions for a given type - things such as initialising a bound type from a table. In the example above, I had to set test.s, .f and .i individually. What I'm planning is the ability to do the following:-

test = TestClass.construct();

TestClass.init_object( test, { s = "test", i = 68, f = 89.4 } );

Boom, the object 'test' has now had values m_int, m_float and m_string set from script using the values contained in the table. This method would allow people to say, load values into the table from a file and then use them to init objects within script.

I also want to allow users to bind get/set methods in their classes to a given GM property. So imagine your class:-

class Test
int get_myint() const { return m_int; }
void set_myint( int a_val ) { m_int = a_val; }
int m_int;

Having a get/set method called in script is just fugly eg:

test = Test.construct();
test.set_myint( 50 );
print( test.get_myint() );

The better way would be to allow the user to specify their own get/set methods and tie it to a single property. So the following works:-

test = Test.construct();
test.myint = 50;
print( test.myint );

Much better. I'm looking into ways of doing this now. Naturally the get/set method interface would HAVE to be uniform.

Aside from this, I also want to give the user power over the operators that they can expose to GameMonkey.

There's a bunch more that's going in there, but I guess, for now, I'll leave you alone :P
Sign in to follow this  


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement