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

interfaceMakerPythonSimple.cxx

Go to the documentation of this file.
00001 // Filename: interfaceMakerPythonSimple.cxx
00002 // Created by:  drose (01Oct01)
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 "interfaceMakerPythonSimple.h"
00020 #include "interrogateBuilder.h"
00021 #include "interrogate.h"
00022 #include "functionRemap.h"
00023 #include "parameterRemapUnchanged.h"
00024 #include "typeManager.h"
00025 
00026 #include "interrogateDatabase.h"
00027 #include "interrogateType.h"
00028 #include "interrogateFunction.h"
00029 #include "cppFunctionType.h"
00030 
00031 ////////////////////////////////////////////////////////////////////
00032 //     Function: InterfaceMakerPythonSimple::Constructor
00033 //       Access: Public
00034 //  Description:
00035 ////////////////////////////////////////////////////////////////////
00036 InterfaceMakerPythonSimple::
00037 InterfaceMakerPythonSimple(InterrogateModuleDef *def) :
00038   InterfaceMakerPython(def)
00039 {
00040 }
00041 
00042 ////////////////////////////////////////////////////////////////////
00043 //     Function: InterfaceMakerPythonSimple::Destructor
00044 //       Access: Public, Virtual
00045 //  Description:
00046 ////////////////////////////////////////////////////////////////////
00047 InterfaceMakerPythonSimple::
00048 ~InterfaceMakerPythonSimple() {
00049 }
00050 
00051 ////////////////////////////////////////////////////////////////////
00052 //     Function: InterfaceMakerPythonSimple::write_prototypes
00053 //       Access: Public, Virtual
00054 //  Description: Generates the list of function prototypes
00055 //               corresponding to the functions that will be output in
00056 //               write_functions().
00057 ////////////////////////////////////////////////////////////////////
00058 void InterfaceMakerPythonSimple::
00059 write_prototypes(ostream &out) {
00060   Functions::iterator fi;
00061   for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
00062     Function *func = (*fi);
00063     write_prototype_for(out, func);
00064   }
00065 
00066   out << "\n";
00067   InterfaceMakerPython::write_prototypes(out);
00068 }
00069 
00070 ////////////////////////////////////////////////////////////////////
00071 //     Function: InterfaceMakerPythonSimple::write_functions
00072 //       Access: Public, Virtual
00073 //  Description: Generates the list of functions that are appropriate
00074 //               for this interface.  This function is called *before*
00075 //               write_prototypes(), above.
00076 ////////////////////////////////////////////////////////////////////
00077 void InterfaceMakerPythonSimple::
00078 write_functions(ostream &out) {
00079   Functions::iterator fi;
00080   for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
00081     Function *func = (*fi);
00082     write_function_for(out, func);
00083   }
00084 
00085   InterfaceMakerPython::write_functions(out);
00086 }
00087 
00088 ////////////////////////////////////////////////////////////////////
00089 //     Function: InterfaceMakerPythonSimple::write_module
00090 //       Access: Public, Virtual
00091 //  Description: Generates whatever additional code is required to
00092 //               support a module file.
00093 ////////////////////////////////////////////////////////////////////
00094 void InterfaceMakerPythonSimple::
00095 write_module(ostream &out, InterrogateModuleDef *def) {
00096   InterfaceMakerPython::write_module(out, def);
00097 
00098   out << "static PyMethodDef python_simple_funcs[] = {\n";
00099 
00100   Functions::iterator fi;
00101   for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
00102     Function *func = (*fi);
00103     Function::Remaps::const_iterator ri;
00104     for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
00105       FunctionRemap *remap = (*ri);
00106       out << "  { \"" << remap->_unique_name << "\", &" 
00107           << remap->_wrapper_name << ", METH_VARARGS },\n";
00108     }
00109   }  
00110   out << "  { NULL, NULL }\n"
00111       << "};\n\n"
00112 
00113       << "#ifdef _WIN32\n"
00114       << "extern \"C\" __declspec(dllexport) void init" << def->library_name << "();\n"
00115       << "#else\n"
00116       << "extern \"C\" void init" << def->library_name << "();\n"
00117       << "#endif\n\n"
00118     
00119       << "void init" << def->library_name << "() {\n"
00120       << "  Py_InitModule(\"" << def->library_name
00121       << "\", python_simple_funcs);\n"
00122       << "}\n\n";
00123 }
00124 
00125 ////////////////////////////////////////////////////////////////////
00126 //     Function: InterfaceMakerPythonSimple::synthesize_this_parameter
00127 //       Access: Public, Virtual
00128 //  Description: This method should be overridden and redefined to
00129 //               return true for interfaces that require the implicit
00130 //               "this" parameter, if present, to be passed as the
00131 //               first parameter to any wrapper functions.
00132 ////////////////////////////////////////////////////////////////////
00133 bool InterfaceMakerPythonSimple::
00134 synthesize_this_parameter() {
00135   return true;
00136 }
00137 
00138 ////////////////////////////////////////////////////////////////////
00139 //     Function: InterfaceMakerPythonSimple::get_wrapper_prefix
00140 //       Access: Protected, Virtual
00141 //  Description: Returns the prefix string used to generate wrapper
00142 //               function names.
00143 ////////////////////////////////////////////////////////////////////
00144 string InterfaceMakerPythonSimple::
00145 get_wrapper_prefix() {
00146   return "_inP";
00147 }
00148 
00149 ////////////////////////////////////////////////////////////////////
00150 //     Function: InterfaceMakerPythonSimple::get_unique_prefix
00151 //       Access: Protected, Virtual
00152 //  Description: Returns the prefix string used to generate unique
00153 //               symbolic names, which are not necessarily C-callable
00154 //               function names.
00155 ////////////////////////////////////////////////////////////////////
00156 string InterfaceMakerPythonSimple::
00157 get_unique_prefix() {
00158   return "p";
00159 }
00160 
00161 ////////////////////////////////////////////////////////////////////
00162 //     Function: InterfaceMakerPythonSimple::record_function_wrapper
00163 //       Access: Protected, Virtual
00164 //  Description: Associates the function wrapper with its function in
00165 //               the appropriate structures in the database.
00166 ////////////////////////////////////////////////////////////////////
00167 void InterfaceMakerPythonSimple::
00168 record_function_wrapper(InterrogateFunction &ifunc, 
00169                         FunctionWrapperIndex wrapper_index) {
00170   ifunc._python_wrappers.push_back(wrapper_index);
00171 }
00172 
00173 ////////////////////////////////////////////////////////////////////
00174 //     Function: InterfaceMakerPythonSimple::write_prototype_for
00175 //       Access: Private
00176 //  Description: Writes the prototype for the indicated function.
00177 ////////////////////////////////////////////////////////////////////
00178 void InterfaceMakerPythonSimple::
00179 write_prototype_for(ostream &out, InterfaceMaker::Function *func) {
00180   Function::Remaps::const_iterator ri;
00181 
00182   for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
00183     FunctionRemap *remap = (*ri);
00184     if (!output_function_names) {
00185       // If we're not saving the function names, don't export it from
00186       // the library.
00187       out << "static ";
00188     } else {
00189       out << "extern \"C\" ";
00190     }
00191     out << "PyObject *"
00192         << remap->_wrapper_name << "(PyObject *self, PyObject *args);\n";
00193   }
00194 }
00195 
00196 ////////////////////////////////////////////////////////////////////
00197 //     Function: InterfaceMakerPythonSimple::write_function_for
00198 //       Access: Private
00199 //  Description: Writes the definition for a function that will call
00200 //               the indicated C++ function or method.
00201 ////////////////////////////////////////////////////////////////////
00202 void InterfaceMakerPythonSimple::
00203 write_function_for(ostream &out, InterfaceMaker::Function *func) {
00204   Function::Remaps::const_iterator ri;
00205 
00206   for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
00207     FunctionRemap *remap = (*ri);
00208     write_function_instance(out, func, remap);
00209   }
00210 }
00211 
00212 ////////////////////////////////////////////////////////////////////
00213 //     Function: InterfaceMakerPythonSimple::write_function_instance
00214 //       Access: Private
00215 //  Description: Writes out the particular function that handles a
00216 //               single instance of an overloaded function.
00217 ////////////////////////////////////////////////////////////////////
00218 void InterfaceMakerPythonSimple::
00219 write_function_instance(ostream &out, InterfaceMaker::Function *func,
00220                         FunctionRemap *remap) {
00221   out << "/*\n"
00222       << " * Python simple wrapper for\n"
00223       << " * ";
00224   remap->write_orig_prototype(out, 0);
00225   out << "\n"
00226       << " */\n";
00227 
00228   if (!output_function_names) {
00229     // If we're not saving the function names, don't export it from
00230     // the library.
00231     out << "static ";
00232   }
00233 
00234   out << "PyObject *\n"
00235       << remap->_wrapper_name << "(PyObject *, PyObject *args) {\n";
00236 
00237   if (generate_spam) {
00238     write_spam_message(out, remap);
00239   }
00240 
00241   string format_specifiers;
00242   string parameter_list;
00243   string container;
00244   vector_string pexprs;
00245 
00246   // Make one pass through the parameter list.  We will output a
00247   // one-line temporary variable definition for each parameter, while
00248   // simultaneously building the ParseTuple() function call and also
00249   // the parameter expression list for call_function().
00250 
00251   int pn;
00252   for (pn = 0; pn < (int)remap->_parameters.size(); pn++) {
00253     indent(out, 2);
00254     CPPType *orig_type = remap->_parameters[pn]._remap->get_orig_type();
00255     CPPType *type = remap->_parameters[pn]._remap->get_new_type();
00256     string param_name = remap->get_parameter_name(pn);
00257     
00258     // This is the string to convert our local variable to the
00259     // appropriate C++ type.  Normally this is just a cast.
00260     string pexpr_string =
00261       "(" + type->get_local_name(&parser) + ")" + param_name;
00262     
00263     if (remap->_parameters[pn]._remap->new_type_is_atomic_string()) {
00264       if (TypeManager::is_char_pointer(orig_type)) {
00265         out << "char *" << param_name;
00266         format_specifiers += "s";
00267         parameter_list += ", &" + param_name;
00268         
00269       } else {
00270         out << "char *" << param_name
00271             << "_str; int " << param_name << "_len";
00272         format_specifiers += "s#";
00273         parameter_list += ", &" + param_name
00274           + "_str, &" + param_name + "_len";
00275         pexpr_string = "basic_string<char>(" +
00276           param_name + "_str, " +
00277           param_name + "_len)";
00278       }
00279       
00280     } else if (TypeManager::is_bool(type)) {
00281       out << "PyObject *" << param_name;
00282       format_specifiers += "O";
00283       parameter_list += ", &" + param_name;
00284       pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)";
00285 
00286     } else if (TypeManager::is_integer(type)) {
00287       out << "int " << param_name;
00288       format_specifiers += "i";
00289       parameter_list += ", &" + param_name;
00290 
00291     } else if (TypeManager::is_float(type)) {
00292       out << "double " << param_name;
00293       format_specifiers += "d";
00294       parameter_list += ", &" + param_name;
00295 
00296     } else if (TypeManager::is_char_pointer(type)) {
00297       out << "char *" << param_name;
00298       format_specifiers += "s";
00299       parameter_list += ", &" + param_name;
00300 
00301     } else if (TypeManager::is_pointer(type)) {
00302       out << "int " << param_name;
00303       format_specifiers += "i";
00304       parameter_list += ", &" + param_name;
00305 
00306     } else {
00307       // Ignore a parameter.
00308       out << "PyObject *" << param_name;
00309       format_specifiers += "O";
00310       parameter_list += ", &" + param_name;
00311     }
00312 
00313     out << ";\n";
00314     if (remap->_has_this && pn == 0) {
00315       // The "this" parameter gets passed in separately.
00316       container = pexpr_string;
00317     }
00318     pexprs.push_back(pexpr_string);
00319   }
00320 
00321   out << "  if (PyArg_ParseTuple(args, \"" << format_specifiers
00322       << "\"" << parameter_list << ")) {\n";
00323   
00324   if (track_interpreter) {
00325     out << "    in_interpreter = 0;\n";
00326   }
00327   
00328   if (!remap->_void_return && 
00329       remap->_return_type->new_type_is_atomic_string()) {
00330     // Treat strings as a special case.  We don't want to format the
00331     // return expression.
00332     string return_expr = remap->call_function(out, 4, false, container, pexprs);
00333     
00334     CPPType *type = remap->_return_type->get_orig_type();
00335     out << "    ";
00336     type->output_instance(out, "return_value", &parser);
00337     out << " = " << return_expr << ";\n";
00338     
00339     if (track_interpreter) {
00340       out << "    in_interpreter = 1;\n";
00341     }
00342     
00343     return_expr = manage_return_value(out, 4, remap, "return_value");
00344     test_assert(out, 4);
00345     pack_return_value(out, 4, remap, return_expr);
00346     
00347   } else {
00348     string return_expr = remap->call_function(out, 4, true, container, pexprs);
00349     if (return_expr.empty()) {
00350       if (track_interpreter) {
00351         out << "    in_interpreter = 1;\n";
00352       }
00353       test_assert(out, 4);
00354       out << "    return Py_BuildValue(\"\");\n";
00355       
00356     } else {
00357       CPPType *type = remap->_return_type->get_temporary_type();
00358       out << "    ";
00359       type->output_instance(out, "return_value", &parser);
00360       out << " = " << return_expr << ";\n";
00361       if (track_interpreter) {
00362         out << "    in_interpreter = 1;\n";
00363       }
00364       
00365       return_expr = manage_return_value(out, 4, remap, "return_value");
00366       test_assert(out, 4);
00367       pack_return_value(out, 4, remap, remap->_return_type->temporary_to_return(return_expr));
00368     }
00369   }
00370   
00371   out << "  }\n";
00372   
00373   out << "  return (PyObject *)NULL;\n";
00374   out << "}\n\n";
00375 }
00376 
00377 ////////////////////////////////////////////////////////////////////
00378 //     Function: InterfaceMakerPythonSimple::pack_return_value
00379 //       Access: Private
00380 //  Description: Outputs a command to pack the indicated expression,
00381 //               of the return_type type, as a Python return value.
00382 ////////////////////////////////////////////////////////////////////
00383 void InterfaceMakerPythonSimple::
00384 pack_return_value(ostream &out, int indent_level,
00385                   FunctionRemap *remap, string return_expr) {
00386   CPPType *orig_type = remap->_return_type->get_orig_type();
00387   CPPType *type = remap->_return_type->get_new_type();
00388 
00389   if (remap->_return_type->new_type_is_atomic_string()) {
00390     if (TypeManager::is_char_pointer(orig_type)) {
00391       indent(out, indent_level)
00392         << "return PyString_FromString(" << return_expr << ");\n";
00393 
00394     } else {
00395       indent(out, indent_level)
00396         << "return PyString_FromStringAndSize("
00397         << return_expr << ".data(), " << return_expr << ".length());\n";
00398     }
00399 
00400   } else if (TypeManager::is_integer(type)) {
00401     indent(out, indent_level)
00402       << "return PyInt_FromLong(" << return_expr << ");\n";
00403 
00404   } else if (TypeManager::is_float(type)) {
00405     indent(out, indent_level)
00406       << "return PyFloat_FromDouble(" << return_expr << ");\n";
00407 
00408   } else if (TypeManager::is_char_pointer(type)) {
00409     indent(out, indent_level)
00410       << "return PyString_FromString(" << return_expr << ");\n";
00411 
00412   } else if (TypeManager::is_pointer(type)) {
00413     indent(out, indent_level)
00414       << "return PyInt_FromLong((int)" << return_expr << ");\n";
00415 
00416   } else {
00417     // Return None.
00418     indent(out, indent_level)
00419       << "return Py_BuildValue(\"\");\n";
00420   }
00421 }

Generated on Fri Apr 18 01:33:47 2003 for DTool by doxygen1.3