gmod-lcpu/native/projects/lcpu/src/LuaHelpers.hpp

66 lines
2.9 KiB
C++

//! Helpers for lua binding
#pragma once
#include <GarrysMod/Lua/Interface.h>
#include <lucore/Logger.hpp>
// These are like the official GMOD header LUA_FUNCTION but allow forward declaration
// and implementation inside of classes, making writing class bindings that much less
// of a PITA. Nifty!
#define LUA_MEMBER_FUNCTION(FUNC) \
static int FUNC##__ImpStatic(GarrysMod::Lua::ILuaBase* LUA); \
static int FUNC(lua_State* L) { \
GarrysMod::Lua::ILuaBase* LUA = L->luabase; \
LUA->SetState(L); \
return FUNC##__ImpStatic(LUA); \
}
#define LUA_MEMBER_FUNCTION_IMPLEMENT(CLASS, FUNC) int CLASS::FUNC##__ImpStatic(GarrysMod::Lua::ILuaBase* LUA)
// will make a "self" variable with the class
#define LUA_CLASS_GET(T, name, stackPos) \
LUA->CheckType(stackPos, T::__lua_typeid); \
auto name = LUA->GetUserType<T>(stackPos, T::__lua_typeid); \
if(!name) { \
LUA->ThrowError("nullptr " #T " passed to function which requires a valid instance"); \
}
#define LUA_CLASS_BIND_VARIABLES(ACCESS_LEVEL) \
public: \
static int __lua_typeid; \
ACCESS_LEVEL: \
LUA_MEMBER_FUNCTION(__gc);
#define LUA_CLASS_BIND_VARIABLES_IMPLEMENT(T) \
int T::__lua_typeid = 0; \
LUA_MEMBER_FUNCTION_IMPLEMENT(T, __gc) { \
LUA->CheckType(1, T::__lua_typeid); \
auto self = LUA->GetUserType<T>(1, T::__lua_typeid); \
if(self != nullptr) { /* GetUserType returns nullptr on failure */ \
lucore::LogInfo("GCing {} object", #T); \
delete self; \
} \
return 0; \
}
#define LUA_CLASS_BIND_BEGIN(T) \
T::__lua_typeid = LUA->CreateMetaTable(#T); \
LUA->PushSpecial(GarrysMod::Lua::SPECIAL_REG); \
LUA->PushNumber(T::__lua_typeid); \
LUA->SetField(-2, #T "__typeid"); \
LUA->Pop(); /* pop registry */ \
LUA->Push(-1); \
LUA->SetField(-2, "__index"); \
LUA_SET_C_FUNCTION(__gc)
#define LUA_CLASS_BIND_END() LUA->Pop();
// Helpers for lua functions
#define LUA_SET_C_FUNCTION(name) \
LUA->PushCFunction(name); \
LUA->SetField(-2, #name);
#define LUA_SET_C_FUNCTION_NAME(name, altName) \
LUA->PushCFunction(name); \
LUA->SetField(-2, altName);