I am currently working on a project that involves Lua. For convenience, I created a wrapper class for the Lua state structure. However, I also added some methods for getting globals and table fields. Since these methods are very similar, I decided do turn them into macros.
Do you consider this a good solution? Would you have done it another way?
#include <lua/lua.hpp>
#include <util/Exception.h>
#include "LuaState.h"
namespace gnaar {
LuaState::LuaState() : ls(luaL_newstate())
{
luaL_openlibs(ls);
}
void LuaState::doFile(const char* file)
{
if (luaL_dofile(ls, file) != 0)
{
throwException(lua_tostring(ls, -1));
}
}
lua_State* LuaState::operator*()
{
return ls;
}
LuaState::~LuaState()
{
lua_close(ls);
}
//==================== ugly macro stuff below, beware ====================
#define _getGlobal(_lua, _type, _check, _conversion) \
template <> \
_type LuaState::getGlobal<_type>(const char* name, _type dfault) \
{ \
lua_getglobal(_lua, name); \
if (_check(_lua, -1)) \
{ \
return (_type) _conversion(_lua, -1); \
} \
else \
{ \
return dfault; \
} \
}
#define _getTableField(_lua, _type, _check, _conversion) \
template <> _type LuaState::getTableField<_type> \
(const char* table, const char* key, _type def) \
{ \
lua_getglobal(_lua, table); \
if (!lua_istable(_lua, -1)) \
{ \
return def; \
} \
_type result; \
lua_pushstring(_lua, key); \
lua_gettable(_lua, -2); \
if (!_check(_lua, -1)) \
{ \
result = def; \
} \
else \
{ \
result = (_type) _conversion(_lua, -1); \
} \
lua_pop(_lua, 1); \
return result; \
}
_getGlobal(ls, int, lua_isnumber, lua_tonumber)
_getGlobal(ls, const char*, lua_isstring, lua_tostring)
_getGlobal(ls, bool, lua_isboolean, lua_toboolean)
_getTableField(ls, int, lua_isnumber, lua_tonumber)
_getTableField(ls, const char*, lua_isstring, lua_tostring)
_getTableField(ls, bool, lua_isboolean, lua_toboolean)
} // namespace gnaar
lua_isnumberandlua_tonumber) or (lua_isstringlua_tostring) to function templates (e.g.,lua_is<TypeHere>andlua_to<TypeHere>), you won't have to specializegetGlobalandgetTableFieldmanually/via macros and will be able to statically dispatch inside them automatically/via template-type selection. \$\endgroup\$