Skip to content
Extraits de code Groupes Projets
Sélectionner une révision Git
  • 0230e2d0251cac687db632e5e3ea5bdbf29c1203
  • master par défaut
  • script
  • new-devel
  • devel
  • timingView-edit
  • fix-mpv
7 résultats

CRTPLuaScriptObject.hh

Blame
  • CRTPLuaScriptObject.hh 6,48 Kio
    #pragma once
    
    #include "LuaContext.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_CREATE(class)       luaL_Reg{ "new", class ::CREATE }
    
    #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 *) noexcept;                         \
        ~theClassName() noexcept;
    // clang-format on
    
    // CRTP to expose objects to Lua
    template <class Object> class CRTPLuaScriptObject {
    protected:
        static int GC(lua_State *L) noexcept
        {
            const Object *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;
        }
    
        static int CREATE(lua_State *L) noexcept
        {
            Object *obj = reinterpret_cast<Object *>(lua_newuserdata(L, sizeof(Object)));
            new (obj) Object(L);
            luaL_getmetatable(L, Object::className);
            lua_setmetatable(L, -2);
            return 1;
        }
    
        static Object *CHECK(lua_State *L, int index) noexcept
        {
            luaL_checktype(L, index, LUA_TUSERDATA);
            auto *context = LuaContext::getContext(L);
            Object *obj   = reinterpret_cast<Object *>(luaL_checkudata(L, index, Object::className));
            if (obj == nullptr) {
                err(context) << "Type error, userdata is not of class " << Object::className << "\n";
                luaL_typeerror(L, index, Object::className);
            }
            return obj;
        }
    
        static inline constexpr luaL_Reg luaRegDefaultGC = { "__gc", GC };
    
    public:
        static void Register(lua_State *L) noexcept
        {
            auto *context = LuaContext::getContext(L);
    
            // Fill the method table, newclass = {}
            lua_newtable(L);
            const int methodtable = lua_gettop(L);