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.cpp 31KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274
  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. #include "luainterface.h"
  23. #include "luaobject.h"
  24. #include <framework/core/resourcemanager.h>
  25. #include <lua.hpp>
  26. #include "lbitlib.h"
  27. LuaInterface g_lua;
  28. LuaInterface::LuaInterface()
  29. {
  30. L = nullptr;
  31. m_cppCallbackDepth = 0;
  32. m_weakTableRef = 0;
  33. m_totalObjRefs = 0;
  34. m_totalFuncRefs = 0;
  35. }
  36. LuaInterface::~LuaInterface()
  37. {
  38. }
  39. void LuaInterface::init()
  40. {
  41. createLuaState();
  42. // store global environment reference
  43. pushThread();
  44. getEnv();
  45. m_globalEnv = ref();
  46. pop();
  47. // check if demangle_type is working as expected
  48. assert(stdext::demangle_type<LuaObject>() == "LuaObject");
  49. // register LuaObject, the base of all other objects
  50. registerClass<LuaObject>();
  51. bindClassMemberFunction<LuaObject>("getUseCount", &LuaObject::getUseCount);
  52. bindClassMemberFunction<LuaObject>("getClassName", &LuaObject::getClassName);
  53. registerClassMemberFunction<LuaObject>("getFieldsTable", (LuaCppFunction) ([](LuaInterface* lua) -> int {
  54. LuaObjectPtr obj = g_lua.popObject();
  55. obj->luaGetFieldsTable();
  56. return 1;
  57. }));
  58. }
  59. void LuaInterface::terminate()
  60. {
  61. // close lua state, it will release all objects
  62. closeLuaState();
  63. assert(m_totalFuncRefs == 0);
  64. assert(m_totalObjRefs == 0);
  65. }
  66. void LuaInterface::registerSingletonClass(const std::string& className)
  67. {
  68. newTable();
  69. pushValue();
  70. setGlobal(className);
  71. pop();
  72. }
  73. void LuaInterface::registerClass(const std::string& className, const std::string& baseClass)
  74. {
  75. // creates the class table (that it's also the class methods table)
  76. newTable();
  77. pushValue();
  78. setGlobal(className);
  79. const int klass = getTop();
  80. // creates the class fieldmethods table
  81. newTable();
  82. pushValue();
  83. setGlobal(className + "_fieldmethods");
  84. int klass_fieldmethods = getTop();
  85. // creates the class metatable
  86. newTable();
  87. pushValue();
  88. setGlobal(className + "_mt");
  89. int klass_mt = getTop();
  90. // set metatable metamethods
  91. pushCppFunction(&LuaInterface::luaObjectGetEvent);
  92. setField("__index", klass_mt);
  93. pushCppFunction(&LuaInterface::luaObjectSetEvent);
  94. setField("__newindex", klass_mt);
  95. pushCppFunction(&LuaInterface::luaObjectEqualEvent);
  96. setField("__eq", klass_mt);
  97. pushCppFunction(&LuaInterface::luaObjectCollectEvent);
  98. setField("__gc", klass_mt);
  99. // set some fields that will be used later in metatable
  100. pushValue(klass);
  101. setField("methods", klass_mt);
  102. pushValue(klass_fieldmethods);
  103. setField("fieldmethods", klass_mt);
  104. // redirect methods and fieldmethods to the base class ones
  105. if(!className.empty() && className != "LuaObject") {
  106. // the following code is what create classes hierarchy for lua, by reproducing:
  107. // DerivedClass = { __index = BaseClass }
  108. // DerivedClass_fieldmethods = { __index = BaseClass_methods }
  109. // redirect the class methods to the base methods
  110. pushValue(klass);
  111. newTable();
  112. getGlobal(baseClass);
  113. setField("__index");
  114. setMetatable();
  115. pop();
  116. // redirect the class fieldmethods to the base fieldmethods
  117. pushValue(klass_fieldmethods);
  118. newTable();
  119. getGlobal(baseClass + "_fieldmethods");
  120. setField("__index");
  121. setMetatable();
  122. pop();
  123. }
  124. // pops klass, klass_mt, klass_fieldmethods
  125. pop(3);
  126. }
  127. void LuaInterface::registerClassStaticFunction(const std::string& className,
  128. const std::string& functionName,
  129. const LuaCppFunction& function)
  130. {
  131. registerClassMemberFunction(className, functionName, function);
  132. }
  133. void LuaInterface::registerClassMemberFunction(const std::string& className,
  134. const std::string& functionName,
  135. const LuaCppFunction& function)
  136. {
  137. getGlobal(className);
  138. pushCppFunction(function);
  139. setField(functionName);
  140. pop();
  141. }
  142. void LuaInterface::registerClassMemberField(const std::string& className,
  143. const std::string& field,
  144. const LuaCppFunction& getFunction,
  145. const LuaCppFunction& setFunction)
  146. {
  147. getGlobal(className + "_fieldmethods");
  148. if(getFunction) {
  149. pushCppFunction(getFunction);
  150. setField(stdext::format("get_%s", field));
  151. }
  152. if(setFunction) {
  153. pushCppFunction(setFunction);
  154. setField(stdext::format("set_%s", field));
  155. }
  156. pop();
  157. }
  158. void LuaInterface::registerGlobalFunction(const std::string& functionName, const LuaCppFunction& function)
  159. {
  160. pushCppFunction(function);
  161. setGlobal(functionName);
  162. }
  163. int LuaInterface::luaObjectGetEvent(LuaInterface* lua)
  164. {
  165. // stack: obj, key
  166. LuaObjectPtr obj = lua->toObject(-2);
  167. std::string key = lua->toString(-1);
  168. assert(obj);
  169. lua->remove(-1); // removes key
  170. // if a get method for this key exists, calls it
  171. lua->getMetatable(); // pushes obj metatable
  172. lua->getField("fieldmethods"); // push obj fieldmethods
  173. lua->remove(-2); // removes obj metatable
  174. lua->getField("get_" + key); // pushes get method
  175. lua->remove(-2); // remove obj fieldmethods
  176. if(!lua->isNil()) { // is the get method not nil?
  177. lua->insert(-2); // moves obj to the top
  178. lua->signalCall(1, 1); // calls get method, arguments: obj
  179. return 1;
  180. }
  181. lua->pop(); // pops the nil get method
  182. // if the field for this key exists, returns it
  183. obj->luaGetField(key);
  184. if(!lua->isNil()) {
  185. lua->remove(-2); // removes the obj
  186. // field value is on the stack
  187. return 1;
  188. }
  189. lua->pop(); // pops the nil field
  190. // pushes the method assigned by this key
  191. lua->getMetatable(); // pushes obj metatable
  192. lua->getField("methods"); // push obj methods
  193. lua->remove(-2); // removes obj metatable
  194. lua->getField(key); // pushes obj method
  195. lua->remove(-2); // remove obj methods
  196. lua->remove(-2); // removes obj
  197. // the result value is on the stack
  198. return 1;
  199. }
  200. int LuaInterface::luaObjectSetEvent(LuaInterface* lua)
  201. {
  202. // stack: obj, key, value
  203. LuaObjectPtr obj = lua->toObject(-3);
  204. std::string key = lua->toString(-2);
  205. assert(obj);
  206. lua->remove(-2); // removes key
  207. lua->insert(-2); // moves obj to the top
  208. // check if a set method for this field exists and call it
  209. lua->getMetatable(); // pushes obj metatable
  210. lua->getField("fieldmethods"); // push obj fieldmethods
  211. lua->remove(-2); // removes obj metatable
  212. lua->getField("set_" + key); // pushes set method
  213. lua->remove(-2); // remove obj fieldmethods
  214. if(!lua->isNil()) { // is the set method not nil?
  215. lua->insert(-3); // moves func to -3
  216. lua->insert(-2); // moves obj to -2, and value to -1
  217. lua->signalCall(2, 0); // calls set method, arguments: obj, value
  218. return 0;
  219. }
  220. lua->pop(); // pops the nil set method
  221. // no set method exists, then treats as an field and set it
  222. lua->pop(); // pops the object
  223. obj->luaSetField(key); // sets the obj field
  224. return 0;
  225. }
  226. int LuaInterface::luaObjectEqualEvent(LuaInterface* lua)
  227. {
  228. // stack: obj1, obj2
  229. bool ret = false;
  230. // check if obj1 == obj2
  231. if(lua->isUserdata(-1) && lua->isUserdata(-2)) {
  232. LuaObjectPtr* objPtr2 = static_cast<LuaObjectPtr*>(lua->popUserdata());
  233. LuaObjectPtr* objPtr1 = static_cast<LuaObjectPtr*>(lua->popUserdata());
  234. assert(objPtr1 && objPtr2);
  235. if(*objPtr1 == *objPtr2)
  236. ret = true;
  237. } else
  238. lua->pop(2);
  239. lua->pushBoolean(ret);
  240. return 1;
  241. }
  242. int LuaInterface::luaObjectCollectEvent(LuaInterface* lua)
  243. {
  244. // gets object pointer
  245. auto objPtr = static_cast<LuaObjectPtr*>(lua->popUserdata());
  246. assert(objPtr);
  247. // resets pointer to decrease object use count
  248. objPtr->reset();
  249. g_lua.m_totalObjRefs--;
  250. return 0;
  251. }
  252. ///////////////////////////////////////////////////////////////////////////////
  253. bool LuaInterface::safeRunScript(const std::string& fileName)
  254. {
  255. try {
  256. runScript(fileName);
  257. return true;
  258. } catch(stdext::exception& e) {
  259. g_logger.error(stdext::format("Failed to load script '%s': %s", fileName, e.what()));
  260. return false;
  261. }
  262. }
  263. void LuaInterface::runScript(const std::string& fileName)
  264. {
  265. loadScript(fileName);
  266. safeCall(0, 0);
  267. }
  268. void LuaInterface::runBuffer(const std::string& buffer, const std::string& source)
  269. {
  270. loadBuffer(buffer, source);
  271. safeCall(0, 0);
  272. }
  273. void LuaInterface::loadScript(const std::string& fileName)
  274. {
  275. // resolve file full path
  276. std::string filePath = fileName;
  277. if(!stdext::starts_with(fileName, "/"))
  278. filePath = getCurrentSourcePath() + "/" + filePath;
  279. filePath = g_resources.guessFilePath(filePath, "lua");
  280. std::string buffer = g_resources.readFileContents(filePath);
  281. std::string source = "@" + filePath;
  282. loadBuffer(buffer, source);
  283. }
  284. void LuaInterface::loadFunction(const std::string& buffer, const std::string& source)
  285. {
  286. if(buffer.empty()) {
  287. pushNil();
  288. return;
  289. }
  290. std::string buf;
  291. if(stdext::starts_with(buffer, "function"))
  292. buf = stdext::format("__func = %s", buffer);
  293. else
  294. buf = stdext::format("__func = function(self)\n%s\nend", buffer);
  295. loadBuffer(buf, source);
  296. safeCall();
  297. // get the function
  298. getGlobal("__func");
  299. // reset the global __func
  300. pushNil();
  301. setGlobal("__func");
  302. }
  303. void LuaInterface::evaluateExpression(const std::string& expression, const std::string& source)
  304. {
  305. // evaluates the expression
  306. if(!expression.empty()) {
  307. std::string buffer = stdext::format("__exp = (%s)", expression);
  308. loadBuffer(buffer, source);
  309. safeCall();
  310. // gets the expression result
  311. getGlobal("__exp");
  312. // resets global __exp
  313. pushNil();
  314. setGlobal("__exp");
  315. } else
  316. pushNil();
  317. }
  318. std::string LuaInterface::traceback(const std::string& errorMessage, int level)
  319. {
  320. // gets debug.traceback
  321. getGlobal("debug");
  322. getField("traceback");
  323. remove(-2); // remove debug
  324. // calls debug.traceback(errorMessage, level)
  325. pushString(errorMessage);
  326. pushInteger(level);
  327. call(2,1);
  328. // returns the traceback message
  329. return popString();
  330. }
  331. void LuaInterface::throwError(const std::string& message)
  332. {
  333. if(isInCppCallback()) {
  334. pushString(message);
  335. error();
  336. } else
  337. throw stdext::exception(message);
  338. }
  339. std::string LuaInterface::getCurrentSourcePath(int level)
  340. {
  341. std::string path;
  342. if(!L)
  343. return path;
  344. // check all stack functions for script source path
  345. while(true) {
  346. getStackFunction(level); // pushes stack function
  347. // only lua functions is wanted, because only them have a working directory
  348. if(isLuaFunction()) {
  349. path = functionSourcePath();
  350. break;
  351. } else if(isNil()) {
  352. pop();
  353. break;
  354. } else
  355. pop();
  356. // next level
  357. level++;
  358. }
  359. return path;
  360. }
  361. int LuaInterface::safeCall(int numArgs, int numRets)
  362. {
  363. assert(hasIndex(-numArgs-1));
  364. // saves the current stack size for calculating the number of results later
  365. int previousStackSize = stackSize();
  366. // pushes error function
  367. int errorFuncIndex = previousStackSize - numArgs;
  368. pushCFunction(&LuaInterface::luaErrorHandler);
  369. insert(errorFuncIndex);
  370. // calls the function in protected mode (means errors will be caught)
  371. int ret = pcall(numArgs, LUA_MULTRET, errorFuncIndex);
  372. remove(errorFuncIndex); // remove error func
  373. // if there was an error throw an exception
  374. if(ret != 0)
  375. throw LuaException(popString());
  376. int rets = (stackSize() + numArgs + 1) - previousStackSize;
  377. while(numRets != -1 && rets != numRets) {
  378. if(rets < numRets) {
  379. pushNil();
  380. rets++;
  381. } else {
  382. pop();
  383. rets--;
  384. }
  385. }
  386. // returns the number of results
  387. return rets;
  388. }
  389. int LuaInterface::signalCall(int numArgs, int numRets)
  390. {
  391. int rets = 0;
  392. int funcIndex = -numArgs-1;
  393. try {
  394. // must be a function
  395. if(isFunction(funcIndex)) {
  396. rets = safeCall(numArgs);
  397. if(numRets != -1) {
  398. if(rets != numRets)
  399. throw LuaException("function call didn't return the expected number of results", 0);
  400. }
  401. }
  402. // can also calls table of functions
  403. else if(isTable(funcIndex)) {
  404. // loop through table values
  405. pushNil();
  406. bool done = false;
  407. while(next(funcIndex-1)) {
  408. if(isFunction()) {
  409. // repush arguments
  410. for(int i=0;i<numArgs;++i)
  411. pushValue(-numArgs-2);
  412. int rets = safeCall(numArgs);
  413. if(rets == 1) {
  414. done = popBoolean();
  415. if(done) {
  416. pop();
  417. break;
  418. }
  419. } else if(rets != 0)
  420. throw LuaException("function call didn't return the expected number of results", 0);
  421. } else {
  422. throw LuaException("attempt to call a non function", 0);
  423. }
  424. }
  425. pop(numArgs + 1); // pops the table of function and arguments
  426. if(numRets == 1 || numRets == -1) {
  427. rets = 1;
  428. pushBoolean(done);
  429. }
  430. }
  431. // nil values are ignored
  432. else if(isNil(funcIndex)) {
  433. pop(numArgs + 1); // pops the function and arguments
  434. }
  435. // if not nil, warn
  436. else {
  437. throw LuaException("attempt to call a non function value", 0);
  438. }
  439. } catch(stdext::exception& e) {
  440. g_logger.error(stdext::format("protected lua call failed: %s", e.what()));
  441. }
  442. // pushes nil values if needed
  443. while(numRets != -1 && rets < numRets) {
  444. pushNil();
  445. rets++;
  446. }
  447. // returns the number of results on the stack
  448. return rets;
  449. }
  450. int LuaInterface::newSandboxEnv()
  451. {
  452. newTable(); // pushes the new environment table
  453. newTable(); // pushes the new environment metatable
  454. getRef(getGlobalEnvironment()); // pushes the global environment
  455. setField("__index"); // sets metatable __index to the global environment
  456. setMetatable(); // assigns environment metatable
  457. return ref(); // return a reference to the environment table
  458. }
  459. ///////////////////////////////////////////////////////////////////////////////
  460. // lua C functions
  461. int LuaInterface::luaScriptLoader(lua_State* L)
  462. {
  463. // loads the script as a function
  464. std::string fileName = g_lua.popString();
  465. try {
  466. g_lua.loadScript(fileName);
  467. return 1;
  468. } catch(stdext::exception& e) {
  469. g_lua.pushString(std::string("\n\t") + e.what());
  470. return 1;
  471. }
  472. }
  473. int LuaInterface::lua_dofile(lua_State* L)
  474. {
  475. std::string file = g_lua.popString();
  476. try {
  477. g_lua.loadScript(file);
  478. g_lua.call(0, LUA_MULTRET);
  479. return g_lua.stackSize();
  480. } catch(stdext::exception& e) {
  481. g_lua.pushString(e.what());
  482. g_lua.error();
  483. return 0;
  484. }
  485. }
  486. int LuaInterface::lua_dofiles(lua_State* L)
  487. {
  488. std::string contains = "";
  489. if(g_lua.getTop() > 2) {
  490. contains = g_lua.popString();
  491. }
  492. bool recursive = false;
  493. if(g_lua.getTop() > 1) {
  494. recursive = g_lua.popBoolean();
  495. }
  496. std::string directory = g_lua.popString();
  497. g_lua.loadFiles(directory, recursive, contains);
  498. return 0;
  499. }
  500. int LuaInterface::lua_loadfile(lua_State* L)
  501. {
  502. std::string fileName = g_lua.popString();
  503. try {
  504. g_lua.loadScript(fileName);
  505. return 1;
  506. } catch(stdext::exception& e) {
  507. g_lua.pushNil();
  508. g_lua.pushString(e.what());
  509. g_lua.error();
  510. return 2;
  511. }
  512. }
  513. int LuaInterface::luaErrorHandler(lua_State* L)
  514. {
  515. // pops the error message
  516. auto error = g_lua.popString();
  517. // prevents repeated tracebacks
  518. if(error.find("stack traceback:") == std::string::npos)
  519. error = g_lua.traceback(error, 1);
  520. // pushes the new error message with traceback information
  521. g_lua.pushString(error);
  522. return 1;
  523. }
  524. int LuaInterface::luaCppFunctionCallback(lua_State* L)
  525. {
  526. // retrieves function pointer from userdata
  527. auto funcPtr = static_cast<LuaCppFunctionPtr*>(g_lua.popUpvalueUserdata());
  528. assert(funcPtr);
  529. int numRets = 0;
  530. // do the call
  531. try {
  532. g_lua.m_cppCallbackDepth++;
  533. numRets = (*(funcPtr->get()))(&g_lua);
  534. g_lua.m_cppCallbackDepth--;
  535. assert(numRets == g_lua.stackSize());
  536. } catch(stdext::exception& e) {
  537. // cleanup stack
  538. while(g_lua.stackSize() > 0)
  539. g_lua.pop();
  540. numRets = 0;
  541. g_lua.pushString(stdext::format("C++ call failed: %s", g_lua.traceback(e.what())));
  542. g_lua.error();
  543. }
  544. return numRets;
  545. }
  546. int LuaInterface::luaCollectCppFunction(lua_State* L)
  547. {
  548. auto funcPtr = static_cast<LuaCppFunctionPtr*>(g_lua.popUserdata());
  549. assert(funcPtr);
  550. funcPtr->reset();
  551. g_lua.m_totalFuncRefs--;
  552. return 0;
  553. }
  554. ///////////////////////////////////////////////////////////////////////////////
  555. // from here all next functions are interfaces for the Lua API
  556. void LuaInterface::createLuaState()
  557. {
  558. // creates lua state
  559. L = luaL_newstate();
  560. if(!L)
  561. g_logger.fatal("Unable to create lua state");
  562. // load lua standard libraries
  563. luaL_openlibs(L);
  564. // load bit32 lib for bitwise operations
  565. luaopen_bit32(L);
  566. // creates weak table
  567. newTable();
  568. newTable();
  569. pushString("v");
  570. setField("__mode");
  571. setMetatable();
  572. m_weakTableRef = ref();
  573. // installs script loader
  574. getGlobal("package");
  575. getField("loaders");
  576. pushCFunction(&LuaInterface::luaScriptLoader);
  577. rawSeti(5);
  578. pop(2);
  579. // replace dofile
  580. pushCFunction(&LuaInterface::lua_dofile);
  581. setGlobal("dofile");
  582. // dofiles
  583. pushCFunction(&LuaInterface::lua_dofiles);
  584. setGlobal("dofiles");
  585. // replace loadfile
  586. pushCFunction(&LuaInterface::lua_loadfile);
  587. setGlobal("loadfile");
  588. }
  589. void LuaInterface::closeLuaState()
  590. {
  591. if(L) {
  592. // close lua, it also collects
  593. lua_close(L);
  594. L = NULL;
  595. }
  596. }
  597. void LuaInterface::collectGarbage()
  598. {
  599. // prevents recursive collects
  600. static bool collecting = false;
  601. if(!collecting) {
  602. collecting = true;
  603. // we must collect two times because __gc metamethod
  604. // is called on uservalues only the second time
  605. for(int i=0;i<2;++i)
  606. lua_gc(L, LUA_GCCOLLECT, 0);
  607. collecting = false;
  608. }
  609. }
  610. void LuaInterface::loadBuffer(const std::string& buffer, const std::string& source)
  611. {
  612. // loads lua buffer
  613. int ret = luaL_loadbuffer(L, buffer.c_str(), buffer.length(), source.c_str());
  614. if(ret != 0)
  615. throw LuaException(popString(), 0);
  616. }
  617. int LuaInterface::pcall(int numArgs, int numRets, int errorFuncIndex)
  618. {
  619. assert(hasIndex(-numArgs - 1));
  620. return lua_pcall(L, numArgs, numRets, errorFuncIndex);
  621. }
  622. void LuaInterface::call(int numArgs, int numRets)
  623. {
  624. assert(hasIndex(-numArgs - 1));
  625. lua_call(L, numArgs, numRets);
  626. }
  627. void LuaInterface::error()
  628. {
  629. assert(hasIndex(-1));
  630. lua_error(L);
  631. }
  632. int LuaInterface::ref()
  633. {
  634. int ref = luaL_ref(L, LUA_REGISTRYINDEX);
  635. assert(ref != LUA_NOREF);
  636. assert(ref < 2147483647);
  637. return ref;
  638. }
  639. int LuaInterface::weakRef()
  640. {
  641. static int id = 0;
  642. // generates a new id
  643. ++id;
  644. if(id == 2147483647)
  645. id = 0;
  646. // gets weak table
  647. getRef(m_weakTableRef);
  648. insert(-2);
  649. // sets weak_table[id] = v
  650. rawSeti(id);
  651. // pops weak table
  652. pop();
  653. return id;
  654. }
  655. void LuaInterface::unref(int ref)
  656. {
  657. if(ref >= 0 && L != NULL)
  658. luaL_unref(L, LUA_REGISTRYINDEX, ref);
  659. }
  660. const char* LuaInterface::typeName(int index)
  661. {
  662. assert(hasIndex(index));
  663. int type = lua_type(L, index);
  664. return lua_typename(L, type);
  665. }
  666. std::string LuaInterface::functionSourcePath()
  667. {
  668. std::string path;
  669. // gets function source path
  670. lua_Debug ar;
  671. memset(&ar, 0, sizeof(ar));
  672. lua_getinfo(L, ">Sn", &ar);
  673. if(ar.source) {
  674. // scripts coming from files has source beginning with '@'
  675. if(ar.source[0] == '@') {
  676. path = ar.source;
  677. path = path.substr(1, path.find_last_of("/") - 1);
  678. path = path.substr(0, path.find_last_of(":"));
  679. }
  680. }
  681. return path;
  682. }
  683. void LuaInterface::insert(int index)
  684. {
  685. assert(hasIndex(index));
  686. lua_insert(L, index);
  687. }
  688. void LuaInterface::remove(int index)
  689. {
  690. assert(hasIndex(index));
  691. lua_remove(L, index);
  692. }
  693. bool LuaInterface::next(int index)
  694. {
  695. assert(hasIndex(index));
  696. return lua_next(L, index);
  697. }
  698. void LuaInterface::getStackFunction(int level)
  699. {
  700. lua_Debug ar;
  701. if(lua_getstack(L, level, &ar) == 1)
  702. lua_getinfo(L, "f", &ar);
  703. else
  704. pushNil();
  705. }
  706. void LuaInterface::getRef(int ref)
  707. {
  708. lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
  709. }
  710. void LuaInterface::getWeakRef(int weakRef)
  711. {
  712. // pushes weak_table[weakRef]
  713. getRef(m_weakTableRef);
  714. rawGeti(weakRef);
  715. remove(-2);
  716. }
  717. void LuaInterface::setGlobalEnvironment(int env)
  718. {
  719. pushThread();
  720. getRef(env);
  721. assert(isTable());
  722. setEnv();
  723. pop();
  724. }
  725. void LuaInterface::setMetatable(int index)
  726. {
  727. assert(hasIndex(index));
  728. lua_setmetatable(L, index);
  729. }
  730. void LuaInterface::getMetatable(int index)
  731. {
  732. assert(hasIndex(index));
  733. lua_getmetatable(L, index);
  734. }
  735. void LuaInterface::getField(const char* key, int index)
  736. {
  737. assert(hasIndex(index));
  738. assert(isUserdata(index) || isTable(index));
  739. lua_getfield(L, index, key);
  740. }
  741. void LuaInterface::setField(const char* key, int index)
  742. {
  743. assert(hasIndex(index));
  744. assert(isUserdata(index) || isTable(index));
  745. lua_setfield(L, index, key);
  746. }
  747. void LuaInterface::getEnv(int index)
  748. {
  749. assert(hasIndex(index));
  750. lua_getfenv(L, index);
  751. }
  752. void LuaInterface::setEnv(int index)
  753. {
  754. assert(hasIndex(index));
  755. lua_setfenv(L, index);
  756. }
  757. void LuaInterface::getTable(int index)
  758. {
  759. assert(hasIndex(index));
  760. lua_gettable(L, index);
  761. }
  762. void LuaInterface::setTable(int index)
  763. {
  764. assert(hasIndex(index));
  765. lua_settable(L, index);
  766. }
  767. void LuaInterface::clearTable(int index)
  768. {
  769. assert(hasIndex(index) && isTable(index));
  770. pushNil(); // table, nil
  771. bool stop = false;
  772. while(next(index-1)) { // table, key, value
  773. pop(); // table, key
  774. pushValue(); // table, key, key
  775. if(next(index-2)) { // table, key, nextkey, value
  776. pop(); // table, key, nextkey
  777. insert(-2); // table, nextkey, key
  778. pushNil(); // table, nextkey, key, nil
  779. rawSet(index-3); // table, nextkey
  780. } else { // table, key
  781. pushNil(); // table, key, nil
  782. rawSet(index-2); // table
  783. break;
  784. }
  785. }
  786. }
  787. void LuaInterface::getGlobal(const std::string& key)
  788. {
  789. lua_getglobal(L, key.c_str());
  790. }
  791. void LuaInterface::getGlobalField(const std::string& globalKey, const std::string& fieldKey)
  792. {
  793. getGlobal(globalKey);
  794. if(!isNil()) {
  795. assert(isTable() || isUserdata());
  796. getField(fieldKey);
  797. remove(-2);
  798. }
  799. }
  800. void LuaInterface::setGlobal(const std::string& key)
  801. {
  802. assert(hasIndex(-1));
  803. lua_setglobal(L, key.c_str());
  804. }
  805. void LuaInterface::rawGet(int index)
  806. {
  807. assert(hasIndex(index));
  808. lua_rawget(L, index);
  809. }
  810. void LuaInterface::rawGeti(int n, int index)
  811. {
  812. assert(hasIndex(index));
  813. lua_rawgeti(L, index, n);
  814. }
  815. void LuaInterface::rawSet(int index)
  816. {
  817. assert(hasIndex(index));
  818. lua_rawset(L, index);
  819. }
  820. void LuaInterface::rawSeti(int n, int index)
  821. {
  822. assert(hasIndex(index));
  823. lua_rawseti(L, index, n);
  824. }
  825. void LuaInterface::newTable()
  826. {
  827. lua_newtable(L);
  828. }
  829. void* LuaInterface::newUserdata(int size)
  830. {
  831. return lua_newuserdata(L, size);
  832. }
  833. void LuaInterface::pop(int n)
  834. {
  835. if(n > 0) {
  836. assert(hasIndex(-n));
  837. lua_pop(L, n);
  838. }
  839. }
  840. long LuaInterface::popInteger()
  841. {
  842. assert(hasIndex(-1));
  843. long v = toInteger(-1);
  844. pop();
  845. return v;
  846. }
  847. double LuaInterface::popNumber()
  848. {
  849. assert(hasIndex(-1));
  850. double v = toNumber(-1);
  851. pop();
  852. return v;
  853. }
  854. bool LuaInterface::popBoolean()
  855. {
  856. assert(hasIndex(-1));
  857. bool v = toBoolean(-1);
  858. pop();
  859. return v;
  860. }
  861. std::string LuaInterface::popString()
  862. {
  863. assert(hasIndex(-1));
  864. std::string v = toString(-1);
  865. pop();
  866. return v;
  867. }
  868. void* LuaInterface::popUserdata()
  869. {
  870. assert(hasIndex(-1));
  871. void* v = toUserdata(-1);
  872. pop();
  873. return v;
  874. }
  875. LuaObjectPtr LuaInterface::popObject()
  876. {
  877. assert(hasIndex(-1));
  878. LuaObjectPtr v = toObject(-1);
  879. pop();
  880. return v;
  881. }
  882. void* LuaInterface::popUpvalueUserdata()
  883. {
  884. return lua_touserdata(L, lua_upvalueindex(1));
  885. }
  886. void LuaInterface::pushNil()
  887. {
  888. lua_pushnil(L);
  889. checkStack();
  890. }
  891. void LuaInterface::pushInteger(long v)
  892. {
  893. lua_pushinteger(L, v);
  894. checkStack();
  895. }
  896. void LuaInterface::pushNumber(double v)
  897. {
  898. lua_pushnumber(L, v);
  899. checkStack();
  900. }
  901. void LuaInterface::pushBoolean(bool v)
  902. {
  903. lua_pushboolean(L, v);
  904. checkStack();
  905. }
  906. void LuaInterface::pushCString(const char* v)
  907. {
  908. assert(v);
  909. lua_pushstring(L, v);
  910. checkStack();
  911. }
  912. void LuaInterface::pushString(const std::string& v)
  913. {
  914. lua_pushlstring(L, v.c_str(), v.length());
  915. checkStack();
  916. }
  917. void LuaInterface::pushLightUserdata(void* p)
  918. {
  919. lua_pushlightuserdata(L, p);
  920. checkStack();
  921. }
  922. void LuaInterface::pushThread()
  923. {
  924. lua_pushthread(L);
  925. checkStack();
  926. }
  927. void LuaInterface::pushObject(const LuaObjectPtr& obj)
  928. {
  929. // fills a new userdata with a new LuaObjectPtr pointer
  930. new(newUserdata(sizeof(LuaObjectPtr))) LuaObjectPtr(obj);
  931. m_totalObjRefs++;
  932. obj->luaGetMetatable();
  933. if(isNil())
  934. g_logger.fatal(stdext::format("metatable for class '%s' not found, did you bind the C++ class?", obj->getClassName()));
  935. setMetatable();
  936. }
  937. void LuaInterface::pushCFunction(LuaCFunction func, int n)
  938. {
  939. lua_pushcclosure(L, func, n);
  940. checkStack();
  941. }
  942. void LuaInterface::pushCppFunction(const LuaCppFunction& func)
  943. {
  944. // create a pointer to func (this pointer will hold the function existence)
  945. new(newUserdata(sizeof(LuaCppFunctionPtr))) LuaCppFunctionPtr(new LuaCppFunction(func));
  946. m_totalFuncRefs++;
  947. // sets the userdata __gc metamethod, needed to free the function pointer when it gets collected
  948. newTable();
  949. pushCFunction(&LuaInterface::luaCollectCppFunction);
  950. setField("__gc");
  951. setMetatable();
  952. // actually pushes a C function callback that will call the cpp function
  953. pushCFunction(&LuaInterface::luaCppFunctionCallback, 1);
  954. }
  955. void LuaInterface::pushValue(int index)
  956. {
  957. assert(hasIndex(index));
  958. lua_pushvalue(L, index);
  959. checkStack();
  960. }
  961. bool LuaInterface::isNil(int index)
  962. {
  963. assert(hasIndex(index));
  964. return lua_isnil(L, index);
  965. }
  966. bool LuaInterface::isBoolean(int index)
  967. {
  968. assert(hasIndex(index));
  969. return lua_isboolean(L, index);
  970. }
  971. bool LuaInterface::isNumber(int index)
  972. {
  973. assert(hasIndex(index));
  974. return lua_isnumber(L, index);
  975. }
  976. bool LuaInterface::isString(int index)
  977. {
  978. assert(hasIndex(index));
  979. return lua_isstring(L, index);
  980. }
  981. bool LuaInterface::isTable(int index)
  982. {
  983. assert(hasIndex(index));
  984. return lua_istable(L, index);
  985. }
  986. bool LuaInterface::isFunction(int index)
  987. {
  988. assert(hasIndex(index));
  989. return lua_isfunction(L, index);
  990. }
  991. bool LuaInterface::isCFunction(int index)
  992. {
  993. assert(hasIndex(index));
  994. return lua_iscfunction(L, index);
  995. }
  996. bool LuaInterface::isUserdata(int index)
  997. {
  998. assert(hasIndex(index));
  999. return lua_isuserdata(L, index);
  1000. }
  1001. bool LuaInterface::toBoolean(int index)
  1002. {
  1003. assert(hasIndex(index));
  1004. return (bool)lua_toboolean(L, index);
  1005. }
  1006. int LuaInterface::toInteger(int index)
  1007. {
  1008. assert(hasIndex(index));
  1009. return lua_tointeger(L, index);
  1010. }
  1011. double LuaInterface::toNumber(int index)
  1012. {
  1013. assert(hasIndex(index));
  1014. return lua_tonumber(L, index);
  1015. }
  1016. const char* LuaInterface::toCString(int index)
  1017. {
  1018. assert(hasIndex(index));
  1019. return lua_tostring(L, index);
  1020. }
  1021. std::string LuaInterface::toString(int index)
  1022. {
  1023. assert(hasIndex(index));
  1024. std::string str;
  1025. size_t len;
  1026. const char *c_str = lua_tolstring(L, index, &len);
  1027. if(c_str && len > 0)
  1028. str.assign(c_str, len);
  1029. return str;
  1030. }
  1031. void* LuaInterface::toUserdata(int index)
  1032. {
  1033. assert(hasIndex(index));
  1034. return lua_touserdata(L, index);
  1035. }
  1036. LuaObjectPtr LuaInterface::toObject(int index)
  1037. {
  1038. assert(hasIndex(index));
  1039. if(isUserdata(index)) {
  1040. LuaObjectPtr* objRef = static_cast<LuaObjectPtr*>(toUserdata(index));
  1041. if(objRef && *objRef)
  1042. return *objRef;
  1043. }
  1044. return nullptr;
  1045. }
  1046. int LuaInterface::getTop()
  1047. {
  1048. return lua_gettop(L);
  1049. }
  1050. void LuaInterface::loadFiles(std::string directory, bool recursive, std::string contains)
  1051. {
  1052. for(const std::string& fileName : g_resources.listDirectoryFiles(directory)) {
  1053. std::string fullPath = directory + "/" + fileName;
  1054. if(recursive && g_resources.directoryExists(fullPath)) {
  1055. loadFiles(fullPath, true, contains);
  1056. continue;
  1057. }
  1058. if(!g_resources.isFileType(fileName, "lua"))
  1059. continue;
  1060. if(!contains.empty() && fileName.find(contains) == std::string::npos)
  1061. continue;
  1062. try {
  1063. g_lua.loadScript(fullPath);
  1064. g_lua.call(0, 0);
  1065. } catch(stdext::exception& e) {
  1066. g_lua.pushString(e.what());
  1067. g_lua.error();
  1068. }
  1069. }
  1070. }