Browse Source

fix interrogate on Linux

David Rose 20 years ago
parent
commit
b531ece1b4

+ 1 - 1
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -2019,7 +2019,7 @@ void InterfaceMakerPythonNative::write_function_instance(ostream &out, Interface
         format_specifiers += "u#";
         parameter_list += ", &" + param_name
           + "_str, &" + param_name + "_len";
-        pexpr_string = "basic_string<wchar_t>(" +
+        pexpr_string = "basic_string<wchar_t>((wchar_t *)" +
           param_name + "_str, " +
           param_name + "_len)";
 

+ 512 - 512
dtool/src/interrogate/interfaceMakerPythonSimple.cxx

@@ -1,512 +1,512 @@
-// Filename: interfaceMakerPythonSimple.cxx
-// Created by:  drose (01Oct01)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://etc.cmu.edu/panda3d/docs/license/ .
-//
-// To contact the maintainers of this program    write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#include "interfaceMakerPythonSimple.h"
-#include "interrogateBuilder.h"
-#include "interrogate.h"
-#include "functionRemap.h"
-#include "parameterRemapUnchanged.h"
-#include "typeManager.h"
-
-#include "interrogateDatabase.h"
-#include "interrogateType.h"
-#include "interrogateFunction.h"
-#include "cppFunctionType.h"
-
-////////////////////////////////////////////////////////////////////
-//     Function: InterfaceMakerPythonSimple::Constructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-InterfaceMakerPythonSimple::
-InterfaceMakerPythonSimple(InterrogateModuleDef *def) :
-  InterfaceMakerPython(def)
-{
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: InterfaceMakerPythonSimple::Destructor
-//       Access: Public, Virtual
-//  Description:
-////////////////////////////////////////////////////////////////////
-InterfaceMakerPythonSimple::
-~InterfaceMakerPythonSimple() {
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: InterfaceMakerPythonSimple::write_prototypes
-//       Access: Public, Virtual
-//  Description: Generates the list of function prototypes
-//               corresponding to the functions that will be output in
-//               write_functions().
-////////////////////////////////////////////////////////////////////
-void InterfaceMakerPythonSimple::
-write_prototypes(ostream &out,ostream *out_h) {
-  Functions::iterator fi;
-  for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
-    Function *func = (*fi);
-    write_prototype_for(out, func);
-  }
-
-  out << "\n";
-  InterfaceMakerPython::write_prototypes(out,out_h);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: InterfaceMakerPythonSimple::write_functions
-//       Access: Public, Virtual
-//  Description: Generates the list of functions that are appropriate
-//               for this interface.  This function is called *before*
-//               write_prototypes(), above.
-////////////////////////////////////////////////////////////////////
-void InterfaceMakerPythonSimple::
-write_functions(ostream &out) {
-  Functions::iterator fi;
-  for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
-    Function *func = (*fi);
-    write_function_for(out, func);
-  }
-
-  InterfaceMakerPython::write_functions(out);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: InterfaceMakerPythonSimple::write_module
-//       Access: Public, Virtual
-//  Description: Generates whatever additional code is required to
-//               support a module file.
-////////////////////////////////////////////////////////////////////
-void InterfaceMakerPythonSimple::
-write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) {
-  InterfaceMakerPython::write_module(out,out_h, def);
-
-  out << "static PyMethodDef python_simple_funcs[] = {\n";
-
-  Functions::iterator fi;
-  for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
-    Function *func = (*fi);
-    Function::Remaps::const_iterator ri;
-    for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
-      FunctionRemap *remap = (*ri);
-      out << "  { \"" << remap->_reported_name << "\", &" 
-          << remap->_wrapper_name << ", METH_VARARGS },\n";
-    }
-  }  
-  out << "  { NULL, NULL }\n"
-      << "};\n\n"
-
-      << "#ifdef _WIN32\n"
-      << "extern \"C\" __declspec(dllexport) void init" << def->library_name << "();\n"
-      << "#else\n"
-      << "extern \"C\" void init" << def->library_name << "();\n"
-      << "#endif\n\n"
-    
-      << "void init" << def->library_name << "() {\n"
-      << "  Py_InitModule(\"" << def->library_name
-      << "\", python_simple_funcs);\n"
-      << "}\n\n";
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: InterfaceMakerPythonSimple::synthesize_this_parameter
-//       Access: Public, Virtual
-//  Description: This method should be overridden and redefined to
-//               return true for interfaces that require the implicit
-//               "this" parameter, if present, to be passed as the
-//               first parameter to any wrapper functions.
-////////////////////////////////////////////////////////////////////
-bool InterfaceMakerPythonSimple::
-synthesize_this_parameter() {
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: InterfaceMakerPythonSimple::get_wrapper_prefix
-//       Access: Protected, Virtual
-//  Description: Returns the prefix string used to generate wrapper
-//               function names.
-////////////////////////////////////////////////////////////////////
-string InterfaceMakerPythonSimple::
-get_wrapper_prefix() {
-  return "_inP";
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: InterfaceMakerPythonSimple::get_unique_prefix
-//       Access: Protected, Virtual
-//  Description: Returns the prefix string used to generate unique
-//               symbolic names, which are not necessarily C-callable
-//               function names.
-////////////////////////////////////////////////////////////////////
-string InterfaceMakerPythonSimple::
-get_unique_prefix() {
-  return "p";
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: InterfaceMakerPythonSimple::record_function_wrapper
-//       Access: Protected, Virtual
-//  Description: Associates the function wrapper with its function in
-//               the appropriate structures in the database.
-////////////////////////////////////////////////////////////////////
-void InterfaceMakerPythonSimple::
-record_function_wrapper(InterrogateFunction &ifunc, 
-                        FunctionWrapperIndex wrapper_index) {
-  ifunc._python_wrappers.push_back(wrapper_index);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: InterfaceMakerPythonSimple::write_prototype_for
-//       Access: Private
-//  Description: Writes the prototype for the indicated function.
-////////////////////////////////////////////////////////////////////
-void InterfaceMakerPythonSimple::
-write_prototype_for(ostream &out, InterfaceMaker::Function *func) {
-  Function::Remaps::const_iterator ri;
-
-  for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
-    FunctionRemap *remap = (*ri);
-    if (!output_function_names) {
-      // If we're not saving the function names, don't export it from
-      // the library.
-      out << "static ";
-    } else {
-      out << "extern \"C\" ";
-    }
-    out << "PyObject *"
-        << remap->_wrapper_name << "(PyObject *self, PyObject *args);\n";
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: InterfaceMakerPythonSimple::write_function_for
-//       Access: Private
-//  Description: Writes the definition for a function that will call
-//               the indicated C++ function or method.
-////////////////////////////////////////////////////////////////////
-void InterfaceMakerPythonSimple::
-write_function_for(ostream &out, InterfaceMaker::Function *func) {
-  Function::Remaps::const_iterator ri;
-
-  for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
-    FunctionRemap *remap = (*ri);
-    write_function_instance(out, func, remap);
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: InterfaceMakerPythonSimple::write_function_instance
-//       Access: Private
-//  Description: Writes out the particular function that handles a
-//               single instance of an overloaded function.
-////////////////////////////////////////////////////////////////////
-void InterfaceMakerPythonSimple::write_function_instance(ostream &out, InterfaceMaker::Function *func,
-                        FunctionRemap *remap) {
-  out << "/*\n"
-      << " * Python simple wrapper for\n"
-      << " * ";
-  remap->write_orig_prototype(out, 0);
-  out << "\n"
-      << " */\n";
-
-  if (!output_function_names) {
-    // If we're not saving the function names, don't export it from
-    // the library.
-    out << "static ";
-  }
-
-  out << "PyObject *\n"
-      << remap->_wrapper_name << "(PyObject *, PyObject *args) {\n";
-
-  if (generate_spam) {
-    write_spam_message(out, remap);
-  }
-
-  string format_specifiers;
-  string parameter_list;
-  string container;
-  vector_string pexprs;
-  string extra_convert;
-  string extra_param_check;
-  string extra_cleanup;
-
-  // Make one pass through the parameter list.  We will output a
-  // one-line temporary variable definition for each parameter, while
-  // simultaneously building the ParseTuple() function call and also
-  // the parameter expression list for call_function().
-
-  int pn;
-  for (pn = 0; pn < (int)remap->_parameters.size(); ++pn) {
-    indent(out, 2);
-    CPPType *orig_type = remap->_parameters[pn]._remap->get_orig_type();
-    CPPType *type = remap->_parameters[pn]._remap->get_new_type();
-    string param_name = remap->get_parameter_name(pn);
-    
-    // This is the string to convert our local variable to the
-    // appropriate C++ type.  Normally this is just a cast.
-    string pexpr_string =
-      "(" + type->get_local_name(&parser) + ")" + param_name;
-    
-    if (remap->_parameters[pn]._remap->new_type_is_atomic_string()) {
-      if (TypeManager::is_char_pointer(orig_type)) {
-        out << "char *" << param_name;
-        format_specifiers += "s";
-        parameter_list += ", &" + param_name;
-        
-      } else if (TypeManager::is_wstring(orig_type)) {
-        out << "Py_UNICODE *" << param_name
-            << "_str; int " << param_name << "_len";
-        format_specifiers += "u#";
-        parameter_list += ", &" + param_name
-          + "_str, &" + param_name + "_len";
-        pexpr_string = "basic_string<wchar_t>(" +
-          param_name + "_str, " +
-          param_name + "_len)";
-
-      } else {
-        out << "char *" << param_name
-            << "_str; int " << param_name << "_len";
-        format_specifiers += "s#";
-        parameter_list += ", &" + param_name
-          + "_str, &" + param_name + "_len";
-        pexpr_string = "basic_string<char>(" +
-          param_name + "_str, " +
-          param_name + "_len)";
-      }
-      
-    } else if (TypeManager::is_bool(type)) {
-      out << "PyObject *" << param_name;
-      format_specifiers += "O";
-      parameter_list += ", &" + param_name;
-      pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)";
-
-    } else if (TypeManager::is_unsigned_longlong(type)) {
-      out << "PyObject *" << param_name;
-      format_specifiers += "O";
-      parameter_list += ", &" + param_name;
-      extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
-      extra_param_check += "|| (" + param_name + "_long == NULL)";
-      pexpr_string = "PyLong_AsUnsignedLongLong(" + param_name + "_long)";
-      extra_cleanup += " Py_XDECREF(" + param_name + "_long);";
-
-    } else if (TypeManager::is_longlong(type)) {
-      out << "PyObject *" << param_name;
-      format_specifiers += "O";
-      parameter_list += ", &" + param_name;
-      extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
-      extra_param_check += "|| (" + param_name + "_long == NULL)";
-      pexpr_string = "PyLong_AsLongLong(" + param_name + "_long)";
-      extra_cleanup += " Py_XDECREF(" + param_name + "_long);";
-
-    } else if (TypeManager::is_unsigned_integer(type)) {
-      out << "PyObject *" << param_name;
-      format_specifiers += "O";
-      parameter_list += ", &" + param_name;
-      extra_convert += " PyObject *" + param_name + "_uint = PyNumber_Long(" + param_name + ");";
-      extra_param_check += "|| (" + param_name + "_uint == NULL)";
-      pexpr_string = "(unsigned int)PyLong_AsUnsignedLong(" + param_name + "_uint)";
-      extra_cleanup += " Py_XDECREF(" + param_name + "_uint);";
-
-    } else if (TypeManager::is_integer(type)) {
-      out << "int " << param_name;
-      format_specifiers += "i";
-      parameter_list += ", &" + param_name;
-
-    } else if (TypeManager::is_float(type)) {
-      out << "double " << param_name;
-      format_specifiers += "d";
-      parameter_list += ", &" + param_name;
-
-    } else if (TypeManager::is_char_pointer(type)) {
-      out << "char *" << param_name;
-      format_specifiers += "s";
-      parameter_list += ", &" + param_name;
-
-    } else if (TypeManager::is_pointer_to_PyObject(type)) {
-      out << "PyObject *" << param_name;
-      format_specifiers += "O";
-      parameter_list += ", &" + param_name;
-      pexpr_string = param_name;
-
-    } else if (TypeManager::is_pointer(type)) {
-      out << "int " << param_name;
-      format_specifiers += "i";
-      parameter_list += ", &" + param_name;
-
-    } else {
-      // Ignore a parameter.
-      out << "PyObject *" << param_name;
-      format_specifiers += "O";
-      parameter_list += ", &" + param_name;
-    }
-
-    out << ";\n";
-    if (remap->_has_this && pn == 0) {
-      // The "this" parameter gets passed in separately.
-      container = pexpr_string;
-    }
-    pexprs.push_back(pexpr_string);
-  }
-
-  out << "  if (PyArg_ParseTuple(args, \"" << format_specifiers
-      << "\"" << parameter_list << ")) {\n";
-
-  if (!extra_convert.empty()) {
-    out << "   " << extra_convert << "\n";
-  }
-
-  if (!extra_param_check.empty()) {
-    out << "    if (" << extra_param_check.substr(3) << ") {\n";
-    if (!extra_cleanup.empty()) {
-      out << "     " << extra_cleanup << "\n";
-    }
-    out << "      PyErr_SetString(PyExc_TypeError, \"Invalid parameters.\");\n"
-        << "      return (PyObject *)NULL;\n"
-        << "    }\n";
-  }
-  
-  if (track_interpreter) {
-    out << "    in_interpreter = 0;\n";
-  }
-
-  if (!remap->_void_return && 
-      remap->_return_type->new_type_is_atomic_string()) {
-    // Treat strings as a special case.  We don't want to format the
-    // return expression.
-    string return_expr = remap->call_function(out, 4, false, container, pexprs);
-    CPPType *type = remap->_return_type->get_orig_type();
-    out << "    ";
-    type->output_instance(out, "return_value", &parser);
-    out << " = " << return_expr << ";\n";
-    
-    if (track_interpreter) {
-      out << "    in_interpreter = 1;\n";
-    }
-    if (!extra_cleanup.empty()) {
-      out << "   " << extra_cleanup << "\n";
-    }
-    
-    return_expr = manage_return_value(out, 4, remap, "return_value");
-    test_assert(out, 4);
-    pack_return_value(out, 4, remap, return_expr);
-    
-  } else {
-    string return_expr = remap->call_function(out, 4, true, container, pexprs);
-    if (return_expr.empty()) {
-      if (track_interpreter) {
-        out << "    in_interpreter = 1;\n";
-      }
-      if (!extra_cleanup.empty()) {
-        out << "   " << extra_cleanup << "\n";
-      }
-      test_assert(out, 4);
-      out << "    return Py_BuildValue(\"\");\n";
-      
-    } else {
-      CPPType *type = remap->_return_type->get_temporary_type();
-      out << "    ";
-      type->output_instance(out, "return_value", &parser);
-      out << " = " << return_expr << ";\n";
-      if (track_interpreter) {
-        out << "    in_interpreter = 1;\n";
-      }
-      if (!extra_cleanup.empty()) {
-        out << "   " << extra_cleanup << "\n";
-      }
-      
-      return_expr = manage_return_value(out, 4, remap, "return_value");
-      test_assert(out, 4);
-      pack_return_value(out, 4, remap, remap->_return_type->temporary_to_return(return_expr));
-    }
-  }
-  
-  out << "  }\n";
-  
-  out << "  return (PyObject *)NULL;\n";
-  out << "}\n\n";
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: InterfaceMakerPythonSimple::pack_return_value
-//       Access: Private
-//  Description: Outputs a command to pack the indicated expression,
-//               of the return_type type, as a Python return value.
-////////////////////////////////////////////////////////////////////
-void InterfaceMakerPythonSimple::
-pack_return_value(ostream &out, int indent_level,
-                  FunctionRemap *remap, string return_expr) {
-  CPPType *orig_type = remap->_return_type->get_orig_type();
-  CPPType *type = remap->_return_type->get_new_type();
-
-  if (remap->_return_type->new_type_is_atomic_string()) 
-  {
-    if (TypeManager::is_char_pointer(orig_type)) {
-      indent(out, indent_level)
-        << "return PyString_FromString(" << return_expr << ");\n";
-
-    } else if (TypeManager::is_wstring(orig_type)) {
-      indent(out, indent_level)
-        << "return PyUnicode_FromWideChar("
-        << return_expr << ".data(), (int)" << return_expr << ".length());\n";
-
-    } else {
-      indent(out, indent_level)
-        << "return PyString_FromStringAndSize("
-        << return_expr << ".data(), " << return_expr << ".length());\n";
-    }
-
-  } else if (TypeManager::is_unsigned_longlong(type)) 
-  {
-    indent(out, indent_level)
-      << "return PyLong_FromUnsignedLongLong(" << return_expr << ");\n";
-
-  } else if (TypeManager::is_longlong(type)) 
-  {
-    indent(out, indent_level)
-      << "return PyLong_FromLongLong(" << return_expr << ");\n";
-
-  } else if (TypeManager::is_unsigned_integer(type)) {
-    indent(out, indent_level)
-      << "return PyLong_FromUnsignedLong(" << return_expr << ");\n";
-
-  } else if (TypeManager::is_integer(type)) {
-    indent(out, indent_level)
-      << "return PyInt_FromLong(" << return_expr << ");\n";
-
-  } else if (TypeManager::is_float(type)) {
-    indent(out, indent_level)
-      << "return PyFloat_FromDouble(" << return_expr << ");\n";
-
-  } else if (TypeManager::is_char_pointer(type)) {
-    indent(out, indent_level)
-      << "return PyString_FromString(" << return_expr << ");\n";
-
-  } else if (TypeManager::is_pointer_to_PyObject(type)) {
-    indent(out, indent_level)
-      << "return " << return_expr << ";\n";
-    
-  } else if (TypeManager::is_pointer(type)) {
-    indent(out, indent_level)
-      << "return PyInt_FromLong((int)" << return_expr << ");\n";
-
-  } else {
-    // Return None.
-    indent(out, indent_level)
-      << "return Py_BuildValue(\"\");\n";
-  }
-}
+// Filename: interfaceMakerPythonSimple.cxx
+// Created by:  drose (01Oct01)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program    write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "interfaceMakerPythonSimple.h"
+#include "interrogateBuilder.h"
+#include "interrogate.h"
+#include "functionRemap.h"
+#include "parameterRemapUnchanged.h"
+#include "typeManager.h"
+
+#include "interrogateDatabase.h"
+#include "interrogateType.h"
+#include "interrogateFunction.h"
+#include "cppFunctionType.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterfaceMakerPythonSimple::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+InterfaceMakerPythonSimple::
+InterfaceMakerPythonSimple(InterrogateModuleDef *def) :
+  InterfaceMakerPython(def)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterfaceMakerPythonSimple::Destructor
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+InterfaceMakerPythonSimple::
+~InterfaceMakerPythonSimple() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterfaceMakerPythonSimple::write_prototypes
+//       Access: Public, Virtual
+//  Description: Generates the list of function prototypes
+//               corresponding to the functions that will be output in
+//               write_functions().
+////////////////////////////////////////////////////////////////////
+void InterfaceMakerPythonSimple::
+write_prototypes(ostream &out,ostream *out_h) {
+  Functions::iterator fi;
+  for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
+    Function *func = (*fi);
+    write_prototype_for(out, func);
+  }
+
+  out << "\n";
+  InterfaceMakerPython::write_prototypes(out,out_h);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterfaceMakerPythonSimple::write_functions
+//       Access: Public, Virtual
+//  Description: Generates the list of functions that are appropriate
+//               for this interface.  This function is called *before*
+//               write_prototypes(), above.
+////////////////////////////////////////////////////////////////////
+void InterfaceMakerPythonSimple::
+write_functions(ostream &out) {
+  Functions::iterator fi;
+  for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
+    Function *func = (*fi);
+    write_function_for(out, func);
+  }
+
+  InterfaceMakerPython::write_functions(out);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterfaceMakerPythonSimple::write_module
+//       Access: Public, Virtual
+//  Description: Generates whatever additional code is required to
+//               support a module file.
+////////////////////////////////////////////////////////////////////
+void InterfaceMakerPythonSimple::
+write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) {
+  InterfaceMakerPython::write_module(out,out_h, def);
+
+  out << "static PyMethodDef python_simple_funcs[] = {\n";
+
+  Functions::iterator fi;
+  for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
+    Function *func = (*fi);
+    Function::Remaps::const_iterator ri;
+    for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
+      FunctionRemap *remap = (*ri);
+      out << "  { \"" << remap->_reported_name << "\", &" 
+          << remap->_wrapper_name << ", METH_VARARGS },\n";
+    }
+  }  
+  out << "  { NULL, NULL }\n"
+      << "};\n\n"
+
+      << "#ifdef _WIN32\n"
+      << "extern \"C\" __declspec(dllexport) void init" << def->library_name << "();\n"
+      << "#else\n"
+      << "extern \"C\" void init" << def->library_name << "();\n"
+      << "#endif\n\n"
+    
+      << "void init" << def->library_name << "() {\n"
+      << "  Py_InitModule(\"" << def->library_name
+      << "\", python_simple_funcs);\n"
+      << "}\n\n";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterfaceMakerPythonSimple::synthesize_this_parameter
+//       Access: Public, Virtual
+//  Description: This method should be overridden and redefined to
+//               return true for interfaces that require the implicit
+//               "this" parameter, if present, to be passed as the
+//               first parameter to any wrapper functions.
+////////////////////////////////////////////////////////////////////
+bool InterfaceMakerPythonSimple::
+synthesize_this_parameter() {
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterfaceMakerPythonSimple::get_wrapper_prefix
+//       Access: Protected, Virtual
+//  Description: Returns the prefix string used to generate wrapper
+//               function names.
+////////////////////////////////////////////////////////////////////
+string InterfaceMakerPythonSimple::
+get_wrapper_prefix() {
+  return "_inP";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterfaceMakerPythonSimple::get_unique_prefix
+//       Access: Protected, Virtual
+//  Description: Returns the prefix string used to generate unique
+//               symbolic names, which are not necessarily C-callable
+//               function names.
+////////////////////////////////////////////////////////////////////
+string InterfaceMakerPythonSimple::
+get_unique_prefix() {
+  return "p";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterfaceMakerPythonSimple::record_function_wrapper
+//       Access: Protected, Virtual
+//  Description: Associates the function wrapper with its function in
+//               the appropriate structures in the database.
+////////////////////////////////////////////////////////////////////
+void InterfaceMakerPythonSimple::
+record_function_wrapper(InterrogateFunction &ifunc, 
+                        FunctionWrapperIndex wrapper_index) {
+  ifunc._python_wrappers.push_back(wrapper_index);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterfaceMakerPythonSimple::write_prototype_for
+//       Access: Private
+//  Description: Writes the prototype for the indicated function.
+////////////////////////////////////////////////////////////////////
+void InterfaceMakerPythonSimple::
+write_prototype_for(ostream &out, InterfaceMaker::Function *func) {
+  Function::Remaps::const_iterator ri;
+
+  for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
+    FunctionRemap *remap = (*ri);
+    if (!output_function_names) {
+      // If we're not saving the function names, don't export it from
+      // the library.
+      out << "static ";
+    } else {
+      out << "extern \"C\" ";
+    }
+    out << "PyObject *"
+        << remap->_wrapper_name << "(PyObject *self, PyObject *args);\n";
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterfaceMakerPythonSimple::write_function_for
+//       Access: Private
+//  Description: Writes the definition for a function that will call
+//               the indicated C++ function or method.
+////////////////////////////////////////////////////////////////////
+void InterfaceMakerPythonSimple::
+write_function_for(ostream &out, InterfaceMaker::Function *func) {
+  Function::Remaps::const_iterator ri;
+
+  for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
+    FunctionRemap *remap = (*ri);
+    write_function_instance(out, func, remap);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterfaceMakerPythonSimple::write_function_instance
+//       Access: Private
+//  Description: Writes out the particular function that handles a
+//               single instance of an overloaded function.
+////////////////////////////////////////////////////////////////////
+void InterfaceMakerPythonSimple::write_function_instance(ostream &out, InterfaceMaker::Function *func,
+                        FunctionRemap *remap) {
+  out << "/*\n"
+      << " * Python simple wrapper for\n"
+      << " * ";
+  remap->write_orig_prototype(out, 0);
+  out << "\n"
+      << " */\n";
+
+  if (!output_function_names) {
+    // If we're not saving the function names, don't export it from
+    // the library.
+    out << "static ";
+  }
+
+  out << "PyObject *\n"
+      << remap->_wrapper_name << "(PyObject *, PyObject *args) {\n";
+
+  if (generate_spam) {
+    write_spam_message(out, remap);
+  }
+
+  string format_specifiers;
+  string parameter_list;
+  string container;
+  vector_string pexprs;
+  string extra_convert;
+  string extra_param_check;
+  string extra_cleanup;
+
+  // Make one pass through the parameter list.  We will output a
+  // one-line temporary variable definition for each parameter, while
+  // simultaneously building the ParseTuple() function call and also
+  // the parameter expression list for call_function().
+
+  int pn;
+  for (pn = 0; pn < (int)remap->_parameters.size(); ++pn) {
+    indent(out, 2);
+    CPPType *orig_type = remap->_parameters[pn]._remap->get_orig_type();
+    CPPType *type = remap->_parameters[pn]._remap->get_new_type();
+    string param_name = remap->get_parameter_name(pn);
+    
+    // This is the string to convert our local variable to the
+    // appropriate C++ type.  Normally this is just a cast.
+    string pexpr_string =
+      "(" + type->get_local_name(&parser) + ")" + param_name;
+    
+    if (remap->_parameters[pn]._remap->new_type_is_atomic_string()) {
+      if (TypeManager::is_char_pointer(orig_type)) {
+        out << "char *" << param_name;
+        format_specifiers += "s";
+        parameter_list += ", &" + param_name;
+        
+      } else if (TypeManager::is_wstring(orig_type)) {
+        out << "Py_UNICODE *" << param_name
+            << "_str; int " << param_name << "_len";
+        format_specifiers += "u#";
+        parameter_list += ", &" + param_name
+          + "_str, &" + param_name + "_len";
+        pexpr_string = "basic_string<wchar_t>((wchar_t *)" +
+          param_name + "_str, " +
+          param_name + "_len)";
+
+      } else {
+        out << "char *" << param_name
+            << "_str; int " << param_name << "_len";
+        format_specifiers += "s#";
+        parameter_list += ", &" + param_name
+          + "_str, &" + param_name + "_len";
+        pexpr_string = "basic_string<char>(" +
+          param_name + "_str, " +
+          param_name + "_len)";
+      }
+      
+    } else if (TypeManager::is_bool(type)) {
+      out << "PyObject *" << param_name;
+      format_specifiers += "O";
+      parameter_list += ", &" + param_name;
+      pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)";
+
+    } else if (TypeManager::is_unsigned_longlong(type)) {
+      out << "PyObject *" << param_name;
+      format_specifiers += "O";
+      parameter_list += ", &" + param_name;
+      extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
+      extra_param_check += "|| (" + param_name + "_long == NULL)";
+      pexpr_string = "PyLong_AsUnsignedLongLong(" + param_name + "_long)";
+      extra_cleanup += " Py_XDECREF(" + param_name + "_long);";
+
+    } else if (TypeManager::is_longlong(type)) {
+      out << "PyObject *" << param_name;
+      format_specifiers += "O";
+      parameter_list += ", &" + param_name;
+      extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
+      extra_param_check += "|| (" + param_name + "_long == NULL)";
+      pexpr_string = "PyLong_AsLongLong(" + param_name + "_long)";
+      extra_cleanup += " Py_XDECREF(" + param_name + "_long);";
+
+    } else if (TypeManager::is_unsigned_integer(type)) {
+      out << "PyObject *" << param_name;
+      format_specifiers += "O";
+      parameter_list += ", &" + param_name;
+      extra_convert += " PyObject *" + param_name + "_uint = PyNumber_Long(" + param_name + ");";
+      extra_param_check += "|| (" + param_name + "_uint == NULL)";
+      pexpr_string = "(unsigned int)PyLong_AsUnsignedLong(" + param_name + "_uint)";
+      extra_cleanup += " Py_XDECREF(" + param_name + "_uint);";
+
+    } else if (TypeManager::is_integer(type)) {
+      out << "int " << param_name;
+      format_specifiers += "i";
+      parameter_list += ", &" + param_name;
+
+    } else if (TypeManager::is_float(type)) {
+      out << "double " << param_name;
+      format_specifiers += "d";
+      parameter_list += ", &" + param_name;
+
+    } else if (TypeManager::is_char_pointer(type)) {
+      out << "char *" << param_name;
+      format_specifiers += "s";
+      parameter_list += ", &" + param_name;
+
+    } else if (TypeManager::is_pointer_to_PyObject(type)) {
+      out << "PyObject *" << param_name;
+      format_specifiers += "O";
+      parameter_list += ", &" + param_name;
+      pexpr_string = param_name;
+
+    } else if (TypeManager::is_pointer(type)) {
+      out << "int " << param_name;
+      format_specifiers += "i";
+      parameter_list += ", &" + param_name;
+
+    } else {
+      // Ignore a parameter.
+      out << "PyObject *" << param_name;
+      format_specifiers += "O";
+      parameter_list += ", &" + param_name;
+    }
+
+    out << ";\n";
+    if (remap->_has_this && pn == 0) {
+      // The "this" parameter gets passed in separately.
+      container = pexpr_string;
+    }
+    pexprs.push_back(pexpr_string);
+  }
+
+  out << "  if (PyArg_ParseTuple(args, \"" << format_specifiers
+      << "\"" << parameter_list << ")) {\n";
+
+  if (!extra_convert.empty()) {
+    out << "   " << extra_convert << "\n";
+  }
+
+  if (!extra_param_check.empty()) {
+    out << "    if (" << extra_param_check.substr(3) << ") {\n";
+    if (!extra_cleanup.empty()) {
+      out << "     " << extra_cleanup << "\n";
+    }
+    out << "      PyErr_SetString(PyExc_TypeError, \"Invalid parameters.\");\n"
+        << "      return (PyObject *)NULL;\n"
+        << "    }\n";
+  }
+  
+  if (track_interpreter) {
+    out << "    in_interpreter = 0;\n";
+  }
+
+  if (!remap->_void_return && 
+      remap->_return_type->new_type_is_atomic_string()) {
+    // Treat strings as a special case.  We don't want to format the
+    // return expression.
+    string return_expr = remap->call_function(out, 4, false, container, pexprs);
+    CPPType *type = remap->_return_type->get_orig_type();
+    out << "    ";
+    type->output_instance(out, "return_value", &parser);
+    out << " = " << return_expr << ";\n";
+    
+    if (track_interpreter) {
+      out << "    in_interpreter = 1;\n";
+    }
+    if (!extra_cleanup.empty()) {
+      out << "   " << extra_cleanup << "\n";
+    }
+    
+    return_expr = manage_return_value(out, 4, remap, "return_value");
+    test_assert(out, 4);
+    pack_return_value(out, 4, remap, return_expr);
+    
+  } else {
+    string return_expr = remap->call_function(out, 4, true, container, pexprs);
+    if (return_expr.empty()) {
+      if (track_interpreter) {
+        out << "    in_interpreter = 1;\n";
+      }
+      if (!extra_cleanup.empty()) {
+        out << "   " << extra_cleanup << "\n";
+      }
+      test_assert(out, 4);
+      out << "    return Py_BuildValue(\"\");\n";
+      
+    } else {
+      CPPType *type = remap->_return_type->get_temporary_type();
+      out << "    ";
+      type->output_instance(out, "return_value", &parser);
+      out << " = " << return_expr << ";\n";
+      if (track_interpreter) {
+        out << "    in_interpreter = 1;\n";
+      }
+      if (!extra_cleanup.empty()) {
+        out << "   " << extra_cleanup << "\n";
+      }
+      
+      return_expr = manage_return_value(out, 4, remap, "return_value");
+      test_assert(out, 4);
+      pack_return_value(out, 4, remap, remap->_return_type->temporary_to_return(return_expr));
+    }
+  }
+  
+  out << "  }\n";
+  
+  out << "  return (PyObject *)NULL;\n";
+  out << "}\n\n";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterfaceMakerPythonSimple::pack_return_value
+//       Access: Private
+//  Description: Outputs a command to pack the indicated expression,
+//               of the return_type type, as a Python return value.
+////////////////////////////////////////////////////////////////////
+void InterfaceMakerPythonSimple::
+pack_return_value(ostream &out, int indent_level,
+                  FunctionRemap *remap, string return_expr) {
+  CPPType *orig_type = remap->_return_type->get_orig_type();
+  CPPType *type = remap->_return_type->get_new_type();
+
+  if (remap->_return_type->new_type_is_atomic_string()) 
+  {
+    if (TypeManager::is_char_pointer(orig_type)) {
+      indent(out, indent_level)
+        << "return PyString_FromString(" << return_expr << ");\n";
+
+    } else if (TypeManager::is_wstring(orig_type)) {
+      indent(out, indent_level)
+        << "return PyUnicode_FromWideChar("
+        << return_expr << ".data(), (int)" << return_expr << ".length());\n";
+
+    } else {
+      indent(out, indent_level)
+        << "return PyString_FromStringAndSize("
+        << return_expr << ".data(), " << return_expr << ".length());\n";
+    }
+
+  } else if (TypeManager::is_unsigned_longlong(type)) 
+  {
+    indent(out, indent_level)
+      << "return PyLong_FromUnsignedLongLong(" << return_expr << ");\n";
+
+  } else if (TypeManager::is_longlong(type)) 
+  {
+    indent(out, indent_level)
+      << "return PyLong_FromLongLong(" << return_expr << ");\n";
+
+  } else if (TypeManager::is_unsigned_integer(type)) {
+    indent(out, indent_level)
+      << "return PyLong_FromUnsignedLong(" << return_expr << ");\n";
+
+  } else if (TypeManager::is_integer(type)) {
+    indent(out, indent_level)
+      << "return PyInt_FromLong(" << return_expr << ");\n";
+
+  } else if (TypeManager::is_float(type)) {
+    indent(out, indent_level)
+      << "return PyFloat_FromDouble(" << return_expr << ");\n";
+
+  } else if (TypeManager::is_char_pointer(type)) {
+    indent(out, indent_level)
+      << "return PyString_FromString(" << return_expr << ");\n";
+
+  } else if (TypeManager::is_pointer_to_PyObject(type)) {
+    indent(out, indent_level)
+      << "return " << return_expr << ";\n";
+    
+  } else if (TypeManager::is_pointer(type)) {
+    indent(out, indent_level)
+      << "return PyInt_FromLong((int)" << return_expr << ");\n";
+
+  } else {
+    // Return None.
+    indent(out, indent_level)
+      << "return Py_BuildValue(\"\");\n";
+  }
+}