DubyaDubyaDubyaDot
DubyaDubyaDubyaDot

Reputation: 1274

Storing a reference to a Lua value in C, how can it be done?

For example, let's say I have a keyhandling interface, defined in C++ as :

class KeyBoardHandler 
{ 
public:
    virtual onKeyPressed(const KeyEventArgs& e);
    virtual onKeyReleased(const KeyEventArgs& e);
}

Now, I want to extend this to Lua, to allow Lua to take advantage and register a KeyboardHandler in script.

Here's the prototype so far.

class ScriptKeyboardHandler : public KeyboardHandler
{
public:
    ... previous methods omitted
    static void createFromScript(lua_State* L);
    bool createCppData();

private:
    ScriptKeyBoardHandler(lua_State* L);

    int mSelf;
    int mKeyPressFunc;
    int mKeyReleaseFunc;
    lua_State* mpLuaState;
}

Now, I know the implementation will go something like this:

ScriptKeyboardHandler::ScriptKeyboardHandler(lua_State* L) :
    mpState(L)
{ }

ScriptKeyboardHandler::onKeyPressed(...) { 
     // check if mKeyPressFunc is a function
     // call it, passing in mself, and the event args as params
} 

// On Key Release omitted because being similar to the key pressed

ScriptKeyboardHandler::createFromScript(lua_State* L)
{
    auto scriptKeyboardHandler = new ScriptKeyboardHandler(L);
    if (scriptKeyboardHandler->createCppData())
    {
        // set the light user data and return a reference to ourself (mSelf)
    }
}

ScriptKeyboardHandler::createCppData() 
{
    // get the constructor data (second param) and find the keyPressed and keyReleased function, store those for later usage
    // any other data within the constructor data will apply to object
}

-- Syntax of the lua code
MyScriptHandler = { }
MyScriptHandler.__index = MyScriptHandler

MyScriptHandler.onKeyPress = function(self, args)
end

handler = createScriptHandler(handler, MyScriptHandler)
registerKeyHandler(handler)

I just don't know how to find the functions when they are passed in as arguments within a table.

Am I doing this right? I hope I am, it's been a pain the ass because tolua doesn't support virtual classes easily, not ones you can derive from in script anyway.

I'm not worried about the other functions, just how do I find these variables (the key press function, etc, from my C code

Upvotes: 4

Views: 298

Answers (1)

Michael Anderson
Michael Anderson

Reputation: 73470

Here's roughly what my implementation of onKeyPressed would look like.

void ScriptKeyboardHandler::onKeyPressed()
{
   //Get the table corresponding to this object from the C registry
   lua_pushlightuserdata(mpLuaState, this);
   lua_gettable(mpLuaState,LUA_REGISTRYINDEX);

   //Now get the function to call from the object
   lua_pushstring(mpLuaState,"onKeyPress");
   lua_gettable(mpLuaState,-2);

   //Now call the function 
   lua_pushvalue(mpLuaState, -2 ); // Duplicate the self table as first argument
   //TODO: Add the other arguments
   lua_pcall(mpLuaState, 1, 0, 0 ); // TODO: You'll need some error checking here and change the 1 to represent the number of args.

   lua_pop(mpLuaState,1); //Clean up the stack

}

However you'll also need to update the constructor to store the lua object representing the handler into the registry.

Upvotes: 2

Related Questions