Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

dtool/src/interrogate/interfaceMakerPythonObj.cxx

Go to the documentation of this file.
00001 // Filename: interfaceMakerPythonObj.cxx
00002 // Created by:  drose (19Sep01)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "interfaceMakerPythonObj.h"
00020 #include "interrogateBuilder.h"
00021 #include "interrogate.h"
00022 #include "functionRemap.h"
00023 #include "parameterRemapUnchanged.h"
00024 #include "typeManager.h"
00025 #include "functionWriterPtrFromPython.h"
00026 #include "functionWriterPtrToPython.h"
00027 
00028 #include "interrogateDatabase.h"
00029 #include "interrogateType.h"
00030 #include "interrogateFunction.h"
00031 #include "cppFunctionType.h"
00032 
00033 ////////////////////////////////////////////////////////////////////
00034 //     Function: InterfaceMakerPythonObj::Constructor
00035 //       Access: Public
00036 //  Description:
00037 ////////////////////////////////////////////////////////////////////
00038 InterfaceMakerPythonObj::
00039 InterfaceMakerPythonObj(InterrogateModuleDef *def) :
00040   InterfaceMakerPython(def)
00041 {
00042 }
00043 
00044 ////////////////////////////////////////////////////////////////////
00045 //     Function: InterfaceMakerPythonObj::Destructor
00046 //       Access: Public, Virtual
00047 //  Description:
00048 ////////////////////////////////////////////////////////////////////
00049 InterfaceMakerPythonObj::
00050 ~InterfaceMakerPythonObj() {
00051 }
00052 
00053 ////////////////////////////////////////////////////////////////////
00054 //     Function: InterfaceMakerPythonObj::write_prototypes
00055 //       Access: Public, Virtual
00056 //  Description: Generates the list of function prototypes
00057 //               corresponding to the functions that will be output in
00058 //               write_functions().
00059 ////////////////////////////////////////////////////////////////////
00060 void InterfaceMakerPythonObj::
00061 write_prototypes(ostream &out) {
00062   Functions::iterator fi;
00063   for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
00064     Function *func = (*fi);
00065     write_prototype_for(out, func);
00066   }
00067 
00068   out << "\n";
00069   InterfaceMakerPython::write_prototypes(out);
00070 }
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //     Function: InterfaceMakerPythonObj::write_functions
00074 //       Access: Public, Virtual
00075 //  Description: Generates the list of functions that are appropriate
00076 //               for this interface.  This function is called *before*
00077 //               write_prototypes(), above.
00078 ////////////////////////////////////////////////////////////////////
00079 void InterfaceMakerPythonObj::
00080 write_functions(ostream &out) {
00081   Functions::iterator fi;
00082   for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
00083     Function *func = (*fi);
00084     write_function_for(out, func);
00085   }
00086 
00087   InterfaceMakerPython::write_functions(out);
00088 
00089   // Finally, generate all the make-class-wrapper functions.
00090   Objects::iterator oi;
00091   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
00092     Object *object = (*oi).second;
00093 
00094     write_class_wrapper(out, object);
00095   }
00096 }
00097 
00098 ////////////////////////////////////////////////////////////////////
00099 //     Function: InterfaceMakerPythonObj::write_module
00100 //       Access: Public, Virtual
00101 //  Description: Generates whatever additional code is required to
00102 //               support a module file.
00103 ////////////////////////////////////////////////////////////////////
00104 void InterfaceMakerPythonObj::
00105 write_module(ostream &out, InterrogateModuleDef *def) {
00106   InterfaceMakerPython::write_module(out, def);
00107 
00108   out << "static PyMethodDef python_obj_funcs[] = {\n";
00109 
00110   Objects::iterator oi;
00111   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
00112     Object *object = (*oi).second;
00113 
00114     Functions::iterator fi;
00115     for (fi = object->_constructors.begin(); 
00116          fi != object->_constructors.end(); 
00117          ++fi) {
00118       Function *func = (*fi);
00119       out << "  { \"" << func->_ifunc.get_name() << "\", &" << func->_name 
00120           << ", METH_VARARGS },\n";
00121     }
00122   }  
00123   out << "  { NULL, NULL }\n"
00124       << "};\n\n"
00125 
00126       << "#ifdef _WIN32\n"
00127       << "extern \"C\" __declspec(dllexport) void init" << def->library_name << "();\n"
00128       << "#else\n"
00129       << "extern \"C\" void init" << def->library_name << "();\n"
00130       << "#endif\n\n"
00131     
00132       << "void init" << def->library_name << "() {\n"
00133       << "  Py_InitModule(\"" << def->library_name
00134       << "\", python_obj_funcs);\n"
00135       << "}\n\n";
00136 }
00137 
00138 ////////////////////////////////////////////////////////////////////
00139 //     Function: InterfaceMakerPythonObj::synthesize_this_parameter
00140 //       Access: Public, Virtual
00141 //  Description: This method should be overridden and redefined to
00142 //               return true for interfaces that require the implicit
00143 //               "this" parameter, if present, to be passed as the
00144 //               first parameter to any wrapper functions.
00145 ////////////////////////////////////////////////////////////////////
00146 bool InterfaceMakerPythonObj::
00147 synthesize_this_parameter() {
00148   return true;
00149 }
00150 
00151 ////////////////////////////////////////////////////////////////////
00152 //     Function: InterfaceMakerPythonObj::get_builder_name
00153 //       Access: Public, Static
00154 //  Description: Returns the name of the InterfaceMaker function
00155 //               generated to define the Python class for the
00156 //               indicated struct type.
00157 ////////////////////////////////////////////////////////////////////
00158 string InterfaceMakerPythonObj::
00159 get_builder_name(CPPType *struct_type) {
00160   return "get_python_class_" + 
00161     InterrogateBuilder::clean_identifier(struct_type->get_local_name(&parser));
00162 }
00163 
00164 ////////////////////////////////////////////////////////////////////
00165 //     Function: InterfaceMakerPythonObj::get_wrapper_prefix
00166 //       Access: Protected, Virtual
00167 //  Description: Returns the prefix string used to generate wrapper
00168 //               function names.
00169 ////////////////////////////////////////////////////////////////////
00170 string InterfaceMakerPythonObj::
00171 get_wrapper_prefix() {
00172   return "wpo_";
00173 }
00174 
00175 ////////////////////////////////////////////////////////////////////
00176 //     Function: InterfaceMakerPythonObj::write_class_wrapper
00177 //       Access: Private
00178 //  Description: Writes a function that will define the Python class.
00179 ////////////////////////////////////////////////////////////////////
00180 void InterfaceMakerPythonObj::
00181 write_class_wrapper(ostream &out, InterfaceMaker::Object *object) {
00182   CPPType *struct_type = object->_itype._cpptype;
00183   if (struct_type == (CPPType *)NULL) {
00184     return;
00185   }
00186 
00187   string name = get_builder_name(struct_type);
00188   string python_name =
00189     InterrogateBuilder::clean_identifier(struct_type->get_simple_name());
00190 
00191   out << "/*\n"
00192       << " * Generate unique Python class for "
00193       << struct_type->get_local_name(&parser) << "\n"
00194       << " */\n"
00195       << "PyObject *\n"
00196       << name << "() {\n"
00197       << "  static PyObject *wrapper = (PyObject *)NULL;\n"
00198       << "  static PyMethodDef methods[] = {\n";
00199 
00200   int methods_size = 0;
00201   int class_methods_size = 0;
00202 
00203   Functions::iterator fi;
00204   for (fi = object->_methods.begin(); fi != object->_methods.end(); ++fi) {
00205     Function *func = (*fi);
00206     if (func->_has_this) {
00207       out << "  { \"" << func->_ifunc.get_name() << "\", &" << func->_name 
00208           << ", METH_VARARGS },\n";
00209       methods_size++;
00210     }
00211   }
00212 
00213   out << "  };\n"
00214       << "  static const int methods_size = " << methods_size << ";\n\n"
00215       << "  static PyMethodDef class_methods[] = {\n";
00216 
00217   for (fi = object->_methods.begin(); fi != object->_methods.end(); ++fi) {
00218     Function *func = (*fi);
00219     if (!func->_has_this) {
00220       out << "  { \"" << func->_ifunc.get_name() << "\", &" << func->_name 
00221           << ", METH_VARARGS },\n";
00222       class_methods_size++;
00223     }
00224   }
00225 
00226   out << "  };\n"
00227       << "  static const int class_methods_size = " << class_methods_size << ";\n\n"
00228       << "  if (wrapper == (PyObject *)NULL) {\n"
00229       << "    int i;\n"
00230       << "    PyObject *bases = PyTuple_New(0);\n"
00231       << "    PyObject *dict = PyDict_New();\n"
00232       << "    PyObject *name = PyString_FromString(\""
00233       << python_name << "\");\n"
00234       << "    wrapper = PyClass_New(bases, dict, name);\n"
00235       << "    for (i = 0; i < methods_size; i++) {\n"
00236       << "      PyObject *function, *method;\n"
00237       << "      function = PyCFunction_New(&methods[i], (PyObject *)NULL);\n"
00238       << "      method = PyMethod_New(function, (PyObject *)NULL, wrapper);\n"
00239       << "      PyDict_SetItemString(dict, methods[i].ml_name, method);\n"
00240       << "    }\n"
00241       << "    for (i = 0; i < class_methods_size; i++) {\n"
00242       << "      PyObject *function;\n"
00243       << "      function = PyCFunction_New(&class_methods[i], (PyObject *)NULL);\n"
00244       << "      PyDict_SetItemString(dict, class_methods[i].ml_name, function);\n"
00245       << "    }\n"
00246       << "  }\n"
00247       << "  return wrapper;\n"
00248       << "}\n\n";
00249 }
00250 
00251 ////////////////////////////////////////////////////////////////////
00252 //     Function: InterfaceMakerPythonObj::write_prototype_for
00253 //       Access: Private
00254 //  Description: Writes the prototype for the indicated function.
00255 ////////////////////////////////////////////////////////////////////
00256 void InterfaceMakerPythonObj::
00257 write_prototype_for(ostream &out, InterfaceMaker::Function *func) {
00258   out << "static PyObject *"
00259       << func->_name << "(PyObject *self, PyObject *args);\n";
00260 }
00261 
00262 ////////////////////////////////////////////////////////////////////
00263 //     Function: InterfaceMakerPythonObj::write_function_for
00264 //       Access: Private
00265 //  Description: Writes the definition for a function that will call
00266 //               the indicated C++ function or method.
00267 ////////////////////////////////////////////////////////////////////
00268 void InterfaceMakerPythonObj::
00269 write_function_for(ostream &out, InterfaceMaker::Function *func) {
00270   Function::Remaps::const_iterator ri;
00271   out << "/*\n"
00272       << " * Python object wrapper for\n";
00273   for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
00274     FunctionRemap *remap = (*ri);
00275     out << " * ";
00276     remap->write_orig_prototype(out, 0);
00277     out << "\n";
00278   }
00279   out << " */\n";
00280 
00281   out << "static PyObject *"
00282       << func->_name << "(PyObject *, PyObject *args) {\n";
00283 
00284   // Now write out each instance of the overloaded function.
00285   string expected_params = "Arguments must match one of:";
00286 
00287   for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
00288     FunctionRemap *remap = (*ri);
00289     expected_params += "\\n  ";
00290     write_function_instance(out, 2, func, remap, expected_params);
00291   }
00292 
00293   // If we get here in the generated code, none of the parameters were
00294   // valid.  Generate an error exception.  (We don't rely on the error
00295   // already generated by ParseTuple(), because it only reports the
00296   // error for one flavor of the function, whereas we might accept
00297   // multiple flavors for the different overloaded C++ function
00298   // signatures.
00299 
00300   out << "  PyErr_SetString(PyExc_TypeError, \"" << expected_params << "\");\n"
00301       << "  return (PyObject *)NULL;\n";
00302 
00303   out << "}\n\n";
00304 }
00305 
00306 ////////////////////////////////////////////////////////////////////
00307 //     Function: InterfaceMakerPythonObj::write_function_instance
00308 //       Access: Private
00309 //  Description: Writes out the part of a function that handles a
00310 //               single instance of an overloaded function.
00311 ////////////////////////////////////////////////////////////////////
00312 void InterfaceMakerPythonObj::
00313 write_function_instance(ostream &out, int indent_level,
00314                         InterfaceMaker::Function *func,
00315                         FunctionRemap *remap, string &expected_params) {
00316   indent(out, indent_level) << "{\n";
00317   indent(out, indent_level + 2) << "/* ";
00318   remap->write_orig_prototype(out, 0);
00319   out << " */\n\n";
00320   
00321   string format_specifiers;
00322   string parameter_list;
00323   vector_string pexprs;
00324 
00325   // Make one pass through the parameter list.  We will output a
00326   // one-line temporary variable definition for each parameter, while
00327   // simultaneously building the ParseTuple() function call and also
00328   // the parameter expression list for call_function().
00329 
00330   expected_params += remap->_cppfunc->get_simple_name();
00331   expected_params += "(";
00332 
00333   int pn;
00334   for (pn = 0; pn < (int)remap->_parameters.size(); pn++) {
00335     if (pn != 0) {
00336       expected_params += ", ";
00337     }
00338 
00339     indent(out, indent_level + 2);
00340     CPPType *orig_type = remap->_parameters[pn]._remap->get_orig_type();
00341     CPPType *type = remap->_parameters[pn]._remap->get_new_type();
00342     string param_name = remap->get_parameter_name(pn);
00343     
00344     // This is the string to convert our local variable to the
00345     // appropriate C++ type.  Normally this is just a cast.
00346     string pexpr_string =
00347       "(" + type->get_local_name(&parser) + ")" + param_name;
00348     
00349     if (remap->_parameters[pn]._remap->new_type_is_atomic_string()) {
00350       if (TypeManager::is_char_pointer(orig_type)) {
00351         out << "char *" << param_name;
00352         format_specifiers += "s";
00353         parameter_list += ", &" + param_name;
00354         
00355       } else {
00356         out << "char *" << param_name
00357             << "_str; int " << param_name << "_len";
00358         format_specifiers += "s#";
00359         parameter_list += ", &" + param_name
00360           + "_str, &" + param_name + "_len";
00361         pexpr_string = "basic_string<char>(" +
00362           param_name + "_str, " +
00363           param_name + "_len)";
00364       }
00365       expected_params += "string";
00366       
00367     } else if (TypeManager::is_bool(type)) {
00368       out << "PyObject *" << param_name;
00369       format_specifiers += "O";
00370       parameter_list += ", &" + param_name;
00371       pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)";
00372       expected_params += "bool";
00373 
00374     } else if (TypeManager::is_integer(type)) {
00375       out << "int " << param_name;
00376       format_specifiers += "i";
00377       parameter_list += ", &" + param_name;
00378       expected_params += "integer";
00379 
00380     } else if (TypeManager::is_float(type)) {
00381       out << "double " << param_name;
00382       format_specifiers += "d";
00383       parameter_list += ", &" + param_name;
00384       expected_params += "float";
00385 
00386     } else if (TypeManager::is_char_pointer(type)) {
00387       out << "char *" << param_name;
00388       format_specifiers += "s";
00389       parameter_list += ", &" + param_name;
00390       expected_params += "string";
00391 
00392     } else if (TypeManager::is_pointer(type)) {
00393       FunctionWriterPtrFromPython *writer = get_ptr_from_python(type);
00394       writer->get_pointer_type()->output_instance(out, param_name, &parser);
00395       format_specifiers += "O&";
00396       parameter_list += ", &" + writer->get_name() + ", &" + param_name;
00397       expected_params += writer->get_type()->get_preferred_name();
00398 
00399     } else {
00400       // Ignore a parameter.
00401       out << "PyObject *" << param_name;
00402       format_specifiers += "O";
00403       parameter_list += ", &" + param_name;
00404       expected_params += "any";
00405     }
00406 
00407     if (remap->_parameters[pn]._has_name) {
00408       expected_params += " " + remap->_parameters[pn]._name;
00409     }
00410 
00411     out << ";\n";
00412     pexprs.push_back(pexpr_string);
00413   }
00414   expected_params += ")";
00415 
00416   indent(out, indent_level + 2)
00417     << "if (PyArg_ParseTuple(args, \"" << format_specifiers
00418     << "\"" << parameter_list << ")) {\n";
00419 
00420   if (track_interpreter) {
00421     indent(out, indent_level + 4)
00422       << "in_interpreter = 0;\n";
00423   }
00424 
00425   if (!remap->_void_return && 
00426       remap->_return_type->new_type_is_atomic_string()) {
00427     // Treat strings as a special case.  We don't want to format the
00428     // return expression.
00429     string return_expr = 
00430       remap->call_function(out, indent_level + 4, false, "param0", pexprs);
00431 
00432     CPPType *type = remap->_return_type->get_orig_type();
00433     indent(out, indent_level + 4);
00434     type->output_instance(out, "return_value", &parser);
00435     out << " = " << return_expr << ";\n";
00436 
00437     if (track_interpreter) {
00438       indent(out, indent_level + 4)
00439         << "in_interpreter = 1;\n";
00440     }
00441 
00442     return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
00443     test_assert(out, indent_level + 4);
00444     pack_return_value(out, indent_level + 4, remap, return_expr);
00445 
00446   } else {
00447     string return_expr = 
00448       remap->call_function(out, indent_level + 4, true, "param0", pexprs);
00449     if (return_expr.empty()) {
00450       if (track_interpreter) {
00451         indent(out, indent_level + 4)
00452           << "in_interpreter = 1;\n";
00453       }
00454       test_assert(out, indent_level + 4);
00455       indent(out, indent_level + 4)
00456         << "return Py_BuildValue(\"\");\n";
00457 
00458     } else {
00459       CPPType *type = remap->_return_type->get_temporary_type();
00460       indent(out, indent_level + 4);
00461       type->output_instance(out, "return_value", &parser);
00462       out << " = " << return_expr << ";\n";
00463       if (track_interpreter) {
00464         indent(out, indent_level + 4)
00465           << "in_interpreter = 1;\n";
00466       }
00467 
00468       return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
00469       test_assert(out, indent_level + 4);
00470       pack_return_value(out, indent_level + 4, remap, remap->_return_type->temporary_to_return(return_expr));
00471     }
00472   }
00473 
00474   indent(out, indent_level + 2) << "}\n";
00475   indent(out, indent_level + 2)
00476     << "PyErr_Clear();\n";  // Clear the error generated by ParseTuple()
00477   indent(out, indent_level)
00478     << "}\n";
00479 }
00480 
00481 ////////////////////////////////////////////////////////////////////
00482 //     Function: InterfaceMakerPythonObj::pack_return_value
00483 //       Access: Private
00484 //  Description: Outputs a command to pack the indicated expression,
00485 //               of the return_type type, as a Python return value.
00486 ////////////////////////////////////////////////////////////////////
00487 void InterfaceMakerPythonObj::
00488 pack_return_value(ostream &out, int indent_level,
00489                   FunctionRemap *remap, string return_expr) {
00490   CPPType *orig_type = remap->_return_type->get_orig_type();
00491   CPPType *type = remap->_return_type->get_new_type();
00492 
00493   if (remap->_return_type->new_type_is_atomic_string()) {
00494     if (TypeManager::is_char_pointer(orig_type)) {
00495       indent(out, indent_level)
00496         << "return PyString_FromString(" << return_expr << ");\n";
00497 
00498     } else {
00499       indent(out, indent_level)
00500         << "return PyString_FromStringAndSize("
00501         << return_expr << ".data(), " << return_expr << ".length());\n";
00502     }
00503 
00504   } else if (TypeManager::is_integer(type)) {
00505     indent(out, indent_level)
00506       << "return PyInt_FromLong(" << return_expr << ");\n";
00507 
00508   } else if (TypeManager::is_float(type)) {
00509     indent(out, indent_level)
00510       << "return PyFloat_FromDouble(" << return_expr << ");\n";
00511 
00512   } else if (TypeManager::is_char_pointer(type)) {
00513     indent(out, indent_level)
00514       << "return PyString_FromString(" << return_expr << ");\n";
00515 
00516   } else if (TypeManager::is_pointer(type)) {
00517     bool caller_manages = remap->_return_value_needs_management;
00518 
00519     FunctionWriterPtrToPython *writer = get_ptr_to_python(type);
00520     indent(out, indent_level)
00521       << "return " << writer->get_name() << "((" 
00522       << writer->get_pointer_type()->get_local_name(&parser) << ")"
00523       << return_expr << ", " << caller_manages << ");\n";
00524 
00525   } else {
00526     // Return None.
00527     indent(out, indent_level)
00528       << "return Py_BuildValue(\"\");\n";
00529   }
00530 }
00531 
00532 ////////////////////////////////////////////////////////////////////
00533 //     Function: InterfaceMakerPythonObj::get_ptr_from_python
00534 //       Access: Private
00535 //  Description: Returns a FunctionWriter pointer suitable for
00536 //               converting from a Python wrapper of the indicated
00537 //               type to the corresponding C++ pointer.
00538 ////////////////////////////////////////////////////////////////////
00539 FunctionWriterPtrFromPython *InterfaceMakerPythonObj::
00540 get_ptr_from_python(CPPType *type) {
00541   PtrConverter::iterator ci;
00542   ci = _from_python.find(type);
00543   if (ci != _from_python.end()) {
00544     // We've previously used this type.
00545     return (FunctionWriterPtrFromPython *)(*ci).second;
00546   }
00547 
00548   FunctionWriter *writer = 
00549     _function_writers.add_writer(new FunctionWriterPtrFromPython(type));
00550   _from_python.insert(PtrConverter::value_type(type, writer));
00551   return (FunctionWriterPtrFromPython *)writer;
00552 }
00553 
00554 ////////////////////////////////////////////////////////////////////
00555 //     Function: InterfaceMakerPythonObj::get_ptr_to_python
00556 //       Access: Private
00557 //  Description: Returns a FunctionWriter pointer suitable for
00558 //               converting from a C++ pointer of the indicated
00559 //               type to the corresponding Python wrapper.
00560 ////////////////////////////////////////////////////////////////////
00561 FunctionWriterPtrToPython *InterfaceMakerPythonObj::
00562 get_ptr_to_python(CPPType *type) {
00563   PtrConverter::iterator ci;
00564   ci = _to_python.find(type);
00565   if (ci != _to_python.end()) {
00566     // We've previously used this type.
00567     return (FunctionWriterPtrToPython *)(*ci).second;
00568   }
00569 
00570   FunctionWriter *writer = 
00571     _function_writers.add_writer(new FunctionWriterPtrToPython(type));
00572   _to_python.insert(PtrConverter::value_type(type, writer));
00573   return (FunctionWriterPtrToPython *)writer;
00574 }

Generated on Thu May 1 22:13:01 2003 for DTool by doxygen1.3