Scoping classes created in Lua using Luabind

172 Views Asked by At

I am aware that Lua classes can be created using the OO system that Luabind exposes to Lua:

http://www.rasterbar.com/products/luabind/docs.html#defining-classes-in-lua

class 'lua_testclass'

function lua_testclass:__init(name)
    self.name = name
end

function lua_testclass:print()
    print(self.name)
end

a = lua_testclass('example')
a:print()

However I am unable to figure out how to scope the class within another namespace so I can do the following:

a = MyScope.lua_testclass('example')
a:print()

Anyone has a idea. I do not want my classes to pollute the global namespace in Lua.

2

There are 2 best solutions below

0
Oberon On BEST ANSWER

Luabind's class function will always pollute the global table. However, you can clean up after it:

function newclass(name)
    oldglobal = _G[name]
    class(name)
    cls = _G[name]
    _G[name] = oldglobal
    return cls
end

Then you would use it like this:

MyScope.lua_testclass = newclass 'lua_testclass'

Analogous to local mod = require 'mod' you have to spell the name of the class twice, but you could easily build another function on top of this that could be used like setclass(MyScope, 'lua_testclass'), automatically putting the class into MyScope:

function setclass(scope, name) scope[name] = newclass(name) end

Disclaimer: All this code is entirely untested.

0
That Crazy Carl Guy On

I did mine a little differently, but it's generally the same concept. Mine doesn't create the class, but rather just moves it. I also implemented it on the C++ side.

To implement what I did in Lua, you would write:

function moveClass(name)
    oldGlobal = _G[name]
    _G[name] = nil
    return oldGlobal
end

To implement it in C++, you would write:

luabind::module(lua) [
    luabind::def("moveClass", +[](lua_State * lua, std::string name) {
        // In the case the class does not exist, this will just 
        // remove nil and return nil. That essentially does nothing.
        luabind::object oldGlobal = luabind::globals(lua)[name];
        luabind::globals(lua)[name] = luabind::nil;
        return oldGlobal;
    })
];

So now if you were to use that to move a class you created, you would do this:

class 'MyClass'

myTable = {}

myTable.MyClass = moveClass 'MyClass'

As an extra note, if you want the moveClass function to give an error in the case that the class you are trying to move does not exist, use luabind::type(oldGlobal) == LUA_TNIL to determine if the class existed or not.

Example:

luabind::module(lua) [
    luabind::def("moveClass", +[](lua_State * lua, std::string name) {
        luabind::object oldGlobal = luabind::globals(lua)[name];

        if (luabind::type(oldGlobal) == LUA_TNIL) {
            throw std::runtime_error("Class does not exist.");
        }

        luabind::globals(lua)[name] = luabind::nil;
        return oldGlobal;
    })
];