LuaGlueGen.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. #!/usr/bin/python
  2. # Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  3. # All rights reserved.
  4. # Code licensed under the BSD License.
  5. # http://www.anki3d.org/LICENSE
  6. import os
  7. import optparse
  8. import xml.etree.ElementTree as et
  9. # Globals
  10. identation_level = 0
  11. out_file = None
  12. def parse_commandline():
  13. """ Parse the command line arguments """
  14. parser = optparse.OptionParser(usage="usage: %prog [options]", description="Create LUA bindings using XML")
  15. parser.add_option(
  16. "-i", "--input", dest="inp", type="string", help="specify the XML files to parse. Seperate with :")
  17. (options, args) = parser.parse_args()
  18. if not options.inp:
  19. parser.error("argument is missing")
  20. return options.inp.split(":")
  21. def type_sig(value):
  22. """ Calculate the signature of a type """
  23. return hash(value)
  24. def get_base_fname(path):
  25. """ From path/to/a/file.ext return the "file" """
  26. return os.path.splitext(os.path.basename(path))[0]
  27. def wglue(txt):
  28. """ Write glue code to the output """
  29. global out_file
  30. global identation_level
  31. out_file.write("%s%s\n" % ("\t" * identation_level, txt))
  32. def ident(number):
  33. """ Increase or recrease identation for the wglue """
  34. global identation_level
  35. identation_level += number
  36. def type_is_bool(type):
  37. """ Check if a type is boolean """
  38. return type == "Bool" or type == "bool"
  39. def type_is_number(type):
  40. """ Check if a type is number """
  41. numbers = [
  42. "U8", "U16", "U32", "U64", "I8", "I16", "I32", "I64", "U", "I", "PtrSize", "F32", "F64", "int", "unsigned",
  43. "unsigned int", "short", "unsigned short", "uint", "float", "double"
  44. ]
  45. it_is = False
  46. for num in numbers:
  47. if num == type:
  48. it_is = True
  49. break
  50. return it_is
  51. def parse_type_decl(arg_txt):
  52. """ Parse an arg text """
  53. tokens = arg_txt.split(" ")
  54. tokens_size = len(tokens)
  55. type = tokens[tokens_size - 1]
  56. type_len = len(type)
  57. is_ptr = False
  58. is_ref = False
  59. if type[type_len - 1] == "&":
  60. is_ref = True
  61. elif type[type_len - 1] == "*":
  62. is_ptr = True
  63. if is_ref or is_ptr:
  64. type = type[:-1]
  65. is_const = False
  66. if tokens[0] == "const":
  67. is_const = True
  68. return (type, is_ref, is_ptr, is_const)
  69. def ret(ret_el):
  70. """ Push return value """
  71. if ret_el is None:
  72. wglue("return 0;")
  73. return
  74. wglue("// Push return value")
  75. type_txt = ret_el.text
  76. (type, is_ref, is_ptr, is_const) = parse_type_decl(type_txt)
  77. if is_ptr:
  78. wglue("if(ANKI_UNLIKELY(ret == nullptr))")
  79. wglue("{")
  80. ident(1)
  81. wglue("lua_pushstring(l, \"Glue code returned nullptr\");")
  82. wglue("return -1;")
  83. ident(-1)
  84. wglue("}")
  85. wglue("")
  86. if type_is_bool(type):
  87. wglue("lua_pushboolean(l, ret);")
  88. elif type_is_number(type):
  89. wglue("lua_pushnumber(l, lua_Number(ret));")
  90. elif type == "char" or type == "CString":
  91. wglue("lua_pushstring(l, &ret[0]);")
  92. elif type == "Error":
  93. wglue("if(ANKI_UNLIKELY(ret))")
  94. wglue("{")
  95. ident(1)
  96. wglue("lua_pushstring(l, \"Glue code returned an error\");")
  97. wglue("return -1;")
  98. ident(-1)
  99. wglue("}")
  100. wglue("")
  101. wglue("lua_pushnumber(l, lua_Number(!!ret));")
  102. else:
  103. if is_ptr or is_ref:
  104. wglue("voidp = lua_newuserdata(l, sizeof(LuaUserData));")
  105. wglue("ud = static_cast<LuaUserData*>(voidp);")
  106. wglue("luaL_setmetatable(l, \"%s\");" % type)
  107. wglue("extern LuaUserDataTypeInfo luaUserDataTypeInfo%s;" % type)
  108. if is_ptr:
  109. wglue("ud->initPointed(&luaUserDataTypeInfo%s, const_cast<%s*>(ret));" % (type, type))
  110. elif is_ref:
  111. wglue("ud->initPointed(&luaUserDataTypeInfo%s, const_cast<%s*>(&ret));" % (type, type))
  112. else:
  113. wglue("size = LuaUserData::computeSizeForGarbageCollected<%s>();" % type)
  114. wglue("voidp = lua_newuserdata(l, size);")
  115. wglue("luaL_setmetatable(l, \"%s\");" % type)
  116. wglue("ud = static_cast<LuaUserData*>(voidp);")
  117. wglue("extern LuaUserDataTypeInfo luaUserDataTypeInfo%s;" % type)
  118. wglue("ud->initGarbageCollected(&luaUserDataTypeInfo%s);" % type)
  119. wglue("::new(ud->getData<%s>()) %s(std::move(ret));" % (type, type))
  120. wglue("")
  121. wglue("return 1;")
  122. def arg(arg_txt, stack_index, index):
  123. """ Write the pop code for a single argument """
  124. (type, is_ref, is_ptr, is_const) = parse_type_decl(arg_txt)
  125. if type_is_bool(type) or type_is_number(type):
  126. wglue("%s arg%d;" % (type, index))
  127. wglue("if(ANKI_UNLIKELY(LuaBinder::checkNumber(l, %d, arg%d)))" % (stack_index, index))
  128. wglue("{")
  129. ident(1)
  130. wglue("return -1;")
  131. ident(-1)
  132. wglue("}")
  133. elif type == "char" or type == "CString":
  134. wglue("const char* arg%d;" % index)
  135. wglue("if(ANKI_UNLIKELY(LuaBinder::checkString(l, %d, arg%d)))" % (stack_index, index))
  136. wglue("{")
  137. ident(1)
  138. wglue("return -1;")
  139. ident(-1)
  140. wglue("}")
  141. else:
  142. wglue("extern LuaUserDataTypeInfo luaUserDataTypeInfo%s;" % type)
  143. wglue("if(ANKI_UNLIKELY(LuaBinder::checkUserData(l, %d, luaUserDataTypeInfo%s, ud)))" % (stack_index, type))
  144. wglue("{")
  145. ident(1)
  146. wglue("return -1;")
  147. ident(-1)
  148. wglue("}")
  149. wglue("")
  150. wglue("%s* iarg%d = ud->getData<%s>();" % (type, index, type))
  151. if is_ptr:
  152. wglue("%s arg%d(iarg%d);" % (arg_txt, index, index))
  153. else:
  154. wglue("%s arg%d(*iarg%d);" % (arg_txt, index, index))
  155. def args(args_el, stack_index):
  156. """ Write the pop code for argument parsing and return the arg list """
  157. if args_el is None:
  158. return ""
  159. wglue("// Pop arguments")
  160. arg_index = 0
  161. # Do the work
  162. args_str = ""
  163. arg_index = 0
  164. for arg_el in args_el.iter("arg"):
  165. arg(arg_el.text, stack_index, arg_index)
  166. args_str += "arg%d, " % arg_index
  167. wglue("")
  168. stack_index += 1
  169. arg_index += 1
  170. if len(args_str) > 0:
  171. args_str = args_str[:-2]
  172. return args_str
  173. def count_args(args_el):
  174. """ Count the number of arguments """
  175. if args_el is None:
  176. return 0
  177. count = 0
  178. for arg_el in args_el.iter("arg"):
  179. count += 1
  180. return count
  181. def check_args(args_el, bias):
  182. """ Check number of args. Call that first because it throws error """
  183. if args_el is not None:
  184. count = bias + count_args(args_el)
  185. else:
  186. count = bias
  187. wglue("if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, %d)))" % count)
  188. wglue("{")
  189. ident(1)
  190. wglue("return -1;")
  191. ident(-1)
  192. wglue("}")
  193. wglue("")
  194. def get_meth_alias(meth_el):
  195. """ Return the method alias """
  196. meth_name = meth_el.get("name")
  197. if meth_name == "operator+":
  198. meth_alias = "__add"
  199. elif meth_name == "operator-":
  200. meth_alias = "__sub"
  201. elif meth_name == "operator*":
  202. meth_alias = "__mul"
  203. elif meth_name == "operator/":
  204. meth_alias = "__div"
  205. elif meth_name == "operator==":
  206. meth_alias = "__eq"
  207. elif meth_name == "operator<":
  208. meth_alias = "__lt"
  209. elif meth_name == "operator<=":
  210. meth_alias = "__le"
  211. elif meth_name == "operator>":
  212. meth_alias = "__gt"
  213. elif meth_name == "operator>=":
  214. meth_alias = "__ge"
  215. elif meth_name == "operator=":
  216. meth_alias = "copy"
  217. else:
  218. meth_alias = meth_name
  219. meth_alias_txt = meth_el.get("alias")
  220. if meth_alias_txt is not None:
  221. meth_alias = meth_alias_txt
  222. return meth_alias
  223. def write_local_vars():
  224. wglue("LuaUserData* ud;")
  225. wglue("(void)ud;")
  226. wglue("void* voidp;")
  227. wglue("(void)voidp;")
  228. wglue("PtrSize size;")
  229. wglue("(void)size;")
  230. wglue("")
  231. def method(class_name, meth_el):
  232. """ Handle a method """
  233. meth_name = meth_el.get("name")
  234. meth_alias = get_meth_alias(meth_el)
  235. wglue("/// Pre-wrap method %s::%s." % (class_name, meth_name))
  236. wglue("static inline int pwrap%s%s(lua_State* l)" % (class_name, meth_alias))
  237. wglue("{")
  238. ident(1)
  239. write_local_vars()
  240. check_args(meth_el.find("args"), 1)
  241. # Get this pointer
  242. wglue("// Get \"this\" as \"self\"")
  243. wglue("if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfo%s, ud))" % class_name)
  244. wglue("{")
  245. ident(1)
  246. wglue("return -1;")
  247. ident(-1)
  248. wglue("}")
  249. wglue("")
  250. wglue("%s* self = ud->getData<%s>();" % (class_name, class_name))
  251. wglue("")
  252. args_str = args(meth_el.find("args"), 2)
  253. # Return value
  254. ret_txt = None
  255. ret_el = meth_el.find("return")
  256. if ret_el is not None:
  257. ret_txt = ret_el.text
  258. # Method call
  259. wglue("// Call the method")
  260. call = meth_el.find("overrideCall")
  261. if call is not None:
  262. call = call.text
  263. if call is not None:
  264. wglue("%s" % call)
  265. else:
  266. if ret_txt is None:
  267. wglue("self->%s(%s);" % (meth_name, args_str))
  268. else:
  269. wglue("%s ret = self->%s(%s);" % (ret_txt, meth_name, args_str))
  270. wglue("")
  271. ret(ret_el)
  272. ident(-1)
  273. wglue("}")
  274. wglue("")
  275. # Write the actual function
  276. wglue("/// Wrap method %s::%s." % (class_name, meth_name))
  277. wglue("static int wrap%s%s(lua_State* l)" % (class_name, meth_alias))
  278. wglue("{")
  279. ident(1)
  280. wglue("int res = pwrap%s%s(l);" % (class_name, meth_alias))
  281. wglue("if(res >= 0)")
  282. wglue("{")
  283. ident(1)
  284. wglue("return res;")
  285. ident(-1)
  286. wglue("}")
  287. wglue("")
  288. wglue("lua_error(l);")
  289. wglue("return 0;")
  290. ident(-1)
  291. wglue("}")
  292. wglue("")
  293. def static_method(class_name, meth_el):
  294. """ Handle a static method """
  295. meth_name = meth_el.get("name")
  296. meth_alias = get_meth_alias(meth_el)
  297. wglue("/// Pre-wrap static method %s::%s." % (class_name, meth_name))
  298. wglue("static inline int pwrap%s%s(lua_State* l)" % (class_name, meth_alias))
  299. wglue("{")
  300. ident(1)
  301. write_local_vars()
  302. check_args(meth_el.find("args"), 0)
  303. # Args
  304. args_str = args(meth_el.find("args"), 1)
  305. # Return value
  306. ret_txt = None
  307. ret_el = meth_el.find("return")
  308. if ret_el is not None:
  309. ret_txt = ret_el.text
  310. # Method call
  311. wglue("// Call the method")
  312. if ret_txt is None:
  313. wglue("%s::%s(%s);" % (class_name, meth_name, args_str))
  314. else:
  315. wglue("%s ret = %s::%s(%s);" % (ret_txt, class_name, meth_name, args_str))
  316. wglue("")
  317. ret(ret_el)
  318. ident(-1)
  319. wglue("}")
  320. wglue("")
  321. # Write the actual function
  322. wglue("/// Wrap static method %s::%s." % (class_name, meth_name))
  323. wglue("static int wrap%s%s(lua_State* l)" % (class_name, meth_alias))
  324. wglue("{")
  325. ident(1)
  326. wglue("int res = pwrap%s%s(l);" % (class_name, meth_alias))
  327. wglue("if(res >= 0)")
  328. wglue("{")
  329. ident(1)
  330. wglue("return res;")
  331. ident(-1)
  332. wglue("}")
  333. wglue("")
  334. wglue("lua_error(l);")
  335. wglue("return 0;")
  336. ident(-1)
  337. wglue("}")
  338. wglue("")
  339. def constructor(constr_el, class_name, constructor_idx):
  340. """ Handle constructor """
  341. wglue("/// Pre-wrap constructor for %s." % (class_name))
  342. wglue("static inline int pwrap%sCtor%d(lua_State* l)" % (class_name, constructor_idx))
  343. wglue("{")
  344. ident(1)
  345. write_local_vars()
  346. check_args(constr_el.find("args"), 0)
  347. # Args
  348. args_str = args(constr_el.find("args"), 1)
  349. # Create new userdata
  350. wglue("// Create user data")
  351. wglue("size = LuaUserData::computeSizeForGarbageCollected<%s>();" % class_name)
  352. wglue("voidp = lua_newuserdata(l, size);")
  353. wglue("luaL_setmetatable(l, luaUserDataTypeInfo%s.m_typeName);" % class_name)
  354. wglue("ud = static_cast<LuaUserData*>(voidp);")
  355. wglue("extern LuaUserDataTypeInfo luaUserDataTypeInfo%s;" % class_name)
  356. wglue("ud->initGarbageCollected(&luaUserDataTypeInfo%s);" % class_name)
  357. wglue("::new(ud->getData<%s>()) %s(%s);" % (class_name, class_name, args_str))
  358. wglue("")
  359. wglue("return 1;")
  360. ident(-1)
  361. wglue("}")
  362. wglue("")
  363. def constructors(constructors_el, class_name):
  364. """ Wrap all constructors """
  365. idx = 0
  366. func_names_and_arg_counts = []
  367. # Create the pre-wrap C functions
  368. for constructor_el in constructors_el.iter("constructor"):
  369. arg_count = count_args(constructor_el.find("args"))
  370. # Iterate all arg counts and make sure there are no duplicates
  371. for i in range(idx):
  372. if func_names_and_arg_counts[i][1] == arg_count:
  373. raise Exception("Every constructor overload should have a unique arg count. class: %s" % class_name)
  374. constructor(constructor_el, class_name, idx)
  375. func_names_and_arg_counts.append(["pwrap%sCtor%d" % (class_name, idx), arg_count])
  376. idx += 1
  377. if idx == 0:
  378. raise Exception("Found no <constructor>")
  379. # Create the landing function
  380. wglue("/// Wrap constructors for %s." % class_name)
  381. wglue("static int wrap%sCtor(lua_State* l)" % class_name)
  382. wglue("{")
  383. ident(1)
  384. if idx == 1:
  385. wglue("int res = pwrap%sCtor0(l);" % class_name)
  386. else:
  387. wglue("// Chose the right overload")
  388. wglue("const int argCount = lua_gettop(l);")
  389. wglue("int res = 0;")
  390. wglue("switch(argCount)")
  391. wglue("{")
  392. for name_and_arg_count in func_names_and_arg_counts:
  393. func_name = name_and_arg_count[0]
  394. arg_count = name_and_arg_count[1]
  395. wglue("case %d:" % arg_count)
  396. wglue("res = %s(l); break;" % func_name)
  397. wglue("default:")
  398. wglue("lua_pushfstring(l, \"Wrong overloaded new. Wrong number of arguments: %d\", argCount);")
  399. wglue("res = -1;")
  400. wglue("}")
  401. wglue("")
  402. wglue("if(res >= 0)")
  403. wglue("{")
  404. ident(1)
  405. wglue("return res;")
  406. ident(-1)
  407. wglue("}")
  408. wglue("")
  409. wglue("lua_error(l);")
  410. wglue("return 0;")
  411. ident(-1)
  412. wglue("}")
  413. wglue("")
  414. def destructor(class_name):
  415. """ Create a destructor """
  416. wglue("/// Wrap destructor for %s." % (class_name))
  417. wglue("static int wrap%sDtor(lua_State* l)" % class_name)
  418. wglue("{")
  419. ident(1)
  420. write_local_vars()
  421. check_args(None, 1)
  422. wglue("if(ANKI_UNLIKELY(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfo%s, ud)))" % class_name)
  423. wglue("{")
  424. ident(1)
  425. wglue("return -1;")
  426. ident(-1)
  427. wglue("}")
  428. wglue("")
  429. wglue("if(ud->isGarbageCollected())")
  430. wglue("{")
  431. ident(1)
  432. wglue("%s* inst = ud->getData<%s>();" % (class_name, class_name))
  433. wglue("inst->~%s();" % class_name)
  434. ident(-1)
  435. wglue("}")
  436. wglue("")
  437. wglue("return 0;")
  438. ident(-1)
  439. wglue("}")
  440. wglue("")
  441. def class_(class_el):
  442. """ Create a class """
  443. class_name = class_el.get("name")
  444. # Write serializer
  445. serialize = class_el.get("serialize") is not None and class_el.get("serialize") == "true"
  446. if serialize:
  447. # Serialize
  448. serialize_cb_name = "serialize%s" % class_name
  449. wglue("/// Serialize %s" % class_name)
  450. wglue("static void %s(LuaUserData& self, void* data, PtrSize& size)" % serialize_cb_name)
  451. wglue("{")
  452. ident(1)
  453. wglue("%s* obj = self.getData<%s>();" % (class_name, class_name))
  454. wglue("obj->serialize(data, size);")
  455. ident(-1)
  456. wglue("}")
  457. wglue("")
  458. # Deserialize
  459. deserialize_cb_name = "deserialize%s" % class_name
  460. wglue("/// De-serialize %s" % class_name)
  461. wglue("static void %s(const void* data, LuaUserData& self)" % deserialize_cb_name)
  462. wglue("{")
  463. ident(1)
  464. wglue("ANKI_ASSERT(data);")
  465. wglue("%s* obj = self.getData<%s>();" % (class_name, class_name))
  466. wglue("::new(obj) %s();" % class_name)
  467. wglue("obj->deserialize(data);")
  468. ident(-1)
  469. wglue("}")
  470. wglue("")
  471. else:
  472. serialize_cb_name = "nullptr"
  473. deserialize_cb_name = "nullptr"
  474. # Write the type info
  475. wglue("LuaUserDataTypeInfo luaUserDataTypeInfo%s = {" % class_name)
  476. ident(1)
  477. wglue("%d, \"%s\", LuaUserData::computeSizeForGarbageCollected<%s>(), %s, %s" %
  478. (type_sig(class_name), class_name, class_name, serialize_cb_name, deserialize_cb_name))
  479. ident(-1)
  480. wglue("};")
  481. wglue("")
  482. # Specialize the getDataTypeInfoFor
  483. wglue("template<>")
  484. wglue("const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<%s>()" % class_name)
  485. wglue("{")
  486. ident(1)
  487. wglue("return luaUserDataTypeInfo%s;" % class_name)
  488. ident(-1)
  489. wglue("}")
  490. wglue("")
  491. # Constructor declarations
  492. has_constructor = False
  493. constructors_el = class_el.find("constructors")
  494. if constructors_el is not None:
  495. has_constructor = True
  496. constructors(constructors_el, class_name)
  497. # Destructor declarations
  498. if has_constructor:
  499. destructor(class_name)
  500. # Methods LUA C functions declarations
  501. meth_names_aliases = []
  502. meths_el = class_el.find("methods")
  503. if meths_el is not None:
  504. for meth_el in meths_el.iter("method"):
  505. is_static = meth_el.get("static")
  506. is_static = is_static is not None and is_static == "1"
  507. if is_static:
  508. static_method(class_name, meth_el)
  509. else:
  510. method(class_name, meth_el)
  511. meth_name = meth_el.get("name")
  512. meth_alias = get_meth_alias(meth_el)
  513. meth_names_aliases.append([meth_name, meth_alias, is_static])
  514. # Start class declaration
  515. wglue("/// Wrap class %s." % class_name)
  516. wglue("static inline void wrap%s(lua_State* l)" % class_name)
  517. wglue("{")
  518. ident(1)
  519. wglue("LuaBinder::createClass(l, &luaUserDataTypeInfo%s);" % class_name)
  520. # Register constructor
  521. if has_constructor:
  522. wglue("LuaBinder::pushLuaCFuncStaticMethod(l, luaUserDataTypeInfo%s.m_typeName, \"new\", wrap%sCtor);" %
  523. (class_name, class_name))
  524. # Register destructor
  525. if has_constructor:
  526. wglue("LuaBinder::pushLuaCFuncMethod(l, \"__gc\", wrap%sDtor);" % class_name)
  527. # Register methods
  528. if len(meth_names_aliases) > 0:
  529. for meth_name_alias in meth_names_aliases:
  530. meth_alias = meth_name_alias[1]
  531. is_static = meth_name_alias[2]
  532. if is_static:
  533. wglue("LuaBinder::pushLuaCFuncStaticMethod(l, luaUserDataTypeInfo%s.m_typeName, \"%s\", wrap%s%s);" %
  534. (class_name, meth_alias, class_name, meth_alias))
  535. else:
  536. wglue("LuaBinder::pushLuaCFuncMethod(l, \"%s\", wrap%s%s);" % (meth_alias, class_name, meth_alias))
  537. wglue("lua_settop(l, 0);")
  538. ident(-1)
  539. wglue("}")
  540. wglue("")
  541. def function(func_el):
  542. """ Handle a plain function """
  543. func_name = func_el.get("name")
  544. func_alias = get_meth_alias(func_el)
  545. wglue("/// Pre-wrap function %s." % func_name)
  546. wglue("static inline int pwrap%s(lua_State* l)" % func_alias)
  547. wglue("{")
  548. ident(1)
  549. write_local_vars()
  550. check_args(func_el.find("args"), 0)
  551. # Args
  552. args_str = args(func_el.find("args"), 1)
  553. # Return value
  554. ret_txt = None
  555. ret_el = func_el.find("return")
  556. if ret_el is not None:
  557. ret_txt = ret_el.text
  558. # Call
  559. wglue("// Call the function")
  560. call = func_el.find("overrideCall")
  561. if call is not None:
  562. call = call.text
  563. if call is not None:
  564. wglue("%s" % call)
  565. else:
  566. if ret_txt is None:
  567. wglue("%s(%s);" % (func_name, args_str))
  568. else:
  569. wglue("%s ret = %s(%s);" % (ret_txt, func_name, args_str))
  570. wglue("")
  571. ret(ret_el)
  572. ident(-1)
  573. wglue("}")
  574. wglue("")
  575. # Write the actual function
  576. wglue("/// Wrap function %s." % func_name)
  577. wglue("static int wrap%s(lua_State* l)" % func_alias)
  578. wglue("{")
  579. ident(1)
  580. wglue("int res = pwrap%s(l);" % func_alias)
  581. wglue("if(res >= 0)")
  582. wglue("{")
  583. ident(1)
  584. wglue("return res;")
  585. ident(-1)
  586. wglue("}")
  587. wglue("")
  588. wglue("lua_error(l);")
  589. wglue("return 0;")
  590. ident(-1)
  591. wglue("}")
  592. wglue("")
  593. def main():
  594. """ Main function """
  595. global out_file
  596. filenames = parse_commandline()
  597. for filename in filenames:
  598. out_filename = get_base_fname(filename) + ".cpp"
  599. out_file = open(out_filename, "w")
  600. tree = et.parse(filename)
  601. root = tree.getroot()
  602. # Head
  603. head = root.find("head")
  604. if head is not None:
  605. wglue("%s" % head.text)
  606. wglue("")
  607. # Classes
  608. class_names = []
  609. for cls in root.iter("classes"):
  610. for cl in cls.iter("class"):
  611. class_(cl)
  612. class_names.append(cl.get("name"))
  613. # Functions
  614. func_names = []
  615. for fs in root.iter("functions"):
  616. for f in fs.iter("function"):
  617. function(f)
  618. func_names.append(f.get("name"))
  619. # Wrap function
  620. wglue("/// Wrap the module.")
  621. wglue("void wrapModule%s(lua_State* l)" % get_base_fname(filename))
  622. wglue("{")
  623. ident(1)
  624. for class_name in class_names:
  625. wglue("wrap%s(l);" % class_name)
  626. for func_name in func_names:
  627. wglue("LuaBinder::pushLuaCFunc(l, \"%s\", wrap%s);" % (func_name, func_name))
  628. ident(-1)
  629. wglue("}")
  630. wglue("")
  631. # Tail
  632. tail = root.find("tail")
  633. if tail is not None:
  634. wglue("%s" % tail.text)
  635. wglue("")
  636. out_file.close()
  637. if __name__ == "__main__":
  638. main()