Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Registering a C++ class for use in Lua 5.2

Tags:

c++

class

lua

So I was reading up on how to create and register a c++ class for Lua via THIS little blog tutorial.

But as simple, informative and legible as it is, it appears to be for an older version of Lua.

So some of the functions/macros are either missing or just have different signatures.

What would the following code look like in Lua C version 5.2?

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <stringstream>
#include <string>

using namespace std;

// Just a useless test class
class MyClass
{
private:
    int _X;

public:
    MyClass(int x) : _X(x) {};
    ~MyClass() { Release() };

    // Displays your number in a welcoming message box
    void Hello()
    {
        stringstream ss;
        ss << "Hello!" << endl << "Your number is: " << _X;
        string s(ss.str());
        MessageBoxA(NULL, s.c_str(), "MyClass", MB_ICONINFORMATION);
    }

    void Release() {
        //release code goes here
    }
};

// Functions that will create/destroy MyClass instances
static int newMyClass(lua_State* L)
{
    int n = lua_gettop(L); // Number of arguments
    if (n != 2)
        return luaL_error(L, "Got %d arguments, expected 2 (class, x)", n);
    // First argument is now a table that represent the class to instantiate
    luaL_checktype(L, 1, LUA_TTABLE);

    lua_newtable(L); // Create table to represent instance

    // Set first argument of new to metatable of instance
    lua_pushvalue(L, 1);
    lua_setmetatable(L, -2);

    // Do function lookups in metatable
    lua_pushvalue(L, 1);
    lua_setfield(L, 1, "__index");

    // Allocate memory for a pointer to to object
    MyClass** s = (MyClass**)lua_newuserdata(L, sizeof(MyClass*));

    int x = luaL_checknumber(L, 2);

    *s = new MyClass(x);

    luaL_getmetatable(L, "Lua.MyClass");
    lua_setmetatable(L, -2);
    lua_setfield(L, -2, "__self");

    return 1;
}

static int doSomethingMyClass(lua_State* L)
{
    MyClass* c = nullptr;
    checkUserData(L, "Lua.MyClass", c);
    c->Hello();
    return 0;
}

static int destroyMyClass(lua_State* L)
{
    MyClass* c = nullptr;
    checkUserData(L, "Lua.MyClass", c);
    c->Release();
    return 0;
}

// Functions that will show up in our Lua environment
static const luaL_Reg gMyClassFuncs[] = {
    // Creation
    { "new", newMyClass) },
    { "hello", helloMyClass },
    { NULL, NULL }
};

static const luaL_Reg gDestroyMyClassFuncs[] = {
    {"__gc", destroyMyClass},
    {NULL, NULL}
};

// Registers the class for use in Lua
void registerMyClass(lua_State *L)
{  
    // Register metatable for user data in registry
    luaL_newmetatable(L, "Lua.MyClass");
    luaL_register(L, 0, gDestroyMyClassFuncs);      
    luaL_register(L, 0, gMyClassFuncs);      
    lua_pushvalue(L, -1);
    lua_setfield(L, -2, "__index");  

    // Register the base class for instances of Sprite
    luaL_register(L, "MyClass", gSpriteFuncs);  
}


Basically, the goal here is to be able to write the following in Lua:

-- Create a new MyClass instance
local c = MyClass:new(5)
-- Show message
c:Hello() -- Should say something like "Hello! Your number is: 5"

What would I need to change in order to make this work for 5.2?

like image 523
RectangleEquals Avatar asked Jun 02 '13 04:06

RectangleEquals


1 Answers

The only function in that code that is not part of Lua 5.2 is luaL_register. You should use luaL_setfuncs instead.

You should also set the global MyClass by hand or use local MyClass=require"MyClass" in your Lua code because require no longer sets globals.

If you are embedding Lua, you can just compile it and your code with -DLUA_COMPAT_MODULE and get the 5.1 functions. But consider that now is a good time to move your code to Lua 5.2, if you plan to use this version.

like image 199
lhf Avatar answered Sep 19 '22 14:09

lhf