interfaceMakerPythonObj.cxx 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. // Filename: interfaceMakerPythonObj.cxx
  2. // Created by: drose (19Sep01)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
  8. //
  9. // All use of this software is subject to the terms of the Panda 3d
  10. // Software license. You should have received a copy of this license
  11. // along with this source code; you will also find a current copy of
  12. // the license at http://www.panda3d.org/license.txt .
  13. //
  14. // To contact the maintainers of this program write to
  15. // [email protected] .
  16. //
  17. ////////////////////////////////////////////////////////////////////
  18. #include "interfaceMakerPythonObj.h"
  19. #include "interrogateBuilder.h"
  20. #include "interrogate.h"
  21. #include "functionRemap.h"
  22. #include "parameterRemapUnchanged.h"
  23. #include "typeManager.h"
  24. #include "functionWriterPtrFromPython.h"
  25. #include "functionWriterPtrToPython.h"
  26. #include "interrogateDatabase.h"
  27. #include "interrogateType.h"
  28. #include "interrogateFunction.h"
  29. #include "cppFunctionType.h"
  30. ////////////////////////////////////////////////////////////////////
  31. // Function: InterfaceMakerPythonObj::Constructor
  32. // Access: Public
  33. // Description:
  34. ////////////////////////////////////////////////////////////////////
  35. InterfaceMakerPythonObj::
  36. InterfaceMakerPythonObj(InterrogateModuleDef *def) :
  37. InterfaceMakerPython(def)
  38. {
  39. }
  40. ////////////////////////////////////////////////////////////////////
  41. // Function: InterfaceMakerPythonObj::Destructor
  42. // Access: Public, Virtual
  43. // Description:
  44. ////////////////////////////////////////////////////////////////////
  45. InterfaceMakerPythonObj::
  46. ~InterfaceMakerPythonObj() {
  47. }
  48. ////////////////////////////////////////////////////////////////////
  49. // Function: InterfaceMakerPythonObj::write_prototypes
  50. // Access: Public, Virtual
  51. // Description: Generates the list of function prototypes
  52. // corresponding to the functions that will be output in
  53. // write_functions().
  54. ////////////////////////////////////////////////////////////////////
  55. void InterfaceMakerPythonObj::
  56. write_prototypes(ostream &out) {
  57. Functions::iterator fi;
  58. for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
  59. Function *func = (*fi);
  60. write_prototype_for(out, func);
  61. }
  62. out << "\n";
  63. InterfaceMakerPython::write_prototypes(out);
  64. }
  65. ////////////////////////////////////////////////////////////////////
  66. // Function: InterfaceMakerPythonObj::write_functions
  67. // Access: Public, Virtual
  68. // Description: Generates the list of functions that are appropriate
  69. // for this interface. This function is called *before*
  70. // write_prototypes(), above.
  71. ////////////////////////////////////////////////////////////////////
  72. void InterfaceMakerPythonObj::
  73. write_functions(ostream &out) {
  74. Functions::iterator fi;
  75. for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
  76. Function *func = (*fi);
  77. write_function_for(out, func);
  78. }
  79. InterfaceMakerPython::write_functions(out);
  80. // Finally, generate all the make-class-wrapper functions.
  81. Objects::iterator oi;
  82. for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
  83. Object *object = (*oi).second;
  84. write_class_wrapper(out, object);
  85. }
  86. }
  87. ////////////////////////////////////////////////////////////////////
  88. // Function: InterfaceMakerPythonObj::write_module
  89. // Access: Public, Virtual
  90. // Description: Generates whatever additional code is required to
  91. // support a module file.
  92. ////////////////////////////////////////////////////////////////////
  93. void InterfaceMakerPythonObj::
  94. write_module(ostream &out, InterrogateModuleDef *def) {
  95. InterfaceMakerPython::write_module(out, def);
  96. out << "static PyMethodDef python_obj_funcs[] = {\n";
  97. Objects::iterator oi;
  98. for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
  99. Object *object = (*oi).second;
  100. Functions::iterator fi;
  101. for (fi = object->_constructors.begin();
  102. fi != object->_constructors.end();
  103. ++fi) {
  104. Function *func = (*fi);
  105. out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_name
  106. << ", METH_VARARGS },\n";
  107. }
  108. }
  109. out << " { NULL, NULL }\n"
  110. << "};\n\n"
  111. << "#ifdef _WIN32\n"
  112. << "extern \"C\" __declspec(dllexport) void init" << def->library_name << "();\n"
  113. << "#else\n"
  114. << "extern \"C\" void init" << def->library_name << "();\n"
  115. << "#endif\n\n"
  116. << "void init" << def->library_name << "() {\n"
  117. << " Py_InitModule(\"" << def->library_name
  118. << "\", python_obj_funcs);\n"
  119. << "}\n\n";
  120. }
  121. ////////////////////////////////////////////////////////////////////
  122. // Function: InterfaceMakerPythonObj::synthesize_this_parameter
  123. // Access: Public, Virtual
  124. // Description: This method should be overridden and redefined to
  125. // return true for interfaces that require the implicit
  126. // "this" parameter, if present, to be passed as the
  127. // first parameter to any wrapper functions.
  128. ////////////////////////////////////////////////////////////////////
  129. bool InterfaceMakerPythonObj::
  130. synthesize_this_parameter() {
  131. return true;
  132. }
  133. ////////////////////////////////////////////////////////////////////
  134. // Function: InterfaceMakerPythonObj::get_builder_name
  135. // Access: Public, Static
  136. // Description: Returns the name of the InterfaceMaker function
  137. // generated to define the Python class for the
  138. // indicated struct type.
  139. ////////////////////////////////////////////////////////////////////
  140. string InterfaceMakerPythonObj::
  141. get_builder_name(CPPType *struct_type) {
  142. return "get_python_class_" +
  143. InterrogateBuilder::clean_identifier(struct_type->get_local_name(&parser));
  144. }
  145. ////////////////////////////////////////////////////////////////////
  146. // Function: InterfaceMakerPythonObj::get_wrapper_prefix
  147. // Access: Protected, Virtual
  148. // Description: Returns the prefix string used to generate wrapper
  149. // function names.
  150. ////////////////////////////////////////////////////////////////////
  151. string InterfaceMakerPythonObj::
  152. get_wrapper_prefix() {
  153. return "wpo_";
  154. }
  155. ////////////////////////////////////////////////////////////////////
  156. // Function: InterfaceMakerPythonObj::write_class_wrapper
  157. // Access: Private
  158. // Description: Writes a function that will define the Python class.
  159. ////////////////////////////////////////////////////////////////////
  160. void InterfaceMakerPythonObj::
  161. write_class_wrapper(ostream &out, InterfaceMaker::Object *object) {
  162. CPPType *struct_type = object->_itype._cpptype;
  163. if (struct_type == (CPPType *)NULL) {
  164. return;
  165. }
  166. string name = get_builder_name(struct_type);
  167. string python_name =
  168. InterrogateBuilder::clean_identifier(struct_type->get_simple_name());
  169. out << "/*\n"
  170. << " * Generate unique Python class for "
  171. << struct_type->get_local_name(&parser) << "\n"
  172. << " */\n"
  173. << "PyObject *\n"
  174. << name << "() {\n"
  175. << " static PyObject *wrapper = (PyObject *)NULL;\n"
  176. << " static PyMethodDef methods[] = {\n";
  177. int methods_size = 0;
  178. int class_methods_size = 0;
  179. Functions::iterator fi;
  180. for (fi = object->_methods.begin(); fi != object->_methods.end(); ++fi) {
  181. Function *func = (*fi);
  182. if (func->_has_this) {
  183. out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_name
  184. << ", METH_VARARGS },\n";
  185. methods_size++;
  186. }
  187. }
  188. out << " };\n"
  189. << " static const int methods_size = " << methods_size << ";\n\n"
  190. << " static PyMethodDef class_methods[] = {\n";
  191. for (fi = object->_methods.begin(); fi != object->_methods.end(); ++fi) {
  192. Function *func = (*fi);
  193. if (!func->_has_this) {
  194. out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_name
  195. << ", METH_VARARGS },\n";
  196. class_methods_size++;
  197. }
  198. }
  199. out << " };\n"
  200. << " static const int class_methods_size = " << class_methods_size << ";\n\n"
  201. << " if (wrapper == (PyObject *)NULL) {\n"
  202. << " int i;\n"
  203. << " PyObject *bases = PyTuple_New(0);\n"
  204. << " PyObject *dict = PyDict_New();\n"
  205. << " PyObject *name = PyString_FromString(\""
  206. << python_name << "\");\n"
  207. << " wrapper = PyClass_New(bases, dict, name);\n"
  208. << " for (i = 0; i < methods_size; i++) {\n"
  209. << " PyObject *function, *method;\n"
  210. << " function = PyCFunction_New(&methods[i], (PyObject *)NULL);\n"
  211. << " method = PyMethod_New(function, (PyObject *)NULL, wrapper);\n"
  212. << " PyDict_SetItemString(dict, methods[i].ml_name, method);\n"
  213. << " }\n"
  214. << " for (i = 0; i < class_methods_size; i++) {\n"
  215. << " PyObject *function;\n"
  216. << " function = PyCFunction_New(&class_methods[i], (PyObject *)NULL);\n"
  217. << " PyDict_SetItemString(dict, class_methods[i].ml_name, function);\n"
  218. << " }\n"
  219. << " }\n"
  220. << " return wrapper;\n"
  221. << "}\n\n";
  222. }
  223. ////////////////////////////////////////////////////////////////////
  224. // Function: InterfaceMakerPythonObj::write_prototype_for
  225. // Access: Private
  226. // Description: Writes the prototype for the indicated function.
  227. ////////////////////////////////////////////////////////////////////
  228. void InterfaceMakerPythonObj::
  229. write_prototype_for(ostream &out, InterfaceMaker::Function *func) {
  230. out << "static PyObject *"
  231. << func->_name << "(PyObject *self, PyObject *args);\n";
  232. }
  233. ////////////////////////////////////////////////////////////////////
  234. // Function: InterfaceMakerPythonObj::write_function_for
  235. // Access: Private
  236. // Description: Writes the definition for a function that will call
  237. // the indicated C++ function or method.
  238. ////////////////////////////////////////////////////////////////////
  239. void InterfaceMakerPythonObj::
  240. write_function_for(ostream &out, InterfaceMaker::Function *func) {
  241. Function::Remaps::const_iterator ri;
  242. out << "/*\n"
  243. << " * Python object wrapper for\n";
  244. for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
  245. FunctionRemap *remap = (*ri);
  246. out << " * ";
  247. remap->write_orig_prototype(out, 0);
  248. out << "\n";
  249. }
  250. out << " */\n";
  251. out << "static PyObject *"
  252. << func->_name << "(PyObject *, PyObject *args) {\n";
  253. // Now write out each instance of the overloaded function.
  254. string expected_params = "Arguments must match one of:";
  255. for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
  256. FunctionRemap *remap = (*ri);
  257. expected_params += "\\n ";
  258. write_function_instance(out, 2, func, remap, expected_params);
  259. }
  260. // If we get here in the generated code, none of the parameters were
  261. // valid. Generate an error exception. (We don't rely on the error
  262. // already generated by ParseTuple(), because it only reports the
  263. // error for one flavor of the function, whereas we might accept
  264. // multiple flavors for the different overloaded C++ function
  265. // signatures.
  266. out << " PyErr_SetString(PyExc_TypeError, \"" << expected_params << "\");\n"
  267. << " return (PyObject *)NULL;\n";
  268. out << "}\n\n";
  269. }
  270. ////////////////////////////////////////////////////////////////////
  271. // Function: InterfaceMakerPythonObj::write_function_instance
  272. // Access: Private
  273. // Description: Writes out the part of a function that handles a
  274. // single instance of an overloaded function.
  275. ////////////////////////////////////////////////////////////////////
  276. void InterfaceMakerPythonObj::
  277. write_function_instance(ostream &out, int indent_level,
  278. InterfaceMaker::Function *func,
  279. FunctionRemap *remap, string &expected_params) {
  280. indent(out, indent_level) << "{\n";
  281. indent(out, indent_level + 2) << "/* ";
  282. remap->write_orig_prototype(out, 0);
  283. out << " */\n\n";
  284. string format_specifiers;
  285. string parameter_list;
  286. vector_string pexprs;
  287. // Make one pass through the parameter list. We will output a
  288. // one-line temporary variable definition for each parameter, while
  289. // simultaneously building the ParseTuple() function call and also
  290. // the parameter expression list for call_function().
  291. expected_params += remap->_cppfunc->get_simple_name();
  292. expected_params += "(";
  293. int pn;
  294. for (pn = 0; pn < (int)remap->_parameters.size(); pn++) {
  295. if (pn != 0) {
  296. expected_params += ", ";
  297. }
  298. indent(out, indent_level + 2);
  299. CPPType *orig_type = remap->_parameters[pn]._remap->get_orig_type();
  300. CPPType *type = remap->_parameters[pn]._remap->get_new_type();
  301. string param_name = remap->get_parameter_name(pn);
  302. // This is the string to convert our local variable to the
  303. // appropriate C++ type. Normally this is just a cast.
  304. string pexpr_string =
  305. "(" + type->get_local_name(&parser) + ")" + param_name;
  306. if (remap->_parameters[pn]._remap->new_type_is_atomic_string()) {
  307. if (TypeManager::is_char_pointer(orig_type)) {
  308. out << "char *" << param_name;
  309. format_specifiers += "s";
  310. parameter_list += ", &" + param_name;
  311. } else {
  312. out << "char *" << param_name
  313. << "_str; int " << param_name << "_len";
  314. format_specifiers += "s#";
  315. parameter_list += ", &" + param_name
  316. + "_str, &" + param_name + "_len";
  317. pexpr_string = "basic_string<char>(" +
  318. param_name + "_str, " +
  319. param_name + "_len)";
  320. }
  321. expected_params += "string";
  322. } else if (TypeManager::is_bool(type)) {
  323. out << "PyObject *" << param_name;
  324. format_specifiers += "O";
  325. parameter_list += ", &" + param_name;
  326. pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)";
  327. expected_params += "bool";
  328. } else if (TypeManager::is_integer(type)) {
  329. out << "int " << param_name;
  330. format_specifiers += "i";
  331. parameter_list += ", &" + param_name;
  332. expected_params += "integer";
  333. } else if (TypeManager::is_float(type)) {
  334. out << "double " << param_name;
  335. format_specifiers += "d";
  336. parameter_list += ", &" + param_name;
  337. expected_params += "float";
  338. } else if (TypeManager::is_char_pointer(type)) {
  339. out << "char *" << param_name;
  340. format_specifiers += "s";
  341. parameter_list += ", &" + param_name;
  342. expected_params += "string";
  343. } else if (TypeManager::is_pointer(type)) {
  344. FunctionWriterPtrFromPython *writer = get_ptr_from_python(type);
  345. writer->get_pointer_type()->output_instance(out, param_name, &parser);
  346. format_specifiers += "O&";
  347. parameter_list += ", &" + writer->get_name() + ", &" + param_name;
  348. expected_params += writer->get_type()->get_preferred_name();
  349. } else {
  350. // Ignore a parameter.
  351. out << "PyObject *" << param_name;
  352. format_specifiers += "O";
  353. parameter_list += ", &" + param_name;
  354. expected_params += "any";
  355. }
  356. if (remap->_parameters[pn]._has_name) {
  357. expected_params += " " + remap->_parameters[pn]._name;
  358. }
  359. out << ";\n";
  360. pexprs.push_back(pexpr_string);
  361. }
  362. expected_params += ")";
  363. indent(out, indent_level + 2)
  364. << "if (PyArg_ParseTuple(args, \"" << format_specifiers
  365. << "\"" << parameter_list << ")) {\n";
  366. if (track_interpreter) {
  367. indent(out, indent_level + 4)
  368. << "in_interpreter = 0;\n";
  369. }
  370. if (!remap->_void_return &&
  371. remap->_return_type->new_type_is_atomic_string()) {
  372. // Treat strings as a special case. We don't want to format the
  373. // return expression.
  374. string return_expr =
  375. remap->call_function(out, indent_level + 4, false, "param0", pexprs);
  376. CPPType *type = remap->_return_type->get_orig_type();
  377. indent(out, indent_level + 4);
  378. type->output_instance(out, "return_value", &parser);
  379. out << " = " << return_expr << ";\n";
  380. if (track_interpreter) {
  381. indent(out, indent_level + 4)
  382. << "in_interpreter = 1;\n";
  383. }
  384. return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
  385. test_assert(out, indent_level + 4);
  386. pack_return_value(out, indent_level + 4, remap, return_expr);
  387. } else {
  388. string return_expr =
  389. remap->call_function(out, indent_level + 4, true, "param0", pexprs);
  390. if (return_expr.empty()) {
  391. if (track_interpreter) {
  392. indent(out, indent_level + 4)
  393. << "in_interpreter = 1;\n";
  394. }
  395. test_assert(out, indent_level + 4);
  396. indent(out, indent_level + 4)
  397. << "return Py_BuildValue(\"\");\n";
  398. } else {
  399. CPPType *type = remap->_return_type->get_temporary_type();
  400. indent(out, indent_level + 4);
  401. type->output_instance(out, "return_value", &parser);
  402. out << " = " << return_expr << ";\n";
  403. if (track_interpreter) {
  404. indent(out, indent_level + 4)
  405. << "in_interpreter = 1;\n";
  406. }
  407. return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
  408. test_assert(out, indent_level + 4);
  409. pack_return_value(out, indent_level + 4, remap, remap->_return_type->temporary_to_return(return_expr));
  410. }
  411. }
  412. indent(out, indent_level + 2) << "}\n";
  413. indent(out, indent_level + 2)
  414. << "PyErr_Clear();\n"; // Clear the error generated by ParseTuple()
  415. indent(out, indent_level)
  416. << "}\n";
  417. }
  418. ////////////////////////////////////////////////////////////////////
  419. // Function: InterfaceMakerPythonObj::pack_return_value
  420. // Access: Private
  421. // Description: Outputs a command to pack the indicated expression,
  422. // of the return_type type, as a Python return value.
  423. ////////////////////////////////////////////////////////////////////
  424. void InterfaceMakerPythonObj::
  425. pack_return_value(ostream &out, int indent_level,
  426. FunctionRemap *remap, string return_expr) {
  427. CPPType *orig_type = remap->_return_type->get_orig_type();
  428. CPPType *type = remap->_return_type->get_new_type();
  429. if (remap->_return_type->new_type_is_atomic_string()) {
  430. if (TypeManager::is_char_pointer(orig_type)) {
  431. indent(out, indent_level)
  432. << "return PyString_FromString(" << return_expr << ");\n";
  433. } else {
  434. indent(out, indent_level)
  435. << "return PyString_FromStringAndSize("
  436. << return_expr << ".data(), " << return_expr << ".length());\n";
  437. }
  438. } else if (TypeManager::is_integer(type)) {
  439. indent(out, indent_level)
  440. << "return PyInt_FromLong(" << return_expr << ");\n";
  441. } else if (TypeManager::is_float(type)) {
  442. indent(out, indent_level)
  443. << "return PyFloat_FromDouble(" << return_expr << ");\n";
  444. } else if (TypeManager::is_char_pointer(type)) {
  445. indent(out, indent_level)
  446. << "return PyString_FromString(" << return_expr << ");\n";
  447. } else if (TypeManager::is_pointer(type)) {
  448. bool caller_manages = remap->_return_value_needs_management;
  449. FunctionWriterPtrToPython *writer = get_ptr_to_python(type);
  450. indent(out, indent_level)
  451. << "return " << writer->get_name() << "(("
  452. << writer->get_pointer_type()->get_local_name(&parser) << ")"
  453. << return_expr << ", " << caller_manages << ");\n";
  454. } else {
  455. // Return None.
  456. indent(out, indent_level)
  457. << "return Py_BuildValue(\"\");\n";
  458. }
  459. }
  460. ////////////////////////////////////////////////////////////////////
  461. // Function: InterfaceMakerPythonObj::get_ptr_from_python
  462. // Access: Private
  463. // Description: Returns a FunctionWriter pointer suitable for
  464. // converting from a Python wrapper of the indicated
  465. // type to the corresponding C++ pointer.
  466. ////////////////////////////////////////////////////////////////////
  467. FunctionWriterPtrFromPython *InterfaceMakerPythonObj::
  468. get_ptr_from_python(CPPType *type) {
  469. PtrConverter::iterator ci;
  470. ci = _from_python.find(type);
  471. if (ci != _from_python.end()) {
  472. // We've previously used this type.
  473. return (FunctionWriterPtrFromPython *)(*ci).second;
  474. }
  475. FunctionWriter *writer =
  476. _function_writers.add_writer(new FunctionWriterPtrFromPython(type));
  477. _from_python.insert(PtrConverter::value_type(type, writer));
  478. return (FunctionWriterPtrFromPython *)writer;
  479. }
  480. ////////////////////////////////////////////////////////////////////
  481. // Function: InterfaceMakerPythonObj::get_ptr_to_python
  482. // Access: Private
  483. // Description: Returns a FunctionWriter pointer suitable for
  484. // converting from a C++ pointer of the indicated
  485. // type to the corresponding Python wrapper.
  486. ////////////////////////////////////////////////////////////////////
  487. FunctionWriterPtrToPython *InterfaceMakerPythonObj::
  488. get_ptr_to_python(CPPType *type) {
  489. PtrConverter::iterator ci;
  490. ci = _to_python.find(type);
  491. if (ci != _to_python.end()) {
  492. // We've previously used this type.
  493. return (FunctionWriterPtrToPython *)(*ci).second;
  494. }
  495. FunctionWriter *writer =
  496. _function_writers.add_writer(new FunctionWriterPtrToPython(type));
  497. _to_python.insert(PtrConverter::value_type(type, writer));
  498. return (FunctionWriterPtrToPython *)writer;
  499. }