Sélectionner une révision Git
CRTPLuaScriptObject.hh
CRTPLuaScriptObject.hh 9,78 Kio
#pragma once
#include "LuaContext.hh"
#include "ScriptOption.hh"
#include "lua.hpp"
#include <vector>
#include <cstdio>
namespace Vivy::Script
{
// clang-format off
#define LUA_DECL_METHOD(class, name) luaL_Reg{ #name, class ::name }
#define LUA_DECL_META_METHOD(class, meta, name) luaL_Reg{ meta, class ::name }
#define LUA_DECL_CREATE(class) luaL_Reg{ "new", class ::CREATE }
#define LUA_RETURN_NOTHING(L) { lua_settop(L, 0); return 0; }
// clang-format on
#define script_class(theClassName) \
class theClassName final : public CRTPLuaScriptObject<theClassName>
#define method_list static constexpr inline auto
#define LUA_SCRIPTABLE_CLASS(theClassName) \
VIVY_UNMOVABLE_OBJECT(theClassName) \
static constexpr char className[] = #theClassName; \
friend CRTPLuaScriptObject<theClassName>; \
theClassName(lua_State *L) noexcept \
{ \
err(LuaContext::getContext(L)) \
<< "Create instance of " << theClassName::className << "\n"; \
} \
~theClassName() noexcept {}
// CRTP to expose objects to Lua
template <class Object> class CRTPLuaScriptObject {
protected:
static void IterateOverArray(lua_State *const L, const int tblIndex,
const auto callback) noexcept
{
luaL_checktype(L, tblIndex, LUA_TTABLE);
const std::size_t count = lua_rawlen(L, tblIndex);
if (count >= std::numeric_limits<int>::max())
luaL_error(L, "To many items (%lu) in table to iterate over!", count);
const int countInt = static_cast<const int>(count);
for (int i = 1; i <= countInt; ++i) {
luaL_checktype(L, tblIndex, LUA_TTABLE);
lua_pushinteger(L, i); // i -> top stack
lua_gettable(L, tblIndex); // T[i] -> top stack and pop i
if (lua_type(L, -1) == LUA_TNIL)
break; // Sentinel check
// If the callback didn't pop the object form the stack, pop
// it ourself. The value will be accessible at the top of the
// stack (index -1).
if (!callback())
lua_pop(L, -1);
}
}
static int GC(lua_State *const L) noexcept
{
const Object *const obj = reinterpret_cast<const Object *>(lua_topointer(L, 1));
auto *context = LuaContext::getContext(L);
err(context) << "Call destructor for " << Object::className << "\n";
obj->~Object();
return 0;
}