123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462 |
- /*
- * Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
- #ifndef LUAINTERFACE_H
- #define LUAINTERFACE_H
-
- #include "declarations.h"
-
- struct lua_State;
- typedef int (*LuaCFunction) (lua_State *L);
-
- /// Class that manages LUA stuff
- class LuaInterface
- {
- public:
- LuaInterface();
- ~LuaInterface();
-
- void init();
- void terminate();
-
- /// Register core script functions
- void registerFunctions();
-
- // functions that will register all script stuff in lua global environment
- void registerSingletonClass(const std::string& className);
- void registerClass(const std::string& className, const std::string& baseClass = "LuaObject");
-
- void registerClassStaticFunction(const std::string& className,
- const std::string& functionName,
- const LuaCppFunction& function);
-
- void registerClassMemberFunction(const std::string& className,
- const std::string& functionName,
- const LuaCppFunction& function);
-
- void registerClassMemberField(const std::string& className,
- const std::string& field,
- const LuaCppFunction& getFunction,
- const LuaCppFunction& setFunction);
-
- void registerGlobalFunction(const std::string& functionName,
- const LuaCppFunction& function);
-
- // register shortcuts using templates
- template<class C, class B = LuaObject>
- void registerClass() {
- registerClass(stdext::demangle_type<C>(), stdext::demangle_type<B>());
- }
-
- template<class C>
- void registerClassStaticFunction(const std::string& functionName, const LuaCppFunction& function) {
- registerClassStaticFunction(stdext::demangle_type<C>(), functionName, function);
- }
-
- template<class C>
- void registerClassMemberFunction(const std::string& functionName, const LuaCppFunction& function) {
- registerClassMemberFunction(stdext::demangle_type<C>(), functionName, function);
- }
-
- template<class C>
- void registerClassMemberField(const std::string& field,
- const LuaCppFunction& getFunction,
- const LuaCppFunction& setFunction) {
- registerClassMemberField(stdext::demangle_type<C>(), field, getFunction, setFunction);
- }
-
- // methods for binding functions
- template<class C, typename F>
- void bindSingletonFunction(const std::string& functionName, F C::*function, C *instance);
- template<class C, typename F>
- void bindSingletonFunction(const std::string& className, const std::string& functionName, F C::*function, C *instance);
-
- template<class C, typename F>
- void bindClassStaticFunction(const std::string& functionName, const F& function);
- template<typename F>
- void bindClassStaticFunction(const std::string& className, const std::string& functionName, const F& function);
-
- template<class C, typename F, class FC>
- void bindClassMemberFunction(const std::string& functionName, F FC::*function);
- template<class C, typename F, class FC>
- void bindClassMemberFunction(const std::string& className, const std::string& functionName, F FC::*function);
-
- template<class C, typename F1, typename F2, class FC>
- void bindClassMemberField(const std::string& fieldName, F1 FC::*getFunction, F2 FC::*setFunction);
- template<class C, typename F1, typename F2, class FC>
- void bindClassMemberField(const std::string& className, const std::string& fieldName, F1 FC::*getFunction, F2 FC::*setFunction);
-
- template<class C, typename F, class FC>
- void bindClassMemberGetField(const std::string& fieldName, F FC::*getFunction);
- template<class C, typename F, class FC>
- void bindClassMemberGetField(const std::string& className, const std::string& fieldName, F FC::*getFunction);
-
- template<class C, typename F, class FC>
- void bindClassMemberSetField(const std::string& fieldName, F FC::*setFunction);
- template<class C, typename F, class FC>
- void bindClassMemberSetField(const std::string& className, const std::string& fieldName, F FC::*setFunction);
-
- template<typename F>
- void bindGlobalFunction(const std::string& functionName, const F& function);
-
- private:
- /// Metamethod that will retrieve fields values (that include functions) from the object when using '.' or ':'
- static int luaObjectGetEvent(LuaInterface* lua);
- /// Metamethod that is called when setting a field of the object by using the keyword '='
- static int luaObjectSetEvent(LuaInterface* lua);
- /// Metamethod that will check equality of objects by using the keyword '=='
- static int luaObjectEqualEvent(LuaInterface* lua);
- /// Metamethod that is called every two lua garbage collections
- /// for any LuaObject that have no references left in lua environment
- /// anymore, thus this creates the possibility of holding an object
- /// existence by lua until it got no references left
- static int luaObjectCollectEvent(LuaInterface* lua);
-
- public:
- /// Loads and runs a script, any errors are printed to stdout and returns false
- bool safeRunScript(const std::string& fileName);
-
- /// Loads and runs a script
- /// @exception LuaException is thrown on any lua error
- void runScript(const std::string& fileName);
-
- /// Loads and runs the script from buffer
- /// @exception LuaException is thrown on any lua error
- void runBuffer(const std::string& buffer, const std::string& source);
-
- /// Loads a script file and pushes it's main function onto stack,
- /// @exception LuaException is thrown on any lua error
- void loadScript(const std::string& fileName);
-
- /// Loads a function from buffer and pushes it onto stack,
- /// @exception LuaException is thrown on any lua error
- void loadFunction(const std::string& buffer, const std::string& source = "lua function buffer");
-
- /// Evaluates a lua expression and pushes the result value onto the stack
- /// @exception LuaException is thrown on any lua error
- void evaluateExpression(const std::string& expression, const std::string& source = "lua expression");
-
- /// Generates a traceback message for the current call stack
- /// @param errorMessage is an additional error message
- /// @param level is the level of the traceback, 0 means trace from calling function
- /// @return the generated traceback message
- std::string traceback(const std::string& errorMessage = "", int level = 0);
-
- /// Throw a lua error if inside a lua call or generates an C++ stdext::exception
- /// @param message is the error message wich will be displayed before the error traceback
- /// @exception stdext::exception is thrown with the error message if the error is not captured by lua
- void throwError(const std::string& message);
-
- /// Searches for the source of the current running function
- std::string getCurrentSourcePath(int level = 0);
-
- /// @brief Calls a function
- /// The function and arguments must be on top of the stack in order,
- /// results are pushed onto the stack.
- /// @exception LuaException is thrown on any lua error
- /// @return number of results
- int safeCall(int numArgs = 0, int numRets = -1);
-
- /// Same as safeCall but catches exceptions and can also calls a table of functions,
- /// if any error occurs it will be reported to stdout and returns 0 results
- /// @param requestedResults is the number of results requested to pushes onto the stack,
- /// if supplied, the call will always pushes that number of results, even if it fails
- int signalCall(int numArgs = 0, int numRets = -1);
-
- /// @brief Creates a new environment table
- /// The new environment table is redirected to the global environment (aka _G),
- /// this allows to access global variables from _G in the new environment and
- /// prevents new variables in this new environment to be set on the global environment
- int newSandboxEnv();
-
- template<typename... T>
- int luaCallGlobalField(const std::string& global, const std::string& field, const T&... args);
-
- template<typename... T>
- void callGlobalField(const std::string& global, const std::string& field, const T&... args);
-
- template<typename R, typename... T>
- R callGlobalField(const std::string& global, const std::string& field, const T&... args);
-
- bool isInCppCallback() { return m_cppCallbackDepth != 0; }
-
- private:
- /// Load scripts requested by lua 'require'
- static int luaScriptLoader(lua_State* L);
- /// Run scripts requested by lua 'dofile'
- static int lua_dofile(lua_State* L);
- /// Run scripts requested by lua 'dofiles'
- static int lua_dofiles(lua_State* L);
- /// Run scripts requested by lua 'dofiles'
- static int lua_loadfile(lua_State* L);
- /// Handle lua errors from safeCall
- static int luaErrorHandler(lua_State* L);
- /// Handle bound cpp functions callbacks
- static int luaCppFunctionCallback(lua_State* L);
- /// Collect bound cpp function pointers
- static int luaCollectCppFunction(lua_State* L);
-
- public:
- void createLuaState();
- void closeLuaState();
-
- void collectGarbage();
-
- void loadBuffer(const std::string& buffer, const std::string& source);
-
- int pcall(int numArgs = 0, int numRets = 0, int errorFuncIndex = 0);
- void call(int numArgs = 0, int numRets = 0);
- void error();
-
- int ref();
- int weakRef();
- void unref(int ref);
- void useValue() { pushValue(); ref(); }
-
- const char* typeName(int index = -1);
- std::string functionSourcePath();
-
- void insert(int index);
- void remove(int index);
- bool next(int index = -2);
-
- void checkStack() { assert(getTop() <= 20); }
- void getStackFunction(int level = 0);
-
- void getRef(int ref);
- void getWeakRef(int weakRef);
-
- int getGlobalEnvironment() { return m_globalEnv; }
- void setGlobalEnvironment(int env);
- void resetGlobalEnvironment() { setGlobalEnvironment(m_globalEnv); }
-
- void setMetatable(int index = -2);
- void getMetatable(int index = -1);
-
- void getField(const char* key, int index = -1);
- void getField(const std::string& key, int index = -1) { return getField(key.c_str(), index); }
- void setField(const char* key, int index = -2);
- void setField(const std::string& key, int index = -2) { return setField(key.c_str(), index); }
-
- void getTable(int index = -2);
- void setTable(int index = -3);
- void clearTable(int index = -1);
-
- void getEnv(int index = -1);
- void setEnv(int index = -2);
-
- void getGlobal(const std::string& key);
- void getGlobalField(const std::string& globalKey, const std::string& fieldKey);
- void setGlobal(const std::string& key);
-
- void rawGet(int index = -1);
- void rawGeti(int n, int index = -1);
- void rawSet(int index = -3);
- void rawSeti(int n, int index = -2);
-
- void newTable();
- void* newUserdata(int size);
-
- void pop(int n = 1);
- long popInteger();
- double popNumber();
- bool popBoolean();
- std::string popString();
- void* popUserdata();
- void* popUpvalueUserdata();
- LuaObjectPtr popObject();
-
- void pushNil();
- void pushInteger(long v);
- void pushNumber(double v);
- void pushBoolean(bool v);
- void pushCString(const char* v);
- void pushString(const std::string& v);
- void pushLightUserdata(void* p);
- void pushThread();
- void pushValue(int index = -1);
- void pushObject(const LuaObjectPtr& obj);
- void pushCFunction(LuaCFunction func, int n = 0);
- void pushCppFunction(const LuaCppFunction& func);
-
- bool isNil(int index = -1);
- bool isBoolean(int index = -1);
- bool isNumber(int index = -1);
- bool isString(int index = -1);
- bool isTable(int index = -1);
- bool isFunction(int index = -1);
- bool isCFunction(int index = -1);
- bool isLuaFunction(int index = -1) { return (isFunction() && !isCFunction()); }
- bool isUserdata(int index = -1);
-
- bool toBoolean(int index = -1);
- int toInteger(int index = -1);
- double toNumber(int index = -1);
- const char* toCString(int index = -1);
- std::string toString(int index = -1);
- void* toUserdata(int index = -1);
- LuaObjectPtr toObject(int index = -1);
-
- int getTop();
- int stackSize() { return getTop(); }
- void clearStack() { pop(stackSize()); }
- bool hasIndex(int index) { return (stackSize() >= (index < 0 ? -index : index) && index != 0); }
-
- void loadFiles(std::string directory, bool recursive = false, std::string contains = "");
-
- /// Pushes any type onto the stack
- template<typename T, typename... Args>
- int polymorphicPush(const T& v, const Args&... args);
- int polymorphicPush() { return 0; }
-
- /// Casts a value from stack to any type
- /// @exception LuaBadValueCastException thrown if the cast fails
- template<class T>
- T castValue(int index = -1);
-
- /// Same as castValue but also pops
- template<class T>
- T polymorphicPop() { T v = castValue<T>(); pop(1); return v; }
-
- private:
- lua_State* L;
- int m_weakTableRef;
- int m_cppCallbackDepth;
- int m_totalObjRefs;
- int m_totalFuncRefs;
- int m_globalEnv;
- };
-
- extern LuaInterface g_lua;
-
- // must be included after, because they need LuaInterface fully declared
- #include "luaexception.h"
- #include "luabinder.h"
- #include "luavaluecasts.h"
-
- template<typename T, typename... Args>
- int LuaInterface::polymorphicPush(const T& v, const Args&... args) {
- int r = push_luavalue(v);
- return r + polymorphicPush(args...);
- }
-
- // next templates must be defined after above includes
-
- template<class C, typename F>
- void LuaInterface::bindSingletonFunction(const std::string& functionName, F C::*function, C *instance) {
- registerClassStaticFunction<C>(functionName, luabinder::bind_singleton_mem_fun(function, instance));
- }
-
- template<class C, typename F>
- void LuaInterface::bindSingletonFunction(const std::string& className, const std::string& functionName, F C::*function, C *instance) {
- registerClassStaticFunction(className, functionName, luabinder::bind_singleton_mem_fun(function, instance));
- }
-
- template<class C, typename F>
- void LuaInterface::bindClassStaticFunction(const std::string& functionName, const F& function) {
- registerClassStaticFunction<C>(functionName, luabinder::bind_fun(function));
- }
- template<typename F>
- void LuaInterface::bindClassStaticFunction(const std::string& className, const std::string& functionName, const F& function) {
- registerClassStaticFunction(className, functionName, luabinder::bind_fun(function));
- }
-
- template<class C, typename F, class FC>
- void LuaInterface::bindClassMemberFunction(const std::string& functionName, F FC::*function) {
- registerClassMemberFunction<C>(functionName, luabinder::bind_mem_fun<C>(function));
- }
- template<class C, typename F, class FC>
- void LuaInterface::bindClassMemberFunction(const std::string& className, const std::string& functionName, F FC::*function) {
- registerClassMemberFunction(className, functionName, luabinder::bind_mem_fun<C>(function));
- }
-
- template<class C, typename F1, typename F2, class FC>
- void LuaInterface::bindClassMemberField(const std::string& fieldName, F1 FC::*getFunction, F2 FC::*setFunction) {
- registerClassMemberField<C>(fieldName, luabinder::bind_mem_fun<C>(getFunction), luabinder::bind_mem_fun<C>(setFunction));
- }
- template<class C, typename F1, typename F2, class FC>
- void LuaInterface::bindClassMemberField(const std::string& className, const std::string& fieldName, F1 FC::*getFunction, F2 FC::*setFunction) {
- registerClassMemberField(className, fieldName, luabinder::bind_mem_fun<C>(getFunction), luabinder::bind_mem_fun<C>(setFunction));
- }
-
- template<class C, typename F, class FC>
- void LuaInterface::bindClassMemberGetField(const std::string& fieldName, F FC::*getFunction) {
- registerClassMemberField<C>(fieldName, luabinder::bind_mem_fun<C>(getFunction), LuaCppFunction());
- }
- template<class C, typename F, class FC>
- void LuaInterface::bindClassMemberGetField(const std::string& className, const std::string& fieldName, F FC::*getFunction) {
- registerClassMemberField(className, fieldName, luabinder::bind_mem_fun<C>(getFunction), LuaCppFunction());
- }
-
- template<class C, typename F, class FC>
- void LuaInterface::bindClassMemberSetField(const std::string& fieldName, F FC::*setFunction) {
- registerClassMemberField<C>(fieldName, LuaCppFunction(), luabinder::bind_mem_fun<C>(setFunction));
- }
- template<class C, typename F, class FC>
- void LuaInterface::bindClassMemberSetField(const std::string& className, const std::string& fieldName, F FC::*setFunction) {
- registerClassMemberField(className, fieldName, LuaCppFunction(), luabinder::bind_mem_fun<C>(setFunction));
- }
-
- template<typename F>
- void LuaInterface::bindGlobalFunction(const std::string& functionName, const F& function) {
- registerGlobalFunction(functionName, luabinder::bind_fun(function));
- }
-
- template<class T>
- T LuaInterface::castValue(int index) {
- T o;
- if(!luavalue_cast(index, o))
- throw LuaBadValueCastException(typeName(index), stdext::demangle_type<T>());
- return o;
- }
-
- template<typename... T>
- int LuaInterface::luaCallGlobalField(const std::string& global, const std::string& field, const T&... args) {
- g_lua.getGlobalField(global, field);
- if(!g_lua.isNil()) {
- int numArgs = g_lua.polymorphicPush(args...);
- return g_lua.signalCall(numArgs);
- } else
- g_lua.pop(1);
- return 0;
- }
-
- template<typename... T>
- void LuaInterface::callGlobalField(const std::string& global, const std::string& field, const T&... args) {
- int rets = luaCallGlobalField(global, field, args...);
- if(rets > 0)
- pop(rets);
- }
-
- template<typename R, typename... T>
- R LuaInterface::callGlobalField(const std::string& global, const std::string& field, const T&... args) {
- R result;
- int rets = luaCallGlobalField(global, field, args...);
- if(rets > 0) {
- assert(rets == 1);
- result = g_lua.polymorphicPop<R>();
- } else
- result = R();
- return result;
- }
-
- #endif
|