No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

luainterface.h 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /*
  2. * Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. * THE SOFTWARE.
  21. */
  22. #ifndef LUAINTERFACE_H
  23. #define LUAINTERFACE_H
  24. #include "declarations.h"
  25. struct lua_State;
  26. typedef int (*LuaCFunction) (lua_State *L);
  27. /// Class that manages LUA stuff
  28. class LuaInterface
  29. {
  30. public:
  31. LuaInterface();
  32. ~LuaInterface();
  33. void init();
  34. void terminate();
  35. /// Register core script functions
  36. void registerFunctions();
  37. // functions that will register all script stuff in lua global environment
  38. void registerSingletonClass(const std::string& className);
  39. void registerClass(const std::string& className, const std::string& baseClass = "LuaObject");
  40. void registerClassStaticFunction(const std::string& className,
  41. const std::string& functionName,
  42. const LuaCppFunction& function);
  43. void registerClassMemberFunction(const std::string& className,
  44. const std::string& functionName,
  45. const LuaCppFunction& function);
  46. void registerClassMemberField(const std::string& className,
  47. const std::string& field,
  48. const LuaCppFunction& getFunction,
  49. const LuaCppFunction& setFunction);
  50. void registerGlobalFunction(const std::string& functionName,
  51. const LuaCppFunction& function);
  52. // register shortcuts using templates
  53. template<class C, class B = LuaObject>
  54. void registerClass() {
  55. registerClass(stdext::demangle_type<C>(), stdext::demangle_type<B>());
  56. }
  57. template<class C>
  58. void registerClassStaticFunction(const std::string& functionName, const LuaCppFunction& function) {
  59. registerClassStaticFunction(stdext::demangle_type<C>(), functionName, function);
  60. }
  61. template<class C>
  62. void registerClassMemberFunction(const std::string& functionName, const LuaCppFunction& function) {
  63. registerClassMemberFunction(stdext::demangle_type<C>(), functionName, function);
  64. }
  65. template<class C>
  66. void registerClassMemberField(const std::string& field,
  67. const LuaCppFunction& getFunction,
  68. const LuaCppFunction& setFunction) {
  69. registerClassMemberField(stdext::demangle_type<C>(), field, getFunction, setFunction);
  70. }
  71. // methods for binding functions
  72. template<class C, typename F>
  73. void bindSingletonFunction(const std::string& functionName, F C::*function, C *instance);
  74. template<class C, typename F>
  75. void bindSingletonFunction(const std::string& className, const std::string& functionName, F C::*function, C *instance);
  76. template<class C, typename F>
  77. void bindClassStaticFunction(const std::string& functionName, const F& function);
  78. template<typename F>
  79. void bindClassStaticFunction(const std::string& className, const std::string& functionName, const F& function);
  80. template<class C, typename F, class FC>
  81. void bindClassMemberFunction(const std::string& functionName, F FC::*function);
  82. template<class C, typename F, class FC>
  83. void bindClassMemberFunction(const std::string& className, const std::string& functionName, F FC::*function);
  84. template<class C, typename F1, typename F2, class FC>
  85. void bindClassMemberField(const std::string& fieldName, F1 FC::*getFunction, F2 FC::*setFunction);
  86. template<class C, typename F1, typename F2, class FC>
  87. void bindClassMemberField(const std::string& className, const std::string& fieldName, F1 FC::*getFunction, F2 FC::*setFunction);
  88. template<class C, typename F, class FC>
  89. void bindClassMemberGetField(const std::string& fieldName, F FC::*getFunction);
  90. template<class C, typename F, class FC>
  91. void bindClassMemberGetField(const std::string& className, const std::string& fieldName, F FC::*getFunction);
  92. template<class C, typename F, class FC>
  93. void bindClassMemberSetField(const std::string& fieldName, F FC::*setFunction);
  94. template<class C, typename F, class FC>
  95. void bindClassMemberSetField(const std::string& className, const std::string& fieldName, F FC::*setFunction);
  96. template<typename F>
  97. void bindGlobalFunction(const std::string& functionName, const F& function);
  98. private:
  99. /// Metamethod that will retrieve fields values (that include functions) from the object when using '.' or ':'
  100. static int luaObjectGetEvent(LuaInterface* lua);
  101. /// Metamethod that is called when setting a field of the object by using the keyword '='
  102. static int luaObjectSetEvent(LuaInterface* lua);
  103. /// Metamethod that will check equality of objects by using the keyword '=='
  104. static int luaObjectEqualEvent(LuaInterface* lua);
  105. /// Metamethod that is called every two lua garbage collections
  106. /// for any LuaObject that have no references left in lua environment
  107. /// anymore, thus this creates the possibility of holding an object
  108. /// existence by lua until it got no references left
  109. static int luaObjectCollectEvent(LuaInterface* lua);
  110. public:
  111. /// Loads and runs a script, any errors are printed to stdout and returns false
  112. bool safeRunScript(const std::string& fileName);
  113. /// Loads and runs a script
  114. /// @exception LuaException is thrown on any lua error
  115. void runScript(const std::string& fileName);
  116. /// Loads and runs the script from buffer
  117. /// @exception LuaException is thrown on any lua error
  118. void runBuffer(const std::string& buffer, const std::string& source);
  119. /// Loads a script file and pushes it's main function onto stack,
  120. /// @exception LuaException is thrown on any lua error
  121. void loadScript(const std::string& fileName);
  122. /// Loads a function from buffer and pushes it onto stack,
  123. /// @exception LuaException is thrown on any lua error
  124. void loadFunction(const std::string& buffer, const std::string& source = "lua function buffer");
  125. /// Evaluates a lua expression and pushes the result value onto the stack
  126. /// @exception LuaException is thrown on any lua error
  127. void evaluateExpression(const std::string& expression, const std::string& source = "lua expression");
  128. /// Generates a traceback message for the current call stack
  129. /// @param errorMessage is an additional error message
  130. /// @param level is the level of the traceback, 0 means trace from calling function
  131. /// @return the generated traceback message
  132. std::string traceback(const std::string& errorMessage = "", int level = 0);
  133. /// Throw a lua error if inside a lua call or generates an C++ stdext::exception
  134. /// @param message is the error message wich will be displayed before the error traceback
  135. /// @exception stdext::exception is thrown with the error message if the error is not captured by lua
  136. void throwError(const std::string& message);
  137. /// Searches for the source of the current running function
  138. std::string getCurrentSourcePath(int level = 0);
  139. /// @brief Calls a function
  140. /// The function and arguments must be on top of the stack in order,
  141. /// results are pushed onto the stack.
  142. /// @exception LuaException is thrown on any lua error
  143. /// @return number of results
  144. int safeCall(int numArgs = 0, int numRets = -1);
  145. /// Same as safeCall but catches exceptions and can also calls a table of functions,
  146. /// if any error occurs it will be reported to stdout and returns 0 results
  147. /// @param requestedResults is the number of results requested to pushes onto the stack,
  148. /// if supplied, the call will always pushes that number of results, even if it fails
  149. int signalCall(int numArgs = 0, int numRets = -1);
  150. /// @brief Creates a new environment table
  151. /// The new environment table is redirected to the global environment (aka _G),
  152. /// this allows to access global variables from _G in the new environment and
  153. /// prevents new variables in this new environment to be set on the global environment
  154. int newSandboxEnv();
  155. template<typename... T>
  156. int luaCallGlobalField(const std::string& global, const std::string& field, const T&... args);
  157. template<typename... T>
  158. void callGlobalField(const std::string& global, const std::string& field, const T&... args);
  159. template<typename R, typename... T>
  160. R callGlobalField(const std::string& global, const std::string& field, const T&... args);
  161. bool isInCppCallback() { return m_cppCallbackDepth != 0; }
  162. private:
  163. /// Load scripts requested by lua 'require'
  164. static int luaScriptLoader(lua_State* L);
  165. /// Run scripts requested by lua 'dofile'
  166. static int lua_dofile(lua_State* L);
  167. /// Run scripts requested by lua 'dofiles'
  168. static int lua_dofiles(lua_State* L);
  169. /// Run scripts requested by lua 'dofiles'
  170. static int lua_loadfile(lua_State* L);
  171. /// Handle lua errors from safeCall
  172. static int luaErrorHandler(lua_State* L);
  173. /// Handle bound cpp functions callbacks
  174. static int luaCppFunctionCallback(lua_State* L);
  175. /// Collect bound cpp function pointers
  176. static int luaCollectCppFunction(lua_State* L);
  177. public:
  178. void createLuaState();
  179. void closeLuaState();
  180. void collectGarbage();
  181. void loadBuffer(const std::string& buffer, const std::string& source);
  182. int pcall(int numArgs = 0, int numRets = 0, int errorFuncIndex = 0);
  183. void call(int numArgs = 0, int numRets = 0);
  184. void error();
  185. int ref();
  186. int weakRef();
  187. void unref(int ref);
  188. void useValue() { pushValue(); ref(); }
  189. const char* typeName(int index = -1);
  190. std::string functionSourcePath();
  191. void insert(int index);
  192. void remove(int index);
  193. bool next(int index = -2);
  194. void checkStack() { assert(getTop() <= 20); }
  195. void getStackFunction(int level = 0);
  196. void getRef(int ref);
  197. void getWeakRef(int weakRef);
  198. int getGlobalEnvironment() { return m_globalEnv; }
  199. void setGlobalEnvironment(int env);
  200. void resetGlobalEnvironment() { setGlobalEnvironment(m_globalEnv); }
  201. void setMetatable(int index = -2);
  202. void getMetatable(int index = -1);
  203. void getField(const char* key, int index = -1);
  204. void getField(const std::string& key, int index = -1) { return getField(key.c_str(), index); }
  205. void setField(const char* key, int index = -2);
  206. void setField(const std::string& key, int index = -2) { return setField(key.c_str(), index); }
  207. void getTable(int index = -2);
  208. void setTable(int index = -3);
  209. void clearTable(int index = -1);
  210. void getEnv(int index = -1);
  211. void setEnv(int index = -2);
  212. void getGlobal(const std::string& key);
  213. void getGlobalField(const std::string& globalKey, const std::string& fieldKey);
  214. void setGlobal(const std::string& key);
  215. void rawGet(int index = -1);
  216. void rawGeti(int n, int index = -1);
  217. void rawSet(int index = -3);
  218. void rawSeti(int n, int index = -2);
  219. void newTable();
  220. void* newUserdata(int size);
  221. void pop(int n = 1);
  222. long popInteger();
  223. double popNumber();
  224. bool popBoolean();
  225. std::string popString();
  226. void* popUserdata();
  227. void* popUpvalueUserdata();
  228. LuaObjectPtr popObject();
  229. void pushNil();
  230. void pushInteger(long v);
  231. void pushNumber(double v);
  232. void pushBoolean(bool v);
  233. void pushCString(const char* v);
  234. void pushString(const std::string& v);
  235. void pushLightUserdata(void* p);
  236. void pushThread();
  237. void pushValue(int index = -1);
  238. void pushObject(const LuaObjectPtr& obj);
  239. void pushCFunction(LuaCFunction func, int n = 0);
  240. void pushCppFunction(const LuaCppFunction& func);
  241. bool isNil(int index = -1);
  242. bool isBoolean(int index = -1);
  243. bool isNumber(int index = -1);
  244. bool isString(int index = -1);
  245. bool isTable(int index = -1);
  246. bool isFunction(int index = -1);
  247. bool isCFunction(int index = -1);
  248. bool isLuaFunction(int index = -1) { return (isFunction() && !isCFunction()); }
  249. bool isUserdata(int index = -1);
  250. bool toBoolean(int index = -1);
  251. int toInteger(int index = -1);
  252. double toNumber(int index = -1);
  253. const char* toCString(int index = -1);
  254. std::string toString(int index = -1);
  255. void* toUserdata(int index = -1);
  256. LuaObjectPtr toObject(int index = -1);
  257. int getTop();
  258. int stackSize() { return getTop(); }
  259. void clearStack() { pop(stackSize()); }
  260. bool hasIndex(int index) { return (stackSize() >= (index < 0 ? -index : index) && index != 0); }
  261. void loadFiles(std::string directory, bool recursive = false, std::string contains = "");
  262. /// Pushes any type onto the stack
  263. template<typename T, typename... Args>
  264. int polymorphicPush(const T& v, const Args&... args);
  265. int polymorphicPush() { return 0; }
  266. /// Casts a value from stack to any type
  267. /// @exception LuaBadValueCastException thrown if the cast fails
  268. template<class T>
  269. T castValue(int index = -1);
  270. /// Same as castValue but also pops
  271. template<class T>
  272. T polymorphicPop() { T v = castValue<T>(); pop(1); return v; }
  273. private:
  274. lua_State* L;
  275. int m_weakTableRef;
  276. int m_cppCallbackDepth;
  277. int m_totalObjRefs;
  278. int m_totalFuncRefs;
  279. int m_globalEnv;
  280. };
  281. extern LuaInterface g_lua;
  282. // must be included after, because they need LuaInterface fully declared
  283. #include "luaexception.h"
  284. #include "luabinder.h"
  285. #include "luavaluecasts.h"
  286. template<typename T, typename... Args>
  287. int LuaInterface::polymorphicPush(const T& v, const Args&... args) {
  288. int r = push_luavalue(v);
  289. return r + polymorphicPush(args...);
  290. }
  291. // next templates must be defined after above includes
  292. template<class C, typename F>
  293. void LuaInterface::bindSingletonFunction(const std::string& functionName, F C::*function, C *instance) {
  294. registerClassStaticFunction<C>(functionName, luabinder::bind_singleton_mem_fun(function, instance));
  295. }
  296. template<class C, typename F>
  297. void LuaInterface::bindSingletonFunction(const std::string& className, const std::string& functionName, F C::*function, C *instance) {
  298. registerClassStaticFunction(className, functionName, luabinder::bind_singleton_mem_fun(function, instance));
  299. }
  300. template<class C, typename F>
  301. void LuaInterface::bindClassStaticFunction(const std::string& functionName, const F& function) {
  302. registerClassStaticFunction<C>(functionName, luabinder::bind_fun(function));
  303. }
  304. template<typename F>
  305. void LuaInterface::bindClassStaticFunction(const std::string& className, const std::string& functionName, const F& function) {
  306. registerClassStaticFunction(className, functionName, luabinder::bind_fun(function));
  307. }
  308. template<class C, typename F, class FC>
  309. void LuaInterface::bindClassMemberFunction(const std::string& functionName, F FC::*function) {
  310. registerClassMemberFunction<C>(functionName, luabinder::bind_mem_fun<C>(function));
  311. }
  312. template<class C, typename F, class FC>
  313. void LuaInterface::bindClassMemberFunction(const std::string& className, const std::string& functionName, F FC::*function) {
  314. registerClassMemberFunction(className, functionName, luabinder::bind_mem_fun<C>(function));
  315. }
  316. template<class C, typename F1, typename F2, class FC>
  317. void LuaInterface::bindClassMemberField(const std::string& fieldName, F1 FC::*getFunction, F2 FC::*setFunction) {
  318. registerClassMemberField<C>(fieldName, luabinder::bind_mem_fun<C>(getFunction), luabinder::bind_mem_fun<C>(setFunction));
  319. }
  320. template<class C, typename F1, typename F2, class FC>
  321. void LuaInterface::bindClassMemberField(const std::string& className, const std::string& fieldName, F1 FC::*getFunction, F2 FC::*setFunction) {
  322. registerClassMemberField(className, fieldName, luabinder::bind_mem_fun<C>(getFunction), luabinder::bind_mem_fun<C>(setFunction));
  323. }
  324. template<class C, typename F, class FC>
  325. void LuaInterface::bindClassMemberGetField(const std::string& fieldName, F FC::*getFunction) {
  326. registerClassMemberField<C>(fieldName, luabinder::bind_mem_fun<C>(getFunction), LuaCppFunction());
  327. }
  328. template<class C, typename F, class FC>
  329. void LuaInterface::bindClassMemberGetField(const std::string& className, const std::string& fieldName, F FC::*getFunction) {
  330. registerClassMemberField(className, fieldName, luabinder::bind_mem_fun<C>(getFunction), LuaCppFunction());
  331. }
  332. template<class C, typename F, class FC>
  333. void LuaInterface::bindClassMemberSetField(const std::string& fieldName, F FC::*setFunction) {
  334. registerClassMemberField<C>(fieldName, LuaCppFunction(), luabinder::bind_mem_fun<C>(setFunction));
  335. }
  336. template<class C, typename F, class FC>
  337. void LuaInterface::bindClassMemberSetField(const std::string& className, const std::string& fieldName, F FC::*setFunction) {
  338. registerClassMemberField(className, fieldName, LuaCppFunction(), luabinder::bind_mem_fun<C>(setFunction));
  339. }
  340. template<typename F>
  341. void LuaInterface::bindGlobalFunction(const std::string& functionName, const F& function) {
  342. registerGlobalFunction(functionName, luabinder::bind_fun(function));
  343. }
  344. template<class T>
  345. T LuaInterface::castValue(int index) {
  346. T o;
  347. if(!luavalue_cast(index, o))
  348. throw LuaBadValueCastException(typeName(index), stdext::demangle_type<T>());
  349. return o;
  350. }
  351. template<typename... T>
  352. int LuaInterface::luaCallGlobalField(const std::string& global, const std::string& field, const T&... args) {
  353. g_lua.getGlobalField(global, field);
  354. if(!g_lua.isNil()) {
  355. int numArgs = g_lua.polymorphicPush(args...);
  356. return g_lua.signalCall(numArgs);
  357. } else
  358. g_lua.pop(1);
  359. return 0;
  360. }
  361. template<typename... T>
  362. void LuaInterface::callGlobalField(const std::string& global, const std::string& field, const T&... args) {
  363. int rets = luaCallGlobalField(global, field, args...);
  364. if(rets > 0)
  365. pop(rets);
  366. }
  367. template<typename R, typename... T>
  368. R LuaInterface::callGlobalField(const std::string& global, const std::string& field, const T&... args) {
  369. R result;
  370. int rets = luaCallGlobalField(global, field, args...);
  371. if(rets > 0) {
  372. assert(rets == 1);
  373. result = g_lua.polymorphicPop<R>();
  374. } else
  375. result = R();
  376. return result;
  377. }
  378. #endif