tolua_map.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. /* tolua: functions to map features
  2. ** Support code for Lua bindings.
  3. ** Written by Waldemar Celes
  4. ** TeCGraf/PUC-Rio
  5. ** Apr 2003
  6. ** $Id: $
  7. */
  8. /* This code is free software; you can redistribute it and/or modify it.
  9. ** The software provided hereunder is on an "as is" basis, and
  10. ** the author has no obligation to provide maintenance, support, updates,
  11. ** enhancements, or modifications.
  12. */
  13. #include "tolua++.h"
  14. #include "tolua_event.h"
  15. #include "lauxlib.h"
  16. #include <string.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <math.h>
  20. /* Create metatable
  21. * Create and register new metatable
  22. */
  23. static int tolua_newmetatable (lua_State* L, const char* name)
  24. {
  25. int r = luaL_newmetatable(L,name);
  26. #ifdef LUA_VERSION_NUM /* only lua 5.1 */
  27. if (r) {
  28. lua_pushvalue(L, -1);
  29. lua_pushstring(L, name);
  30. lua_settable(L, LUA_REGISTRYINDEX); /* reg[mt] = type_name */
  31. };
  32. #endif
  33. if (r)
  34. tolua_classevents(L); /* set meta events */
  35. // metatable[".classname"] = name
  36. lua_pushliteral(L, ".classname"); // stack: metatable ".classname"
  37. lua_pushstring(L, name); // stack: metatable ".classname" name
  38. lua_rawset(L, -3); // stack: metatable
  39. lua_pop(L,1);
  40. return r;
  41. }
  42. /* Map super classes
  43. * It sets 'name' as being also a 'base', mapping all super classes of 'base' in 'name'
  44. */
  45. static void mapsuper (lua_State* L, const char* name, const char* base)
  46. {
  47. /* push registry.super */
  48. lua_pushstring(L,"tolua_super");
  49. lua_rawget(L,LUA_REGISTRYINDEX); /* stack: super */
  50. luaL_getmetatable(L,name); /* stack: super mt */
  51. lua_rawget(L,-2); /* stack: super table */
  52. if (lua_isnil(L,-1))
  53. {
  54. /* create table */
  55. lua_pop(L,1);
  56. lua_newtable(L); /* stack: super table */
  57. luaL_getmetatable(L,name); /* stack: super table mt */
  58. lua_pushvalue(L,-2); /* stack: super table mt table */
  59. lua_rawset(L,-4); /* stack: super table */
  60. }
  61. /* set base as super class */
  62. lua_pushstring(L,base);
  63. lua_pushboolean(L,1);
  64. lua_rawset(L,-3); /* stack: super table */
  65. /* set all super class of base as super class of name */
  66. luaL_getmetatable(L,base); /* stack: super table base_mt */
  67. lua_rawget(L,-3); /* stack: super table base_table */
  68. if (lua_istable(L,-1))
  69. {
  70. /* traverse base table */
  71. lua_pushnil(L); /* first key */
  72. while (lua_next(L,-2) != 0)
  73. {
  74. /* stack: ... base_table key value */
  75. lua_pushvalue(L,-2); /* stack: ... base_table key value key */
  76. lua_insert(L,-2); /* stack: ... base_table key key value */
  77. lua_rawset(L,-5); /* stack: ... base_table key */
  78. }
  79. }
  80. lua_pop(L,3); /* stack: <empty> */
  81. }
  82. /* creates a 'tolua_ubox' table for base clases, and
  83. // expects the metatable and base metatable on the stack */
  84. static void set_ubox(lua_State* L) {
  85. /* mt basemt */
  86. if (!lua_isnil(L, -1)) {
  87. lua_pushstring(L, "tolua_ubox");
  88. lua_rawget(L,-2);
  89. } else {
  90. lua_pushnil(L);
  91. };
  92. /* mt basemt base_ubox */
  93. if (!lua_isnil(L,-1)) {
  94. lua_pushstring(L, "tolua_ubox");
  95. lua_insert(L, -2);
  96. /* mt basemt key ubox */
  97. lua_rawset(L,-4);
  98. /* (mt with ubox) basemt */
  99. } else {
  100. /* mt basemt nil */
  101. lua_pop(L, 1);
  102. lua_pushstring(L,"tolua_ubox");
  103. lua_newtable(L);
  104. /* make weak value metatable for ubox table to allow userdata to be
  105. garbage-collected */
  106. lua_newtable(L);
  107. lua_pushliteral(L, "__mode");
  108. lua_pushliteral(L, "v");
  109. lua_rawset(L, -3); /* stack: string ubox mt */
  110. lua_setmetatable(L, -2); /* stack:mt basemt string ubox */
  111. lua_rawset(L,-4);
  112. };
  113. };
  114. /* Map inheritance
  115. * It sets 'name' as derived from 'base' by setting 'base' as metatable of 'name'
  116. */
  117. static void mapinheritance (lua_State* L, const char* name, const char* base)
  118. {
  119. /* set metatable inheritance */
  120. luaL_getmetatable(L,name);
  121. if (base && *base)
  122. luaL_getmetatable(L,base);
  123. else {
  124. if (lua_getmetatable(L, -1)) { /* already has a mt, we don't overwrite it */
  125. lua_pop(L, 2);
  126. return;
  127. };
  128. luaL_getmetatable(L,"tolua_commonclass");
  129. };
  130. set_ubox(L);
  131. lua_setmetatable(L,-2);
  132. lua_pop(L,1);
  133. }
  134. /* Object type
  135. */
  136. static int tolua_bnd_type (lua_State* L)
  137. {
  138. tolua_typename(L,lua_gettop(L));
  139. return 1;
  140. }
  141. /* Take ownership
  142. */
  143. static int tolua_bnd_takeownership (lua_State* L)
  144. {
  145. int success = 0;
  146. if (lua_isuserdata(L,1))
  147. {
  148. if (lua_getmetatable(L,1)) /* if metatable? */
  149. {
  150. lua_pop(L,1); /* clear metatable off stack */
  151. /* force garbage collection to avoid C to reuse a to-be-collected address */
  152. #ifdef LUA_VERSION_NUM
  153. lua_gc(L, LUA_GCCOLLECT, 0);
  154. #else
  155. lua_setgcthreshold(L,0);
  156. #endif
  157. success = tolua_register_gc(L,1);
  158. }
  159. }
  160. lua_pushboolean(L,success!=0);
  161. return 1;
  162. }
  163. /* Release ownership
  164. */
  165. static int tolua_bnd_releaseownership (lua_State* L)
  166. {
  167. int done = 0;
  168. if (lua_isuserdata(L,1))
  169. {
  170. void* u = *((void**)lua_touserdata(L,1));
  171. /* force garbage collection to avoid releasing a to-be-collected address */
  172. #ifdef LUA_VERSION_NUM
  173. lua_gc(L, LUA_GCCOLLECT, 0);
  174. #else
  175. lua_setgcthreshold(L,0);
  176. #endif
  177. lua_pushstring(L,"tolua_gc");
  178. lua_rawget(L,LUA_REGISTRYINDEX);
  179. lua_pushlightuserdata(L,u);
  180. lua_rawget(L,-2);
  181. lua_getmetatable(L,1);
  182. if (lua_rawequal(L,-1,-2)) /* check that we are releasing the correct type */
  183. {
  184. lua_pushlightuserdata(L,u);
  185. lua_pushnil(L);
  186. lua_rawset(L,-5);
  187. done = 1;
  188. }
  189. }
  190. lua_pushboolean(L,done!=0);
  191. return 1;
  192. }
  193. /* Type casting
  194. */
  195. int tolua_bnd_cast (lua_State* L)
  196. {
  197. /* // old code
  198. void* v = tolua_tousertype(L,1,NULL);
  199. const char* s = tolua_tostring(L,2,NULL);
  200. if (v && s)
  201. tolua_pushusertype(L,v,s);
  202. else
  203. lua_pushnil(L);
  204. return 1;
  205. */
  206. void* v;
  207. const char* s;
  208. if (lua_islightuserdata(L, 1)) {
  209. v = tolua_touserdata(L, 1, NULL);
  210. } else {
  211. v = tolua_tousertype(L, 1, 0);
  212. };
  213. s = tolua_tostring(L,2,NULL);
  214. if (v && s)
  215. tolua_pushusertype(L,v,s);
  216. else
  217. lua_pushnil(L);
  218. return 1;
  219. }
  220. /* Test userdata is null
  221. */
  222. static int tolua_bnd_isnulluserdata (lua_State* L) {
  223. void **ud = (void**)lua_touserdata(L, -1);
  224. tolua_pushboolean(L, ud == NULL || *ud == NULL);
  225. return 1;
  226. }
  227. /* Inheritance
  228. */
  229. static int tolua_bnd_inherit (lua_State* L) {
  230. /* stack: lua object, c object */
  231. lua_pushstring(L, ".c_instance");
  232. lua_pushvalue(L, -2);
  233. lua_rawset(L, -4);
  234. /* l_obj[".c_instance"] = c_obj */
  235. return 0;
  236. };
  237. #ifdef LUA_VERSION_NUM /* lua 5.1 */
  238. static int tolua_bnd_setpeer(lua_State* L) {
  239. /* stack: userdata, table */
  240. if (!lua_isuserdata(L, -2)) {
  241. lua_pushstring(L, "Invalid argument #1 to setpeer: userdata expected.");
  242. lua_error(L);
  243. };
  244. if (lua_isnil(L, -1)) {
  245. lua_pop(L, 1);
  246. lua_pushvalue(L, TOLUA_NOPEER);
  247. };
  248. lua_setfenv(L, -2);
  249. return 0;
  250. };
  251. static int tolua_bnd_getpeer(lua_State* L) {
  252. /* stack: userdata */
  253. lua_getfenv(L, -1);
  254. if (lua_rawequal(L, -1, TOLUA_NOPEER)) {
  255. lua_pop(L, 1);
  256. lua_pushnil(L);
  257. };
  258. return 1;
  259. };
  260. #endif
  261. /* Get the index which have been override
  262. 2014.6.5 by SunLightJuly
  263. */
  264. static int tolua_bnd_getcfunction(lua_State* L) {
  265. if (!lua_isstring(L, 2)) {
  266. lua_pushstring(L, "Invalid argument #2 to getcfunction: string expected.");
  267. lua_error(L);
  268. }
  269. if (!lua_getmetatable(L, 1)) {
  270. lua_pushstring(L, "Invalid argument #1 to getcfunction: class or object expected.");
  271. lua_error(L);
  272. }
  273. /* stack: class key mt */
  274. while (1) {
  275. lua_pushstring(L, ".backup");
  276. lua_rawget(L, -2); /* stack: class key mt mt[".backup"] */
  277. if (!lua_isnil(L, -1)) {
  278. lua_pushvalue(L, 2); /* stack: class key mt mt[".backup"] key */
  279. lua_rawget(L, -2);
  280. if (!lua_isnil(L, -1)) { // key had been found
  281. return 1;
  282. }
  283. lua_pop(L, 1);
  284. }
  285. lua_pop(L, 1); /* stack: class key mt */
  286. if (!lua_getmetatable(L, -1)) {
  287. break;
  288. }
  289. /* stack: class key mt base_mt */
  290. lua_remove(L, -2); /* stack: class key base_mt */
  291. }
  292. return 0;
  293. }
  294. static int tolua_bnd_iskindof(lua_State *L)
  295. {
  296. tolua_Error tolua_err;
  297. const char *type = luaL_checkstring(L, 2);
  298. if (lua_gettop(L) < 2)
  299. {
  300. lua_pushstring(L, "Miss arguments to iskindof.");
  301. lua_error(L);
  302. }
  303. if (!lua_getmetatable(L, 1)) {
  304. lua_pushstring(L, "Invalid argument #1 to iskindof: class or object expected.");
  305. lua_error(L);
  306. }
  307. if (!type)
  308. {
  309. lua_pushstring(L, "Invalid argument #2 to iskindof: string expected.");
  310. lua_error(L);
  311. }
  312. lua_pushboolean(L, tolua_isusertype(L, 1, type, 0, &tolua_err));
  313. return 1;
  314. }
  315. /* static int class_gc_event (lua_State* L); */
  316. TOLUA_API void tolua_open (lua_State* L)
  317. {
  318. int top = lua_gettop(L);
  319. lua_pushstring(L,"tolua_opened");
  320. lua_rawget(L,LUA_REGISTRYINDEX);
  321. if (!lua_isboolean(L,-1))
  322. {
  323. lua_pushstring(L,"tolua_opened");
  324. lua_pushboolean(L,1);
  325. lua_rawset(L,LUA_REGISTRYINDEX);
  326. // create value root table
  327. lua_pushstring(L, TOLUA_VALUE_ROOT);
  328. lua_newtable(L);
  329. lua_rawset(L, LUA_REGISTRYINDEX);
  330. #ifndef LUA_VERSION_NUM /* only prior to lua 5.1 */
  331. /* create peer object table */
  332. lua_pushstring(L, "tolua_peers");
  333. lua_newtable(L);
  334. /* make weak key metatable for peers indexed by userdata object */
  335. lua_newtable(L);
  336. lua_pushliteral(L, "__mode");
  337. lua_pushliteral(L, "k");
  338. lua_rawset(L, -3); /* stack: string peers mt */
  339. lua_setmetatable(L, -2); /* stack: string peers */
  340. lua_rawset(L,LUA_REGISTRYINDEX);
  341. #endif
  342. /* create object ptr -> udata mapping table */
  343. lua_pushstring(L,"tolua_ubox");
  344. lua_newtable(L);
  345. /* make weak value metatable for ubox table to allow userdata to be
  346. garbage-collected */
  347. lua_newtable(L);
  348. lua_pushliteral(L, "__mode");
  349. lua_pushliteral(L, "v");
  350. lua_rawset(L, -3); /* stack: string ubox mt */
  351. lua_setmetatable(L, -2); /* stack: string ubox */
  352. lua_rawset(L,LUA_REGISTRYINDEX);
  353. // /* create object ptr -> class type mapping table */
  354. // lua_pushstring(L, "tolua_ptr2type");
  355. // lua_newtable(L);
  356. // lua_rawset(L, LUA_REGISTRYINDEX);
  357. lua_pushstring(L,"tolua_super");
  358. lua_newtable(L);
  359. lua_rawset(L,LUA_REGISTRYINDEX);
  360. lua_pushstring(L,"tolua_gc");
  361. lua_newtable(L);
  362. lua_rawset(L,LUA_REGISTRYINDEX);
  363. /* create gc_event closure */
  364. lua_pushstring(L, "tolua_gc_event");
  365. lua_pushstring(L, "tolua_gc");
  366. lua_rawget(L, LUA_REGISTRYINDEX);
  367. lua_pushstring(L, "tolua_super");
  368. lua_rawget(L, LUA_REGISTRYINDEX);
  369. lua_pushcclosure(L, class_gc_event, 2);
  370. lua_rawset(L, LUA_REGISTRYINDEX);
  371. tolua_newmetatable(L,"tolua_commonclass");
  372. tolua_module(L,NULL,0);
  373. tolua_beginmodule(L,NULL);
  374. tolua_module(L,"tolua",0);
  375. tolua_beginmodule(L,"tolua");
  376. tolua_function(L,"type",tolua_bnd_type);
  377. tolua_function(L,"takeownership",tolua_bnd_takeownership);
  378. tolua_function(L,"releaseownership",tolua_bnd_releaseownership);
  379. tolua_function(L,"cast",tolua_bnd_cast);
  380. tolua_function(L,"isnull",tolua_bnd_isnulluserdata);
  381. tolua_function(L,"inherit", tolua_bnd_inherit);
  382. #ifdef LUA_VERSION_NUM /* lua 5.1 */
  383. tolua_function(L, "setpeer", tolua_bnd_setpeer);
  384. tolua_function(L, "getpeer", tolua_bnd_getpeer);
  385. #endif
  386. tolua_function(L,"getcfunction", tolua_bnd_getcfunction);
  387. tolua_function(L,"iskindof", tolua_bnd_iskindof);
  388. tolua_endmodule(L);
  389. tolua_endmodule(L);
  390. }
  391. lua_settop(L,top);
  392. }
  393. /* Copy a C object
  394. */
  395. TOLUA_API void* tolua_copy (lua_State* L, void* value, unsigned int size)
  396. {
  397. void* clone = (void*)malloc(size);
  398. if (clone)
  399. memcpy(clone,value,size);
  400. else
  401. tolua_error(L,"insuficient memory",NULL);
  402. return clone;
  403. }
  404. /* Default collect function
  405. */
  406. TOLUA_API int tolua_default_collect (lua_State* tolua_S)
  407. {
  408. void* self = tolua_tousertype(tolua_S,1,0);
  409. free(self);
  410. return 0;
  411. }
  412. /* Do clone
  413. */
  414. TOLUA_API int tolua_register_gc (lua_State* L, int lo)
  415. {
  416. int success = 1;
  417. void *value = *(void **)lua_touserdata(L,lo);
  418. lua_pushstring(L,"tolua_gc");
  419. lua_rawget(L,LUA_REGISTRYINDEX);
  420. lua_pushlightuserdata(L,value);
  421. lua_rawget(L,-2);
  422. if (!lua_isnil(L,-1)) /* make sure that object is not already owned */
  423. success = 0;
  424. else
  425. {
  426. lua_pushlightuserdata(L,value);
  427. lua_getmetatable(L,lo);
  428. lua_rawset(L,-4);
  429. }
  430. lua_pop(L,2);
  431. return success;
  432. }
  433. /* Register a usertype
  434. * It creates the correspoding metatable in the registry, for both 'type' and 'const type'.
  435. * It maps 'const type' as being also a 'type'
  436. */
  437. TOLUA_API void tolua_usertype (lua_State* L, const char* type)
  438. {
  439. char ctype[128] = "const ";
  440. strncat(ctype,type,120);
  441. /* create both metatables */
  442. if (tolua_newmetatable(L,ctype) && tolua_newmetatable(L,type))
  443. mapsuper(L,type,ctype); /* 'type' is also a 'const type' */
  444. }
  445. /* Begin module
  446. * It pushes the module (or class) table on the stack
  447. */
  448. TOLUA_API void tolua_beginmodule (lua_State* L, const char* name)
  449. {
  450. if (name) { // ... module
  451. //---- now module[name] is a table, get it's metatable to store keys
  452. // get module[name]
  453. lua_pushstring(L,name); // ... module name
  454. lua_rawget(L,-2); // ... module module[name]
  455. // Is module[name] a class table?
  456. lua_pushliteral(L, ".isclass");
  457. lua_rawget(L, -2); // stack: ... module module[name] class_flag
  458. if (lua_isnil(L, -1)) {
  459. lua_pop(L, 1); // stack: ... module module[name]
  460. return; // not a class table, use origin table
  461. }
  462. lua_pop(L, 1); // stack: ... module class_table
  463. // get metatable
  464. if (lua_getmetatable(L, -1)) { // ... module class_table mt
  465. lua_remove(L, -2); // ... module mt
  466. }
  467. //---- by SunLightJuly, 2014.6.5
  468. } else {
  469. lua_pushvalue(L,LUA_GLOBALSINDEX);
  470. }
  471. }
  472. /* End module
  473. * It pops the module (or class) from the stack
  474. */
  475. TOLUA_API void tolua_endmodule (lua_State* L)
  476. {
  477. lua_pop(L,1);
  478. }
  479. /* Map module
  480. * It creates a new module
  481. */
  482. #if 1
  483. TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar)
  484. {
  485. if (name)
  486. {
  487. /* tolua module */
  488. lua_pushstring(L,name);
  489. lua_rawget(L,-2);
  490. if (!lua_istable(L,-1)) /* check if module already exists */
  491. {
  492. lua_pop(L,1);
  493. lua_newtable(L);
  494. lua_pushstring(L,name);
  495. lua_pushvalue(L,-2);
  496. lua_rawset(L,-4); /* assing module into module */
  497. }
  498. }
  499. else
  500. {
  501. /* global table */
  502. lua_pushvalue(L,LUA_GLOBALSINDEX);
  503. }
  504. if (hasvar)
  505. {
  506. if (!tolua_ismodulemetatable(L)) /* check if it already has a module metatable */
  507. {
  508. /* create metatable to get/set C/C++ variable */
  509. lua_newtable(L);
  510. tolua_moduleevents(L);
  511. if (lua_getmetatable(L,-2))
  512. lua_setmetatable(L,-2); /* set old metatable as metatable of metatable */
  513. lua_setmetatable(L,-2);
  514. }
  515. }
  516. lua_pop(L,1); /* pop module */
  517. }
  518. #else
  519. TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar)
  520. {
  521. if (name)
  522. {
  523. /* tolua module */
  524. lua_pushstring(L,name);
  525. lua_newtable(L);
  526. }
  527. else
  528. {
  529. /* global table */
  530. lua_pushvalue(L,LUA_GLOBALSINDEX);
  531. }
  532. if (hasvar)
  533. {
  534. /* create metatable to get/set C/C++ variable */
  535. lua_newtable(L);
  536. tolua_moduleevents(L);
  537. if (lua_getmetatable(L,-2))
  538. lua_setmetatable(L,-2); /* set old metatable as metatable of metatable */
  539. lua_setmetatable(L,-2);
  540. }
  541. if (name)
  542. lua_rawset(L,-3); /* assing module into module */
  543. else
  544. lua_pop(L,1); /* pop global table */
  545. }
  546. #endif
  547. static void push_collector(lua_State* L, const char* type, lua_CFunction col) {
  548. /* push collector function, but only if it's not NULL, or if there's no
  549. collector already */
  550. if (!col) return;
  551. luaL_getmetatable(L,type);
  552. lua_pushstring(L,".collector");
  553. /*
  554. if (!col) {
  555. lua_pushvalue(L, -1);
  556. lua_rawget(L, -3);
  557. if (!lua_isnil(L, -1)) {
  558. lua_pop(L, 3);
  559. return;
  560. };
  561. lua_pop(L, 1);
  562. };
  563. // */
  564. lua_pushcfunction(L,col);
  565. lua_rawset(L,-3);
  566. lua_pop(L, 1);
  567. };
  568. /* Map C class
  569. * It maps a C class, setting the appropriate inheritance and super classes.
  570. */
  571. TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name, const char* base, lua_CFunction col)
  572. {
  573. char cname[128] = "const ";
  574. char cbase[128] = "const ";
  575. strncat(cname,name,120);
  576. strncat(cbase,base,120);
  577. mapinheritance(L,name,base);
  578. mapinheritance(L,cname,name);
  579. mapsuper(L,cname,cbase);
  580. mapsuper(L,name,base);
  581. lua_pushstring(L,lname);
  582. push_collector(L, name, col);
  583. /*
  584. luaL_getmetatable(L,name);
  585. lua_pushstring(L,".collector");
  586. lua_pushcfunction(L,col);
  587. lua_rawset(L,-3);
  588. */
  589. //---- create a new class table, set it's metatable, and assign it to module
  590. lua_newtable(L); // stack: module lname table
  591. luaL_getmetatable(L,name); // stack: module lname table mt
  592. lua_setmetatable(L, -2); // stack: module lname table
  593. //Use a key named ".isclass" to be a flag of class_table
  594. lua_pushliteral(L, ".isclass");
  595. lua_pushboolean(L, 1);
  596. lua_rawset(L, -3); // stack: module lname table
  597. lua_rawset(L, -3); // stack: module
  598. //---- by SunLightJuly, 2014.6.5
  599. /* now we also need to store the collector table for the const
  600. instances of the class */
  601. push_collector(L, cname, col);
  602. /*
  603. luaL_getmetatable(L,cname);
  604. lua_pushstring(L,".collector");
  605. lua_pushcfunction(L,col);
  606. lua_rawset(L,-3);
  607. lua_pop(L,1);
  608. */
  609. }
  610. /* Add base
  611. * It adds additional base classes to a class (for multiple inheritance)
  612. * (not for now)
  613. */
  614. TOLUA_API void tolua_addbase(lua_State* L, char* name, char* base) {
  615. char cname[128] = "const ";
  616. char cbase[128] = "const ";
  617. strncat(cname,name,120);
  618. strncat(cbase,base,120);
  619. mapsuper(L,cname,cbase);
  620. mapsuper(L,name,base);
  621. };
  622. /* Map function
  623. * It assigns a function into the current module (or class)
  624. */
  625. TOLUA_API void tolua_function (lua_State* L, const char* name, lua_CFunction func)
  626. {
  627. lua_pushstring(L,name);
  628. lua_pushcfunction(L,func);
  629. lua_rawset(L,-3);
  630. }
  631. /* sets the __call event for the class (expects the class' main table on top) */
  632. /* never really worked :(
  633. TOLUA_API void tolua_set_call_event(lua_State* L, lua_CFunction func, char* type) {
  634. lua_getmetatable(L, -1);
  635. //luaL_getmetatable(L, type);
  636. lua_pushstring(L,"__call");
  637. lua_pushcfunction(L,func);
  638. lua_rawset(L,-3);
  639. lua_pop(L, 1);
  640. };
  641. */
  642. /* Map constant number
  643. * It assigns a constant number into the current module (or class)
  644. */
  645. TOLUA_API void tolua_constant (lua_State* L, const char* name, lua_Number value)
  646. {
  647. lua_pushstring(L,name);
  648. tolua_pushnumber(L,value);
  649. lua_rawset(L,-3);
  650. }
  651. /* Map variable
  652. * It assigns a variable into the current module (or class)
  653. */
  654. TOLUA_API void tolua_variable (lua_State* L, const char* name, lua_CFunction get, lua_CFunction set)
  655. {
  656. /* get func */
  657. lua_pushstring(L,".get");
  658. lua_rawget(L,-2);
  659. if (!lua_istable(L,-1))
  660. {
  661. /* create .get table, leaving it at the top */
  662. lua_pop(L,1);
  663. lua_newtable(L);
  664. lua_pushstring(L,".get");
  665. lua_pushvalue(L,-2);
  666. lua_rawset(L,-4);
  667. }
  668. lua_pushstring(L,name);
  669. lua_pushcfunction(L,get);
  670. lua_rawset(L,-3); /* store variable */
  671. lua_pop(L,1); /* pop .get table */
  672. /* set func */
  673. if (set)
  674. {
  675. lua_pushstring(L,".set");
  676. lua_rawget(L,-2);
  677. if (!lua_istable(L,-1))
  678. {
  679. /* create .set table, leaving it at the top */
  680. lua_pop(L,1);
  681. lua_newtable(L);
  682. lua_pushstring(L,".set");
  683. lua_pushvalue(L,-2);
  684. lua_rawset(L,-4);
  685. }
  686. lua_pushstring(L,name);
  687. lua_pushcfunction(L,set);
  688. lua_rawset(L,-3); /* store variable */
  689. lua_pop(L,1); /* pop .set table */
  690. }
  691. }
  692. /* Access const array
  693. * It reports an error when trying to write into a const array
  694. */
  695. static int const_array (lua_State* L)
  696. {
  697. luaL_error(L,"value of const array cannot be changed");
  698. return 0;
  699. }
  700. /* Map an array
  701. * It assigns an array into the current module (or class)
  702. */
  703. TOLUA_API void tolua_array (lua_State* L, const char* name, lua_CFunction get, lua_CFunction set)
  704. {
  705. lua_pushstring(L,".get");
  706. lua_rawget(L,-2);
  707. if (!lua_istable(L,-1))
  708. {
  709. /* create .get table, leaving it at the top */
  710. lua_pop(L,1);
  711. lua_newtable(L);
  712. lua_pushstring(L,".get");
  713. lua_pushvalue(L,-2);
  714. lua_rawset(L,-4);
  715. }
  716. lua_pushstring(L,name);
  717. lua_newtable(L); /* create array metatable */
  718. lua_pushvalue(L,-1);
  719. lua_setmetatable(L,-2); /* set the own table as metatable (for modules) */
  720. lua_pushstring(L,"__index");
  721. lua_pushcfunction(L,get);
  722. lua_rawset(L,-3);
  723. lua_pushstring(L,"__newindex");
  724. lua_pushcfunction(L,set?set:const_array);
  725. lua_rawset(L,-3);
  726. lua_rawset(L,-3); /* store variable */
  727. lua_pop(L,1); /* pop .get table */
  728. }
  729. TOLUA_API void tolua_dobuffer(lua_State* L, char* B, unsigned int size, const char* name) {
  730. #ifdef LUA_VERSION_NUM /* lua 5.1 */
  731. if (!luaL_loadbuffer(L, B, size, name)) lua_pcall(L, 0, 0, 0);
  732. #else
  733. lua_dobuffer(L, B, size, name);
  734. #endif
  735. };