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

CRTPLuaScriptObject.hh

Blame
  • 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;
        }