Jump to content

  • Log In with Google      Sign In   
  • Create Account


#ActualSeiryuEnder

Posted 04 June 2012 - 01:06 PM

Right now I'm using Luna to expose my C++ classes to Lua. The problem I'm having is that I want to allocated and manage my objects in C++, only using Lua to potentially create or manipulate them.

I'm not particularly familiar with Lua. My (rather naive) first attempt was to set up a class as per some Luna tutorials, create that class using a factory, pass that class to Lua using lua_pushlightuserdata, and create an object reference in lua to the pointer in the stack.

As it turns out, Lua doesn't know how to interpret that pointer as it defines 'objects' by metatables which a raw memory address won't have. After giving it some thought, I'm currently considering creating an interface class which contains all of my Lua functions. The constructor will accept a parameter to its target class. Because it is only an interface and doesn't contain any actual data, it doesn't cost much to instantiate it whenever a script is run and let the GC clean it up.

However, not only does this seem inefficient but I completely lose type-safety. The script could theoretically pass anything into the lua interface which can crash the program (or worse). Does anyone more experienced with C++-Lua binding know how I can achieve my original goal of handing a C++ object to lua, or have any more elegant solutions? I'll add some pseudo-code below to make my problem a bit more clear.

Current Attempt:
std::vector<GameObject*> objList;

class GameObject
{
public:
	 void DoThing() {}
	 int Do( lua_State* _state ) { DoThing(); }

	 ... insert Luna binding code
}

int CreateObject( lua_State* _state )
{
	 GameObject* obj = new GameObject();
	 objList.push_back( obj );
	 lua_pushlightuserdata( _state, (void*)obj );
	 return 1;
}


int main()
{
	 lua_State* state = luaL_newstate();
	 lua_register( state, "CreateObject", CreateObject );
	 luaL_loadfile( m_State, "DoSomething.lua" );
	 lua_pcall( state, 0, LUA_MULTRET, 0 );
	 lua_close( state );

	 return 0;
}

DoSomething.lua:
local obj = CreateObject( "LuaScript" )
obj.Do()

...This won't work because Lua doesn't know how to interpret that (void*), I incorrectly thought that it would maintain some sort of VFT-esque behavior.

The method I talked about as a potential solution would be something akin to:
class GameObject
{
public:
	 void DoThing() {}
};

class LIGameObject
{
public:
	 LIGameObject( GameObject* _target ) : m_Target(_target) {}
	 int Do( lua_State* _state ) { m_Target->DoThing(); }
	 ... insert Luna binding code
private:
	 GameObject* m_Target;
};

int CreateObject( lua_State* _state )...
int main()...

DoSomething.lua:
obj = LIGameObject( CreateObject( "LuaScript" ) )
obj.Do()

#2SeiryuEnder

Posted 04 June 2012 - 01:05 PM

Right now I'm using Luna to expose my C++ classes to Lua. The problem I'm having is that I want to allocated and manage my objects in C++, only using Lua to potentially create or manipulate them.

I'm not particularly familiar with Lua. My (rather naive) first attempt was to set up a class as per some Luna tutorials, create that class using a factory, pass that class to Lua using lua_pushlightuserdata, and create an object reference in lua to the pointer in the stack.

As it turns out, Lua doesn't know how to interpret that pointer as it defines 'objects' by metatables which a raw memory address won't have. After giving it some thought, I'm currently considering creating an interface class which contains all of my Lua functions. The constructor will accept a parameter to its target class. Because it is only an interface and doesn't contain any actual data, it doesn't cost much to instantiate it whenever a script is run and let the GC clean it up.

However, not only does this seem inefficient but I completely lose type-safety. The script could theoretically pass anything into the lua interface which can crash the program (or worse). Does anyone more experienced with C++-Lua binding know how I can achieve my original goal of handing a C++ object to lua, or have any more elegant solutions? I'll add some pseudo-code below to make my problem a bit more clear.

Current Attempt:
std::vector<GameObject*> objList;

class GameObject
{
	 void DoThing() {}
	 int Do( lua_State* _state ) { DoThing(); }

	 ... insert Luna binding code
}

int CreateObject( lua_State* _state )
{
	 GameObject* obj = new GameObject();
	 objList.push_back( obj );
	 lua_pushlightuserdata( _state, (void*)obj );
	 return 1;
}


int main()
{
	 lua_State* state = luaL_newstate();
	 lua_register( state, "CreateObject", CreateObject );
	 luaL_loadfile( m_State, "DoSomething.lua" );
	 lua_pcall( state, 0, LUA_MULTRET, 0 );
	 lua_close( state );

	 return 0;
}

DoSomething.lua:
local obj = CreateObject( "LuaScript" )
obj.Do()

...This won't work because Lua doesn't know how to interpret that (void*), I incorrectly thought that it would maintain some sort of VFT-esque behavior.

The method I talked about as a potential solution would be something akin to:
class GameObject
{
	 void DoThing() {}
};

class LIGameObject
{
public:
	 LIGameObject( GameObject* _target ) : m_Target(_target) {}
	 int Do( lua_State* _state ) { m_Target->DoThing(); }
	 ... insert Luna binding code
private:
	 GameObject* m_Target;
};

int CreateObject( lua_State* _state )...
int main()...

DoSomething.lua:
obj = LIGameObject( CreateObject( "LuaScript" ) )
obj.Do()

#1SeiryuEnder

Posted 04 June 2012 - 01:04 PM

Right now I'm using Luna to expose my C++ classes to Lua. The problem I'm having is that I want to allocated and manage my objects in C++, only using Lua to potentially create or manipulate them.

I'm not particularly familiar with Lua. My (rather naive) first attempt was to set up a class as per some Luna tutorials, create that class using a factory, pass that class to Lua using lua_pushlightuserdata, and create an object reference in lua to the pointer in the stack.

As it turns out, Lua doesn't know how to interpret that pointer as it defines 'objects' by metatables which a raw memory address won't have. After giving it some thought, I'm currently considering creating an interface class which contains all of my Lua functions. The constructor will accept a parameter to its target class. Because it is only an interface and doesn't contain any actual data, it doesn't cost much to instantiate it whenever a script is run and let the GC clean it up.

However, not only does this seem inefficient but I completely lose type-safety. The script could theoretically pass anything into the lua interface which can crash the program (or worse). Does anyone more experienced with C++-Lua binding know how I can achieve my original goal of handing a C++ object to lua, or having any more elegant solutions? I'll add some pseudo-code below to make my problem a bit more clear.

Current Attempt:
std::vector<GameObject*> objList;

class GameObject
{
	 void DoThing() {}
	 int Do( lua_State* _state ) { DoThing(); }

	 ... insert Luna binding code
}

int CreateObject( lua_State* _state )
{
	 GameObject* obj = new GameObject();
	 objList.push_back( obj );
	 lua_pushlightuserdata( _state, (void*)obj );
	 return 1;
}


int main()
{
	 lua_State* state = luaL_newstate();
	 lua_register( state, "CreateObject", CreateObject );
	 luaL_loadfile( m_State, "DoSomething.lua" );
	 lua_pcall( state, 0, LUA_MULTRET, 0 );
	 lua_close( state );

	 return 0;
}

DoSomething.lua:
local obj = CreateObject( "LuaScript" )
obj.Do()

...This won't work because Lua doesn't know how to interpret that (void*), I incorrectly thought that it would maintain some sort of VFT-esque behavior.

The method I talked about as a potential solution would be something akin to:
class GameObject
{
	 void DoThing() {}
};

class LIGameObject
{
public:
	 LIGameObject( GameObject* _target ) : m_Target(_target) {}
	 int Do( lua_State* _state ) { m_Target->DoThing(); }
	 ... insert Luna binding code
private:
	 GameObject* m_Target;
};

int CreateObject( lua_State* _state )...
int main()...

DoSomething.lua:
obj = LIGameObject( CreateObject( "LuaScript" ) )
obj.Do()

PARTNERS