/* * This file is part of OpenTTD. * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . */ /** @file squirrel_helper.hpp declarations and parts of the implementation of the class for convert code */ #ifndef SQUIRREL_HELPER_HPP #define SQUIRREL_HELPER_HPP #include "squirrel.hpp" #include "../core/smallvec_type.hpp" #include "../economy_type.h" #include "../string_func.h" #include "squirrel_helper_type.hpp" template const char *GetClassName(); /** * The Squirrel convert routines */ namespace SQConvert { /** * Pointers assigned to this class will be free'd when this instance * comes out of scope. Useful to make sure you can use stredup(), * without leaking memory. */ struct SQAutoFreePointers : std::vector { ~SQAutoFreePointers() { for (void * p : *this) free(p); } }; template struct YesT { static const bool Yes = Y; static const bool No = !Y; }; /** * Helper class to recognize if the given type is void. Usage: 'IsVoidT::Yes' */ template struct IsVoidT : YesT {}; template <> struct IsVoidT : YesT {}; /** * Helper class to recognize if the function/method return type is void. */ template struct HasVoidReturnT; /* functions */ template struct HasVoidReturnT : IsVoidT {}; template struct HasVoidReturnT : IsVoidT {}; template struct HasVoidReturnT : IsVoidT {}; template struct HasVoidReturnT : IsVoidT {}; template struct HasVoidReturnT : IsVoidT {}; template struct HasVoidReturnT : IsVoidT {}; template struct HasVoidReturnT : IsVoidT {}; /* methods */ template struct HasVoidReturnT : IsVoidT {}; template struct HasVoidReturnT : IsVoidT {}; template struct HasVoidReturnT : IsVoidT {}; template struct HasVoidReturnT : IsVoidT {}; template struct HasVoidReturnT : IsVoidT {}; template struct HasVoidReturnT : IsVoidT {}; template struct HasVoidReturnT : IsVoidT {}; /** * Special class to make it possible for the compiler to pick the correct GetParam(). */ template class ForceType { }; /** * To return a value to squirrel, we call this function. It converts to the right format. */ template static int Return(HSQUIRRELVM vm, T t); template <> inline int Return (HSQUIRRELVM vm, uint8 res) { sq_pushinteger(vm, (int32)res); return 1; } template <> inline int Return (HSQUIRRELVM vm, uint16 res) { sq_pushinteger(vm, (int32)res); return 1; } template <> inline int Return (HSQUIRRELVM vm, uint32 res) { sq_pushinteger(vm, (int32)res); return 1; } template <> inline int Return (HSQUIRRELVM vm, int8 res) { sq_pushinteger(vm, res); return 1; } template <> inline int Return (HSQUIRRELVM vm, int16 res) { sq_pushinteger(vm, res); return 1; } template <> inline int Return (HSQUIRRELVM vm, int32 res) { sq_pushinteger(vm, res); return 1; } template <> inline int Return (HSQUIRRELVM vm, int64 res) { sq_pushinteger(vm, res); return 1; } template <> inline int Return (HSQUIRRELVM vm, Money res) { sq_pushinteger(vm, res); return 1; } template <> inline int Return (HSQUIRRELVM vm, bool res) { sq_pushbool (vm, res); return 1; } template <> inline int Return (HSQUIRRELVM vm, char *res) { if (res == nullptr) sq_pushnull(vm); else { sq_pushstring(vm, res, -1); free(res); } return 1; } template <> inline int Return(HSQUIRRELVM vm, const char *res) { if (res == nullptr) sq_pushnull(vm); else { sq_pushstring(vm, res, -1); } return 1; } template <> inline int Return (HSQUIRRELVM vm, void *res) { sq_pushuserpointer(vm, res); return 1; } template <> inline int Return (HSQUIRRELVM vm, HSQOBJECT res) { sq_pushobject(vm, res); return 1; } /** * To get a param from squirrel, we call this function. It converts to the right format. */ template static T GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr); template <> inline uint8 GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; } template <> inline uint16 GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; } template <> inline uint32 GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; } template <> inline int8 GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; } template <> inline int16 GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; } template <> inline int32 GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; } template <> inline int64 GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; } template <> inline Money GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; } template <> inline bool GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQBool tmp; sq_getbool (vm, index, &tmp); return tmp != 0; } template <> inline void *GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer tmp; sq_getuserpointer(vm, index, &tmp); return tmp; } template <> inline const char *GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { /* Convert what-ever there is as parameter to a string */ sq_tostring(vm, index); const SQChar *tmp; sq_getstring(vm, -1, &tmp); char *tmp_str = stredup(tmp); sq_poptop(vm); ptr->push_back((void *)tmp_str); StrMakeValidInPlace(tmp_str); return tmp_str; } template <> inline Array *GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { /* Sanity check of the size. */ if (sq_getsize(vm, index) > UINT16_MAX) throw sq_throwerror(vm, "an array used as parameter to a function is too large"); SQObject obj; sq_getstackobj(vm, index, &obj); sq_pushobject(vm, obj); sq_pushnull(vm); std::vector data; while (SQ_SUCCEEDED(sq_next(vm, -2))) { SQInteger tmp; if (SQ_SUCCEEDED(sq_getinteger(vm, -1, &tmp))) { data.push_back((int32)tmp); } else { sq_pop(vm, 4); throw sq_throwerror(vm, "a member of an array used as parameter to a function is not numeric"); } sq_pop(vm, 2); } sq_pop(vm, 2); Array *arr = (Array*)MallocT(sizeof(Array) + sizeof(int32) * data.size()); arr->size = data.size(); memcpy(arr->array, data.data(), sizeof(int32) * data.size()); ptr->push_back(arr); return arr; } /** * Helper class to recognize the function type (retval type, args) and use the proper specialization * for SQ callback. The partial specializations for the second arg (Tis_void_retval) are not possible * on the function. Therefore the class is used instead. */ template ::Yes> struct HelperT; /** * The real C++ caller for function with return value and 0 params. */ template struct HelperT { static int SQCall(void *instance, Tretval (*func)(), HSQUIRRELVM vm) { return Return(vm, (*func)()); } }; /** * The real C++ caller for function with no return value and 0 params. */ template struct HelperT { static int SQCall(void *instance, Tretval (*func)(), HSQUIRRELVM vm) { (*func)(); return 0; } }; /** * The real C++ caller for method with return value and 0 params. */ template struct HelperT { static int SQCall(Tcls *instance, Tretval (Tcls::*func)(), HSQUIRRELVM vm) { return Return(vm, (instance->*func)()); } }; /** * The real C++ caller for method with no return value and 0 params. */ template struct HelperT { static int SQCall(Tcls *instance, Tretval (Tcls::*func)(), HSQUIRRELVM vm) { (instance->*func)(); return 0; } static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(), HSQUIRRELVM vm) { return new Tcls(); } }; /** * The real C++ caller for function with return value and 1 param. */ template struct HelperT { static int SQCall(void *instance, Tretval (*func)(Targ1), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tretval ret = (*func)( GetParam(ForceType(), vm, 2, &ptr) ); return Return(vm, ret); } }; /** * The real C++ caller for function with no return value and 1 param. */ template struct HelperT { static int SQCall(void *instance, Tretval (*func)(Targ1), HSQUIRRELVM vm) { SQAutoFreePointers ptr; (*func)( GetParam(ForceType(), vm, 2, &ptr) ); return 0; } }; /** * The real C++ caller for method with return value and 1 param. */ template struct HelperT { static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tretval ret = (instance->*func)( GetParam(ForceType(), vm, 2, &ptr) ); return Return(vm, ret); } }; /** * The real C++ caller for method with no return value and 1 param. */ template struct HelperT { static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1), HSQUIRRELVM vm) { SQAutoFreePointers ptr; (instance->*func)( GetParam(ForceType(), vm, 2, &ptr) ); return 0; } static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tcls *inst = new Tcls( GetParam(ForceType(), vm, 2, &ptr) ); return inst; } }; /** * The real C++ caller for function with return value and 2 params. */ template struct HelperT { static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tretval ret = (*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr) ); return Return(vm, ret); } }; /** * The real C++ caller for function with no return value and 2 params. */ template struct HelperT { static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2), HSQUIRRELVM vm) { SQAutoFreePointers ptr; (*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr) ); return 0; } }; /** * The real C++ caller for method with return value and 2 params. */ template struct HelperT { static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tretval ret = (instance->*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr) ); return Return(vm, ret); } }; /** * The real C++ caller for method with no return value and 2 params. */ template struct HelperT { static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2), HSQUIRRELVM vm) { SQAutoFreePointers ptr; (instance->*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr) ); return 0; } static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tcls *inst = new Tcls( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr) ); return inst; } }; /** * The real C++ caller for function with return value and 3 params. */ template struct HelperT { static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tretval ret = (*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr) ); return Return(vm, ret); } }; /** * The real C++ caller for function with no return value and 3 params. */ template struct HelperT { static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm) { SQAutoFreePointers ptr; (*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr) ); return 0; } }; /** * The real C++ caller for method with return value and 3 params. */ template struct HelperT { static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tretval ret = (instance->*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr) ); return Return(vm, ret); } }; /** * The real C++ caller for method with no return value and 3 params. */ template struct HelperT { static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm) { SQAutoFreePointers ptr; (instance->*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr) ); return 0; } static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tcls *inst = new Tcls( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr) ); return inst; } }; /** * The real C++ caller for function with return value and 4 params. */ template struct HelperT { static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tretval ret = (*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr) ); return Return(vm, ret); } }; /** * The real C++ caller for function with no return value and 4 params. */ template struct HelperT { static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm) { SQAutoFreePointers ptr; (*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr) ); return 0; } }; /** * The real C++ caller for method with return value and 4 params. */ template struct HelperT { static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tretval ret = (instance->*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr) ); return Return(vm, ret); } }; /** * The real C++ caller for method with no return value and 4 params. */ template struct HelperT { static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm) { SQAutoFreePointers ptr; (instance->*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr) ); return 0; } static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tcls *inst = new Tcls( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr) ); return inst; } }; /** * The real C++ caller for function with return value and 5 params. */ template struct HelperT { static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tretval ret = (*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr), GetParam(ForceType(), vm, 6, &ptr) ); return Return(vm, ret); } }; /** * The real C++ caller for function with no return value and 5 params. */ template struct HelperT { static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm) { SQAutoFreePointers ptr; (*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr), GetParam(ForceType(), vm, 6, &ptr) ); return 0; } }; /** * The real C++ caller for method with return value and 5 params. */ template struct HelperT { static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tretval ret = (instance->*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr), GetParam(ForceType(), vm, 6, &ptr) ); return Return(vm, ret); } }; /** * The real C++ caller for method with no return value and 5 params. */ template struct HelperT { static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm) { SQAutoFreePointers ptr; (instance->*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr), GetParam(ForceType(), vm, 6, &ptr) ); return 0; } static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tcls *inst = new Tcls( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr), GetParam(ForceType(), vm, 6, &ptr) ); return inst; } }; /** * The real C++ caller for function with return value and 10 params. */ template struct HelperT { static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tretval ret = (*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr), GetParam(ForceType(), vm, 6, &ptr), GetParam(ForceType(), vm, 7, &ptr), GetParam(ForceType(), vm, 8, &ptr), GetParam(ForceType(), vm, 9, &ptr), GetParam(ForceType(), vm, 10, &ptr), GetParam(ForceType(), vm, 11, &ptr) ); return Return(vm, ret); } }; /** * The real C++ caller for function with no return value and 10 params. */ template struct HelperT { static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm) { SQAutoFreePointers ptr; (*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr), GetParam(ForceType(), vm, 6, &ptr), GetParam(ForceType(), vm, 7, &ptr), GetParam(ForceType(), vm, 8, &ptr), GetParam(ForceType(), vm, 9, &ptr), GetParam(ForceType(), vm, 10, &ptr), GetParam(ForceType(), vm, 11, &ptr) ); return 0; } }; /** * The real C++ caller for method with return value and 10 params. */ template struct HelperT { static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tretval ret = (instance->*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr), GetParam(ForceType(), vm, 6, &ptr), GetParam(ForceType(), vm, 7, &ptr), GetParam(ForceType(), vm, 8, &ptr), GetParam(ForceType(), vm, 9, &ptr), GetParam(ForceType(), vm, 10, &ptr), GetParam(ForceType(), vm, 11, &ptr) ); return Return(vm, ret); } }; /** * The real C++ caller for method with no return value and 10 params. */ template struct HelperT { static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm) { SQAutoFreePointers ptr; (instance->*func)( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr), GetParam(ForceType(), vm, 6, &ptr), GetParam(ForceType(), vm, 7, &ptr), GetParam(ForceType(), vm, 8, &ptr), GetParam(ForceType(), vm, 9, &ptr), GetParam(ForceType(), vm, 10, &ptr), GetParam(ForceType(), vm, 11, &ptr) ); return 0; } static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm) { SQAutoFreePointers ptr; Tcls *inst = new Tcls( GetParam(ForceType(), vm, 2, &ptr), GetParam(ForceType(), vm, 3, &ptr), GetParam(ForceType(), vm, 4, &ptr), GetParam(ForceType(), vm, 5, &ptr), GetParam(ForceType(), vm, 6, &ptr), GetParam(ForceType(), vm, 7, &ptr), GetParam(ForceType(), vm, 8, &ptr), GetParam(ForceType(), vm, 9, &ptr), GetParam(ForceType(), vm, 10, &ptr), GetParam(ForceType(), vm, 11, &ptr) ); return inst; } }; /** * A general template for all non-static method callbacks from Squirrel. * In here the function_proc is recovered, and the SQCall is called that * can handle this exact amount of params. */ template inline SQInteger DefSQNonStaticCallback(HSQUIRRELVM vm) { /* Find the amount of params we got */ int nparam = sq_gettop(vm); SQUserPointer ptr = nullptr; SQUserPointer real_instance = nullptr; HSQOBJECT instance; /* Get the 'SQ' instance of this class */ Squirrel::GetInstance(vm, &instance); /* Protect against calls to a non-static method in a static way */ sq_pushroottable(vm); const char *className = GetClassName(); sq_pushstring(vm, className, -1); sq_get(vm, -2); sq_pushobject(vm, instance); if (sq_instanceof(vm) != SQTrue) return sq_throwerror(vm, "class method is non-static"); sq_pop(vm, 3); /* Get the 'real' instance of this class */ sq_getinstanceup(vm, 1, &real_instance, nullptr); /* Get the real function pointer */ sq_getuserdata(vm, nparam, &ptr, nullptr); if (real_instance == nullptr) return sq_throwerror(vm, "couldn't detect real instance of class for non-static call"); /* Remove the userdata from the stack */ sq_pop(vm, 1); try { /* Delegate it to a template that can handle this specific function */ return HelperT::SQCall((Tcls *)real_instance, *(Tmethod *)ptr, vm); } catch (SQInteger &e) { return e; } } /** * A general template for all non-static advanced method callbacks from Squirrel. * In here the function_proc is recovered, and the SQCall is called that * can handle this exact amount of params. */ template inline SQInteger DefSQAdvancedNonStaticCallback(HSQUIRRELVM vm) { /* Find the amount of params we got */ int nparam = sq_gettop(vm); SQUserPointer ptr = nullptr; SQUserPointer real_instance = nullptr; HSQOBJECT instance; /* Get the 'SQ' instance of this class */ Squirrel::GetInstance(vm, &instance); /* Protect against calls to a non-static method in a static way */ sq_pushroottable(vm); const char *className = GetClassName(); sq_pushstring(vm, className, -1); sq_get(vm, -2); sq_pushobject(vm, instance); if (sq_instanceof(vm) != SQTrue) return sq_throwerror(vm, "class method is non-static"); sq_pop(vm, 3); /* Get the 'real' instance of this class */ sq_getinstanceup(vm, 1, &real_instance, nullptr); /* Get the real function pointer */ sq_getuserdata(vm, nparam, &ptr, nullptr); if (real_instance == nullptr) return sq_throwerror(vm, "couldn't detect real instance of class for non-static call"); /* Remove the userdata from the stack */ sq_pop(vm, 1); /* Call the function, which its only param is always the VM */ return (SQInteger)(((Tcls *)real_instance)->*(*(Tmethod *)ptr))(vm); } /** * A general template for all function/static method callbacks from Squirrel. * In here the function_proc is recovered, and the SQCall is called that * can handle this exact amount of params. */ template inline SQInteger DefSQStaticCallback(HSQUIRRELVM vm) { /* Find the amount of params we got */ int nparam = sq_gettop(vm); SQUserPointer ptr = nullptr; /* Get the real function pointer */ sq_getuserdata(vm, nparam, &ptr, nullptr); try { /* Delegate it to a template that can handle this specific function */ return HelperT::SQCall((Tcls *)nullptr, *(Tmethod *)ptr, vm); } catch (SQInteger &e) { return e; } } /** * A general template for all static advanced method callbacks from Squirrel. * In here the function_proc is recovered, and the SQCall is called that * can handle this exact amount of params. */ template inline SQInteger DefSQAdvancedStaticCallback(HSQUIRRELVM vm) { /* Find the amount of params we got */ int nparam = sq_gettop(vm); SQUserPointer ptr = nullptr; /* Get the real function pointer */ sq_getuserdata(vm, nparam, &ptr, nullptr); /* Remove the userdata from the stack */ sq_pop(vm, 1); /* Call the function, which its only param is always the VM */ return (SQInteger)(*(*(Tmethod *)ptr))(vm); } /** * A general template for the destructor of SQ instances. This is needed * here as it has to be in the same scope as DefSQConstructorCallback. */ template static SQInteger DefSQDestructorCallback(SQUserPointer p, SQInteger size) { /* Remove the real instance too */ if (p != nullptr) ((Tcls *)p)->Release(); return 0; } /** * A general template to handle creating of instance with any amount of * params. It creates the instance in C++, and it sets all the needed * settings in SQ to register the instance. */ template inline SQInteger DefSQConstructorCallback(HSQUIRRELVM vm) { try { /* Create the real instance */ Tcls *instance = HelperT::SQConstruct((Tcls *)nullptr, (Tmethod)nullptr, vm); sq_setinstanceup(vm, -Tnparam, instance); sq_setreleasehook(vm, -Tnparam, DefSQDestructorCallback); instance->AddRef(); return 0; } catch (SQInteger &e) { return e; } } /** * A general template to handle creating of an instance with a complex * constructor. */ template inline SQInteger DefSQAdvancedConstructorCallback(HSQUIRRELVM vm) { try { /* Find the amount of params we got */ int nparam = sq_gettop(vm); /* Create the real instance */ Tcls *instance = new Tcls(vm); sq_setinstanceup(vm, -nparam, instance); sq_setreleasehook(vm, -nparam, DefSQDestructorCallback); instance->AddRef(); return 0; } catch (SQInteger &e) { return e; } } } // namespace SQConvert #endif /* SQUIRREL_HELPER_HPP */