Jump to content
  • 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

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!