Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Using C++-Allocated Objects in Lua


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 SeiryuEnder   Members   -  Reputation: 199

Like
0Likes
Like

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

Edited by SeiryuEnder, 04 June 2012 - 01:06 PM.


Sponsor:

#2 FLeBlanc   Crossbones+   -  Reputation: 3117

Like
0Likes
Like

Posted 04 June 2012 - 01:55 PM

I personally use tolua++. In C++, I will implement a factory class, something like this:

class Object
{
	 public:
	 // Don't bind constructor/destructor since we want objects to be managed by a factory

	 void foo();
	 static void bar();
};

class ObjectFactory
{
    public:
    ObjectFactory();
	 ~ObjectFactory();

    Object *createObject();
    void destroyObject(Object *o);
};

Per the usage of tolua++, I'll process this header to generate the binding code. In Lua code, then, it is as simple to use as this:

factory=ObjectFactory();
object=factory:createObject();

object:foo()
object.bar()

factory:destroyObject(object)
object=nil


#3 SeiryuEnder   Members   -  Reputation: 199

Like
0Likes
Like

Posted 04 June 2012 - 02:04 PM

I personally use tolua++. In C++, I will implement a factory class, something like this:


I started out trying ToLua++ and Luabind until I found out they both use the Boost libs. Because of the bulkiness I've tried to stay away from Boost but unfortunately I may have to bite the bullet on that one... I much prefer Boost+Type Safety to no Boost+Bad Design. Your implementation looks exactly like what I wanted to do in the first place, I guess I'll back up/revert my Luna code and start working on ToLua++

Edited by SeiryuEnder, 04 June 2012 - 02:04 PM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS