|
@@ -1,651 +1,651 @@
|
|
|
-// Filename: interfaceMakerPythonObj.cxx
|
|
|
|
|
-// Created by: drose (19Sep01)
|
|
|
|
|
-//
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-//
|
|
|
|
|
-// 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 "interfaceMakerPythonObj.h"
|
|
|
|
|
-#include "interrogateBuilder.h"
|
|
|
|
|
-#include "interrogate.h"
|
|
|
|
|
-#include "functionRemap.h"
|
|
|
|
|
-#include "parameterRemapUnchanged.h"
|
|
|
|
|
-#include "typeManager.h"
|
|
|
|
|
-#include "functionWriterPtrFromPython.h"
|
|
|
|
|
-#include "functionWriterPtrToPython.h"
|
|
|
|
|
-
|
|
|
|
|
-#include "interrogateDatabase.h"
|
|
|
|
|
-#include "interrogateType.h"
|
|
|
|
|
-#include "interrogateFunction.h"
|
|
|
|
|
-#include "cppFunctionType.h"
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: InterfaceMakerPythonObj::Constructor
|
|
|
|
|
-// Access: Public
|
|
|
|
|
-// Description:
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-InterfaceMakerPythonObj::
|
|
|
|
|
-InterfaceMakerPythonObj(InterrogateModuleDef *def) :
|
|
|
|
|
- InterfaceMakerPython(def)
|
|
|
|
|
-{
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: InterfaceMakerPythonObj::Destructor
|
|
|
|
|
-// Access: Public, Virtual
|
|
|
|
|
-// Description:
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-InterfaceMakerPythonObj::
|
|
|
|
|
-~InterfaceMakerPythonObj() {
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: InterfaceMakerPythonObj::write_prototypes
|
|
|
|
|
-// Access: Public, Virtual
|
|
|
|
|
-// Description: Generates the list of function prototypes
|
|
|
|
|
-// corresponding to the functions that will be output in
|
|
|
|
|
-// write_functions().
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void InterfaceMakerPythonObj::
|
|
|
|
|
-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: InterfaceMakerPythonObj::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 InterfaceMakerPythonObj::
|
|
|
|
|
-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);
|
|
|
|
|
-
|
|
|
|
|
- // Finally, generate all the make-class-wrapper functions.
|
|
|
|
|
- Objects::iterator oi;
|
|
|
|
|
- for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
|
|
|
|
- Object *object = (*oi).second;
|
|
|
|
|
-
|
|
|
|
|
- write_class_wrapper(out, object);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: InterfaceMakerPythonObj::write_module
|
|
|
|
|
-// Access: Public, Virtual
|
|
|
|
|
-// Description: Generates whatever additional code is required to
|
|
|
|
|
-// support a module file.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void InterfaceMakerPythonObj::
|
|
|
|
|
-write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) {
|
|
|
|
|
- InterfaceMakerPython::write_module(out,out_h, def);
|
|
|
|
|
-
|
|
|
|
|
- out << "static PyMethodDef python_obj_funcs[] = {\n";
|
|
|
|
|
-
|
|
|
|
|
- Objects::iterator oi;
|
|
|
|
|
- for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
|
|
|
|
- Object *object = (*oi).second;
|
|
|
|
|
-
|
|
|
|
|
- Functions::iterator fi;
|
|
|
|
|
- for (fi = object->_constructors.begin();
|
|
|
|
|
- fi != object->_constructors.end();
|
|
|
|
|
- ++fi) {
|
|
|
|
|
- Function *func = (*fi);
|
|
|
|
|
- out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_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_obj_funcs);\n"
|
|
|
|
|
- << "}\n\n";
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: InterfaceMakerPythonObj::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 InterfaceMakerPythonObj::
|
|
|
|
|
-synthesize_this_parameter() {
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: InterfaceMakerPythonObj::get_builder_name
|
|
|
|
|
-// Access: Public, Static
|
|
|
|
|
-// Description: Returns the name of the InterfaceMaker function
|
|
|
|
|
-// generated to define the Python class for the
|
|
|
|
|
-// indicated struct type.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-string InterfaceMakerPythonObj::
|
|
|
|
|
-get_builder_name(CPPType *struct_type) {
|
|
|
|
|
- return "get_python_class_" +
|
|
|
|
|
- InterrogateBuilder::clean_identifier(struct_type->get_local_name(&parser));
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: InterfaceMakerPythonObj::get_wrapper_prefix
|
|
|
|
|
-// Access: Protected, Virtual
|
|
|
|
|
-// Description: Returns the prefix string used to generate wrapper
|
|
|
|
|
-// function names.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-string InterfaceMakerPythonObj::
|
|
|
|
|
-get_wrapper_prefix() {
|
|
|
|
|
- return "wpo_";
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: InterfaceMakerPythonObj::write_class_wrapper
|
|
|
|
|
-// Access: Private
|
|
|
|
|
-// Description: Writes a function that will define the Python class.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void InterfaceMakerPythonObj::
|
|
|
|
|
-write_class_wrapper(ostream &out, InterfaceMaker::Object *object) {
|
|
|
|
|
- CPPType *struct_type = object->_itype._cpptype;
|
|
|
|
|
- if (struct_type == (CPPType *)NULL) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- string name = get_builder_name(struct_type);
|
|
|
|
|
- string python_name =
|
|
|
|
|
- InterrogateBuilder::clean_identifier(struct_type->get_simple_name());
|
|
|
|
|
-
|
|
|
|
|
- out << "/*\n"
|
|
|
|
|
- << " * Generate unique Python class for "
|
|
|
|
|
- << struct_type->get_local_name(&parser) << "\n"
|
|
|
|
|
- << " */\n"
|
|
|
|
|
- << "PyObject *\n"
|
|
|
|
|
- << name << "() {\n"
|
|
|
|
|
- << " static PyObject *wrapper = (PyObject *)NULL;\n"
|
|
|
|
|
- << " static PyMethodDef methods[] = {\n";
|
|
|
|
|
-
|
|
|
|
|
- int methods_size = 0;
|
|
|
|
|
- int class_methods_size = 0;
|
|
|
|
|
-
|
|
|
|
|
- Functions::iterator fi;
|
|
|
|
|
- for (fi = object->_methods.begin(); fi != object->_methods.end(); ++fi) {
|
|
|
|
|
- Function *func = (*fi);
|
|
|
|
|
- if (func->_has_this) {
|
|
|
|
|
- out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_name
|
|
|
|
|
- << ", METH_VARARGS },\n";
|
|
|
|
|
- methods_size++;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- out << " };\n"
|
|
|
|
|
- << " static const int methods_size = " << methods_size << ";\n\n"
|
|
|
|
|
- << " static PyMethodDef class_methods[] = {\n";
|
|
|
|
|
-
|
|
|
|
|
- for (fi = object->_methods.begin(); fi != object->_methods.end(); ++fi) {
|
|
|
|
|
- Function *func = (*fi);
|
|
|
|
|
- if (!func->_has_this) {
|
|
|
|
|
- out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_name
|
|
|
|
|
- << ", METH_VARARGS },\n";
|
|
|
|
|
- class_methods_size++;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- out << " };\n"
|
|
|
|
|
- << " static const int class_methods_size = " << class_methods_size << ";\n\n"
|
|
|
|
|
- << " if (wrapper == (PyObject *)NULL) {\n"
|
|
|
|
|
- << " int i;\n"
|
|
|
|
|
- << " PyObject *bases = PyTuple_New(0);\n"
|
|
|
|
|
- << " PyObject *dict = PyDict_New();\n"
|
|
|
|
|
- << " PyObject *name = PyString_FromString(\""
|
|
|
|
|
- << python_name << "\");\n"
|
|
|
|
|
- << " wrapper = PyClass_New(bases, dict, name);\n"
|
|
|
|
|
- << " for (i = 0; i < methods_size; ++i) {\n"
|
|
|
|
|
- << " PyObject *function, *method;\n"
|
|
|
|
|
- << " function = PyCFunction_New(&methods[i], (PyObject *)NULL);\n"
|
|
|
|
|
- << " method = PyMethod_New(function, (PyObject *)NULL, wrapper);\n"
|
|
|
|
|
- << " PyDict_SetItemString(dict, methods[i].ml_name, method);\n"
|
|
|
|
|
- << " }\n"
|
|
|
|
|
- << " for (i = 0; i < class_methods_size; ++i) {\n"
|
|
|
|
|
- << " PyObject *function;\n"
|
|
|
|
|
- << " function = PyCFunction_New(&class_methods[i], (PyObject *)NULL);\n"
|
|
|
|
|
- << " PyDict_SetItemString(dict, class_methods[i].ml_name, function);\n"
|
|
|
|
|
- << " }\n"
|
|
|
|
|
- << " }\n"
|
|
|
|
|
- << " return wrapper;\n"
|
|
|
|
|
- << "}\n\n";
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: InterfaceMakerPythonObj::write_prototype_for
|
|
|
|
|
-// Access: Private
|
|
|
|
|
-// Description: Writes the prototype for the indicated function.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void InterfaceMakerPythonObj::
|
|
|
|
|
-write_prototype_for(ostream &out, InterfaceMaker::Function *func) {
|
|
|
|
|
- out << "static PyObject *"
|
|
|
|
|
- << func->_name << "(PyObject *self, PyObject *args);\n";
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: InterfaceMakerPythonObj::write_function_for
|
|
|
|
|
-// Access: Private
|
|
|
|
|
-// Description: Writes the definition for a function that will call
|
|
|
|
|
-// the indicated C++ function or method.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void InterfaceMakerPythonObj::
|
|
|
|
|
-write_function_for(ostream &out, InterfaceMaker::Function *func) {
|
|
|
|
|
- Function::Remaps::const_iterator ri;
|
|
|
|
|
- out << "/*\n"
|
|
|
|
|
- << " * Python object wrapper for\n";
|
|
|
|
|
- for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
|
|
|
|
|
- FunctionRemap *remap = (*ri);
|
|
|
|
|
- out << " * ";
|
|
|
|
|
- remap->write_orig_prototype(out, 0);
|
|
|
|
|
- out << "\n";
|
|
|
|
|
- }
|
|
|
|
|
- out << " */\n";
|
|
|
|
|
-
|
|
|
|
|
- out << "static PyObject *"
|
|
|
|
|
- << func->_name << "(PyObject *, PyObject *args) {\n";
|
|
|
|
|
-
|
|
|
|
|
- // Now write out each instance of the overloaded function.
|
|
|
|
|
- string expected_params = "Arguments must match one of:";
|
|
|
|
|
-
|
|
|
|
|
- for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
|
|
|
|
|
- FunctionRemap *remap = (*ri);
|
|
|
|
|
- expected_params += "\\n ";
|
|
|
|
|
- write_function_instance(out, 2, func, remap, expected_params);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // If we get here in the generated code, none of the parameters were
|
|
|
|
|
- // valid. Generate an error exception. (We don't rely on the error
|
|
|
|
|
- // already generated by ParseTuple(), because it only reports the
|
|
|
|
|
- // error for one flavor of the function, whereas we might accept
|
|
|
|
|
- // multiple flavors for the different overloaded C++ function
|
|
|
|
|
- // signatures.
|
|
|
|
|
-
|
|
|
|
|
- out << " PyErr_SetString(PyExc_TypeError, \"" << expected_params << "\");\n"
|
|
|
|
|
- << " return (PyObject *)NULL;\n";
|
|
|
|
|
-
|
|
|
|
|
- out << "}\n\n";
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: InterfaceMakerPythonObj::write_function_instance
|
|
|
|
|
-// Access: Private
|
|
|
|
|
-// Description: Writes out the part of a function that handles a
|
|
|
|
|
-// single instance of an overloaded function.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void InterfaceMakerPythonObj::
|
|
|
|
|
-write_function_instance(ostream &out, int indent_level,
|
|
|
|
|
- InterfaceMaker::Function *func,
|
|
|
|
|
- FunctionRemap *remap, string &expected_params) {
|
|
|
|
|
- indent(out, indent_level) << "{\n";
|
|
|
|
|
- indent(out, indent_level + 2) << "/* ";
|
|
|
|
|
- remap->write_orig_prototype(out, 0);
|
|
|
|
|
- out << " */\n\n";
|
|
|
|
|
-
|
|
|
|
|
- string format_specifiers;
|
|
|
|
|
- string parameter_list;
|
|
|
|
|
- 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().
|
|
|
|
|
-
|
|
|
|
|
- expected_params += remap->_cppfunc->get_simple_name();
|
|
|
|
|
- expected_params += "(";
|
|
|
|
|
-
|
|
|
|
|
- int pn;
|
|
|
|
|
- for (pn = 0; pn < (int)remap->_parameters.size(); pn++) {
|
|
|
|
|
- if (pn != 0) {
|
|
|
|
|
- expected_params += ", ";
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- indent(out, indent_level + 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 {
|
|
|
|
|
- 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)";
|
|
|
|
|
- }
|
|
|
|
|
- expected_params += "string";
|
|
|
|
|
-
|
|
|
|
|
- } else if (TypeManager::is_bool(type)) {
|
|
|
|
|
- out << "PyObject *" << param_name;
|
|
|
|
|
- format_specifiers += "O";
|
|
|
|
|
- parameter_list += ", &" + param_name;
|
|
|
|
|
- pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)";
|
|
|
|
|
- expected_params += "bool";
|
|
|
|
|
-
|
|
|
|
|
- } 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);";
|
|
|
|
|
- expected_params += "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);";
|
|
|
|
|
- expected_params += "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);";
|
|
|
|
|
- expected_params += "unsigned int";
|
|
|
|
|
-
|
|
|
|
|
- } else if (TypeManager::is_integer(type)) {
|
|
|
|
|
- out << "int " << param_name;
|
|
|
|
|
- format_specifiers += "i";
|
|
|
|
|
- parameter_list += ", &" + param_name;
|
|
|
|
|
- expected_params += "integer";
|
|
|
|
|
-
|
|
|
|
|
- } else if (TypeManager::is_float(type)) {
|
|
|
|
|
- out << "double " << param_name;
|
|
|
|
|
- format_specifiers += "d";
|
|
|
|
|
- parameter_list += ", &" + param_name;
|
|
|
|
|
- expected_params += "float";
|
|
|
|
|
-
|
|
|
|
|
- } else if (TypeManager::is_char_pointer(type)) {
|
|
|
|
|
- out << "char *" << param_name;
|
|
|
|
|
- format_specifiers += "s";
|
|
|
|
|
- parameter_list += ", &" + param_name;
|
|
|
|
|
- expected_params += "string";
|
|
|
|
|
-
|
|
|
|
|
- } else if (TypeManager::is_pointer(type)) {
|
|
|
|
|
- FunctionWriterPtrFromPython *writer = get_ptr_from_python(type);
|
|
|
|
|
- writer->get_pointer_type()->output_instance(out, param_name, &parser);
|
|
|
|
|
- format_specifiers += "O&";
|
|
|
|
|
- parameter_list += ", &" + writer->get_name() + ", &" + param_name;
|
|
|
|
|
- expected_params += writer->get_type()->get_preferred_name();
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
- // Ignore a parameter.
|
|
|
|
|
- out << "PyObject *" << param_name;
|
|
|
|
|
- format_specifiers += "O";
|
|
|
|
|
- parameter_list += ", &" + param_name;
|
|
|
|
|
- expected_params += "any";
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (remap->_parameters[pn]._has_name) {
|
|
|
|
|
- expected_params += " " + remap->_parameters[pn]._name;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- out << ";\n";
|
|
|
|
|
- pexprs.push_back(pexpr_string);
|
|
|
|
|
- }
|
|
|
|
|
- expected_params += ")";
|
|
|
|
|
-
|
|
|
|
|
- indent(out, indent_level + 2)
|
|
|
|
|
- << "if (PyArg_ParseTuple(args, \"" << format_specifiers
|
|
|
|
|
- << "\"" << parameter_list << ")) {\n";
|
|
|
|
|
-
|
|
|
|
|
- if (!extra_convert.empty()) {
|
|
|
|
|
- indent(out, indent_level + 3)
|
|
|
|
|
- << extra_convert << "\n";
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (!extra_param_check.empty()) {
|
|
|
|
|
- indent(out, indent_level + 4)
|
|
|
|
|
- << "if (" << extra_param_check.substr(3) << ") {\n";
|
|
|
|
|
- if (!extra_cleanup.empty()) {
|
|
|
|
|
- indent(out, indent_level + 5)
|
|
|
|
|
- << extra_cleanup << "\n";
|
|
|
|
|
- }
|
|
|
|
|
- indent(out, indent_level + 6)
|
|
|
|
|
- << "PyErr_SetString(PyExc_TypeError, \"Invalid parameters.\");\n";
|
|
|
|
|
- indent(out, indent_level + 6)
|
|
|
|
|
- << "return (PyObject *)NULL;\n";
|
|
|
|
|
- indent(out, indent_level + 4)
|
|
|
|
|
- << "}\n";
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (track_interpreter) {
|
|
|
|
|
- indent(out, indent_level + 4)
|
|
|
|
|
- << "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, indent_level + 4, false, "param0", pexprs);
|
|
|
|
|
-
|
|
|
|
|
- CPPType *type = remap->_return_type->get_orig_type();
|
|
|
|
|
- indent(out, indent_level + 4);
|
|
|
|
|
- type->output_instance(out, "return_value", &parser);
|
|
|
|
|
- out << " = " << return_expr << ";\n";
|
|
|
|
|
-
|
|
|
|
|
- if (track_interpreter) {
|
|
|
|
|
- indent(out, indent_level + 4)
|
|
|
|
|
- << "in_interpreter = 1;\n";
|
|
|
|
|
- }
|
|
|
|
|
- if (!extra_cleanup.empty()) {
|
|
|
|
|
- indent(out, indent_level + 3)
|
|
|
|
|
- << extra_cleanup << "\n";
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
|
|
|
|
|
- test_assert(out, indent_level + 4);
|
|
|
|
|
- pack_return_value(out, indent_level + 4, remap, return_expr);
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
- string return_expr =
|
|
|
|
|
- remap->call_function(out, indent_level + 4, true, "param0", pexprs);
|
|
|
|
|
- if (return_expr.empty()) {
|
|
|
|
|
- if (track_interpreter) {
|
|
|
|
|
- indent(out, indent_level + 4)
|
|
|
|
|
- << "in_interpreter = 1;\n";
|
|
|
|
|
- }
|
|
|
|
|
- if (!extra_cleanup.empty()) {
|
|
|
|
|
- indent(out, indent_level + 3)
|
|
|
|
|
- << extra_cleanup << "\n";
|
|
|
|
|
- }
|
|
|
|
|
- test_assert(out, indent_level + 4);
|
|
|
|
|
- indent(out, indent_level + 4)
|
|
|
|
|
- << "return Py_BuildValue(\"\");\n";
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
- CPPType *type = remap->_return_type->get_temporary_type();
|
|
|
|
|
- indent(out, indent_level + 4);
|
|
|
|
|
- type->output_instance(out, "return_value", &parser);
|
|
|
|
|
- out << " = " << return_expr << ";\n";
|
|
|
|
|
- if (track_interpreter) {
|
|
|
|
|
- indent(out, indent_level + 4)
|
|
|
|
|
- << "in_interpreter = 1;\n";
|
|
|
|
|
- }
|
|
|
|
|
- if (!extra_cleanup.empty()) {
|
|
|
|
|
- indent(out, indent_level + 3)
|
|
|
|
|
- << extra_cleanup << "\n";
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
|
|
|
|
|
- test_assert(out, indent_level + 4);
|
|
|
|
|
- pack_return_value(out, indent_level + 4, remap, remap->_return_type->temporary_to_return(return_expr));
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- indent(out, indent_level + 2) << "}\n";
|
|
|
|
|
- indent(out, indent_level + 2)
|
|
|
|
|
- << "PyErr_Clear();\n"; // Clear the error generated by ParseTuple()
|
|
|
|
|
- indent(out, indent_level)
|
|
|
|
|
- << "}\n";
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: InterfaceMakerPythonObj::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 InterfaceMakerPythonObj::
|
|
|
|
|
-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 {
|
|
|
|
|
- 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(type)) {
|
|
|
|
|
- bool caller_manages = remap->_return_value_needs_management;
|
|
|
|
|
-
|
|
|
|
|
- FunctionWriterPtrToPython *writer = get_ptr_to_python(type);
|
|
|
|
|
- indent(out, indent_level)
|
|
|
|
|
- << "return " << writer->get_name() << "(("
|
|
|
|
|
- << writer->get_pointer_type()->get_local_name(&parser) << ")"
|
|
|
|
|
- << return_expr << ", " << caller_manages << ");\n";
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
- // Return None.
|
|
|
|
|
- indent(out, indent_level)
|
|
|
|
|
- << "return Py_BuildValue(\"\");\n";
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: InterfaceMakerPythonObj::get_ptr_from_python
|
|
|
|
|
-// Access: Private
|
|
|
|
|
-// Description: Returns a FunctionWriter pointer suitable for
|
|
|
|
|
-// converting from a Python wrapper of the indicated
|
|
|
|
|
-// type to the corresponding C++ pointer.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-FunctionWriterPtrFromPython *InterfaceMakerPythonObj::
|
|
|
|
|
-get_ptr_from_python(CPPType *type) {
|
|
|
|
|
- PtrConverter::iterator ci;
|
|
|
|
|
- ci = _from_python.find(type);
|
|
|
|
|
- if (ci != _from_python.end()) {
|
|
|
|
|
- // We've previously used this type.
|
|
|
|
|
- return (FunctionWriterPtrFromPython *)(*ci).second;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- FunctionWriter *writer =
|
|
|
|
|
- _function_writers.add_writer(new FunctionWriterPtrFromPython(type));
|
|
|
|
|
- _from_python.insert(PtrConverter::value_type(type, writer));
|
|
|
|
|
- return (FunctionWriterPtrFromPython *)writer;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: InterfaceMakerPythonObj::get_ptr_to_python
|
|
|
|
|
-// Access: Private
|
|
|
|
|
-// Description: Returns a FunctionWriter pointer suitable for
|
|
|
|
|
-// converting from a C++ pointer of the indicated
|
|
|
|
|
-// type to the corresponding Python wrapper.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-FunctionWriterPtrToPython *InterfaceMakerPythonObj::
|
|
|
|
|
-get_ptr_to_python(CPPType *type) {
|
|
|
|
|
- PtrConverter::iterator ci;
|
|
|
|
|
- ci = _to_python.find(type);
|
|
|
|
|
- if (ci != _to_python.end()) {
|
|
|
|
|
- // We've previously used this type.
|
|
|
|
|
- return (FunctionWriterPtrToPython *)(*ci).second;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- FunctionWriter *writer =
|
|
|
|
|
- _function_writers.add_writer(new FunctionWriterPtrToPython(type));
|
|
|
|
|
- _to_python.insert(PtrConverter::value_type(type, writer));
|
|
|
|
|
- return (FunctionWriterPtrToPython *)writer;
|
|
|
|
|
-}
|
|
|
|
|
|
|
+// Filename: interfaceMakerPythonObj.cxx
|
|
|
|
|
+// Created by: drose (19Sep01)
|
|
|
|
|
+//
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+//
|
|
|
|
|
+// 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 "interfaceMakerPythonObj.h"
|
|
|
|
|
+#include "interrogateBuilder.h"
|
|
|
|
|
+#include "interrogate.h"
|
|
|
|
|
+#include "functionRemap.h"
|
|
|
|
|
+#include "parameterRemapUnchanged.h"
|
|
|
|
|
+#include "typeManager.h"
|
|
|
|
|
+#include "functionWriterPtrFromPython.h"
|
|
|
|
|
+#include "functionWriterPtrToPython.h"
|
|
|
|
|
+
|
|
|
|
|
+#include "interrogateDatabase.h"
|
|
|
|
|
+#include "interrogateType.h"
|
|
|
|
|
+#include "interrogateFunction.h"
|
|
|
|
|
+#include "cppFunctionType.h"
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: InterfaceMakerPythonObj::Constructor
|
|
|
|
|
+// Access: Public
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+InterfaceMakerPythonObj::
|
|
|
|
|
+InterfaceMakerPythonObj(InterrogateModuleDef *def) :
|
|
|
|
|
+ InterfaceMakerPython(def)
|
|
|
|
|
+{
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: InterfaceMakerPythonObj::Destructor
|
|
|
|
|
+// Access: Public, Virtual
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+InterfaceMakerPythonObj::
|
|
|
|
|
+~InterfaceMakerPythonObj() {
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: InterfaceMakerPythonObj::write_prototypes
|
|
|
|
|
+// Access: Public, Virtual
|
|
|
|
|
+// Description: Generates the list of function prototypes
|
|
|
|
|
+// corresponding to the functions that will be output in
|
|
|
|
|
+// write_functions().
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+void InterfaceMakerPythonObj::
|
|
|
|
|
+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: InterfaceMakerPythonObj::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 InterfaceMakerPythonObj::
|
|
|
|
|
+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);
|
|
|
|
|
+
|
|
|
|
|
+ // Finally, generate all the make-class-wrapper functions.
|
|
|
|
|
+ Objects::iterator oi;
|
|
|
|
|
+ for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
|
|
|
|
+ Object *object = (*oi).second;
|
|
|
|
|
+
|
|
|
|
|
+ write_class_wrapper(out, object);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: InterfaceMakerPythonObj::write_module
|
|
|
|
|
+// Access: Public, Virtual
|
|
|
|
|
+// Description: Generates whatever additional code is required to
|
|
|
|
|
+// support a module file.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+void InterfaceMakerPythonObj::
|
|
|
|
|
+write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) {
|
|
|
|
|
+ InterfaceMakerPython::write_module(out,out_h, def);
|
|
|
|
|
+
|
|
|
|
|
+ out << "static PyMethodDef python_obj_funcs[] = {\n";
|
|
|
|
|
+
|
|
|
|
|
+ Objects::iterator oi;
|
|
|
|
|
+ for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
|
|
|
|
+ Object *object = (*oi).second;
|
|
|
|
|
+
|
|
|
|
|
+ Functions::iterator fi;
|
|
|
|
|
+ for (fi = object->_constructors.begin();
|
|
|
|
|
+ fi != object->_constructors.end();
|
|
|
|
|
+ ++fi) {
|
|
|
|
|
+ Function *func = (*fi);
|
|
|
|
|
+ out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_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_obj_funcs);\n"
|
|
|
|
|
+ << "}\n\n";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: InterfaceMakerPythonObj::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 InterfaceMakerPythonObj::
|
|
|
|
|
+synthesize_this_parameter() {
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: InterfaceMakerPythonObj::get_builder_name
|
|
|
|
|
+// Access: Public, Static
|
|
|
|
|
+// Description: Returns the name of the InterfaceMaker function
|
|
|
|
|
+// generated to define the Python class for the
|
|
|
|
|
+// indicated struct type.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+string InterfaceMakerPythonObj::
|
|
|
|
|
+get_builder_name(CPPType *struct_type) {
|
|
|
|
|
+ return "get_python_class_" +
|
|
|
|
|
+ InterrogateBuilder::clean_identifier(struct_type->get_local_name(&parser));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: InterfaceMakerPythonObj::get_wrapper_prefix
|
|
|
|
|
+// Access: Protected, Virtual
|
|
|
|
|
+// Description: Returns the prefix string used to generate wrapper
|
|
|
|
|
+// function names.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+string InterfaceMakerPythonObj::
|
|
|
|
|
+get_wrapper_prefix() {
|
|
|
|
|
+ return "wpo_";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: InterfaceMakerPythonObj::write_class_wrapper
|
|
|
|
|
+// Access: Private
|
|
|
|
|
+// Description: Writes a function that will define the Python class.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+void InterfaceMakerPythonObj::
|
|
|
|
|
+write_class_wrapper(ostream &out, InterfaceMaker::Object *object) {
|
|
|
|
|
+ CPPType *struct_type = object->_itype._cpptype;
|
|
|
|
|
+ if (struct_type == (CPPType *)NULL) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ string name = get_builder_name(struct_type);
|
|
|
|
|
+ string python_name =
|
|
|
|
|
+ InterrogateBuilder::clean_identifier(struct_type->get_simple_name());
|
|
|
|
|
+
|
|
|
|
|
+ out << "/*\n"
|
|
|
|
|
+ << " * Generate unique Python class for "
|
|
|
|
|
+ << struct_type->get_local_name(&parser) << "\n"
|
|
|
|
|
+ << " */\n"
|
|
|
|
|
+ << "PyObject *\n"
|
|
|
|
|
+ << name << "() {\n"
|
|
|
|
|
+ << " static PyObject *wrapper = (PyObject *)NULL;\n"
|
|
|
|
|
+ << " static PyMethodDef methods[] = {\n";
|
|
|
|
|
+
|
|
|
|
|
+ int methods_size = 0;
|
|
|
|
|
+ int class_methods_size = 0;
|
|
|
|
|
+
|
|
|
|
|
+ Functions::iterator fi;
|
|
|
|
|
+ for (fi = object->_methods.begin(); fi != object->_methods.end(); ++fi) {
|
|
|
|
|
+ Function *func = (*fi);
|
|
|
|
|
+ if (func->_has_this) {
|
|
|
|
|
+ out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_name
|
|
|
|
|
+ << ", METH_VARARGS },\n";
|
|
|
|
|
+ methods_size++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ out << " };\n"
|
|
|
|
|
+ << " static const int methods_size = " << methods_size << ";\n\n"
|
|
|
|
|
+ << " static PyMethodDef class_methods[] = {\n";
|
|
|
|
|
+
|
|
|
|
|
+ for (fi = object->_methods.begin(); fi != object->_methods.end(); ++fi) {
|
|
|
|
|
+ Function *func = (*fi);
|
|
|
|
|
+ if (!func->_has_this) {
|
|
|
|
|
+ out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_name
|
|
|
|
|
+ << ", METH_VARARGS },\n";
|
|
|
|
|
+ class_methods_size++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ out << " };\n"
|
|
|
|
|
+ << " static const int class_methods_size = " << class_methods_size << ";\n\n"
|
|
|
|
|
+ << " if (wrapper == (PyObject *)NULL) {\n"
|
|
|
|
|
+ << " int i;\n"
|
|
|
|
|
+ << " PyObject *bases = PyTuple_New(0);\n"
|
|
|
|
|
+ << " PyObject *dict = PyDict_New();\n"
|
|
|
|
|
+ << " PyObject *name = PyString_FromString(\""
|
|
|
|
|
+ << python_name << "\");\n"
|
|
|
|
|
+ << " wrapper = PyClass_New(bases, dict, name);\n"
|
|
|
|
|
+ << " for (i = 0; i < methods_size; ++i) {\n"
|
|
|
|
|
+ << " PyObject *function, *method;\n"
|
|
|
|
|
+ << " function = PyCFunction_New(&methods[i], (PyObject *)NULL);\n"
|
|
|
|
|
+ << " method = PyMethod_New(function, (PyObject *)NULL, wrapper);\n"
|
|
|
|
|
+ << " PyDict_SetItemString(dict, methods[i].ml_name, method);\n"
|
|
|
|
|
+ << " }\n"
|
|
|
|
|
+ << " for (i = 0; i < class_methods_size; ++i) {\n"
|
|
|
|
|
+ << " PyObject *function;\n"
|
|
|
|
|
+ << " function = PyCFunction_New(&class_methods[i], (PyObject *)NULL);\n"
|
|
|
|
|
+ << " PyDict_SetItemString(dict, class_methods[i].ml_name, function);\n"
|
|
|
|
|
+ << " }\n"
|
|
|
|
|
+ << " }\n"
|
|
|
|
|
+ << " return wrapper;\n"
|
|
|
|
|
+ << "}\n\n";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: InterfaceMakerPythonObj::write_prototype_for
|
|
|
|
|
+// Access: Private
|
|
|
|
|
+// Description: Writes the prototype for the indicated function.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+void InterfaceMakerPythonObj::
|
|
|
|
|
+write_prototype_for(ostream &out, InterfaceMaker::Function *func) {
|
|
|
|
|
+ out << "static PyObject *"
|
|
|
|
|
+ << func->_name << "(PyObject *self, PyObject *args);\n";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: InterfaceMakerPythonObj::write_function_for
|
|
|
|
|
+// Access: Private
|
|
|
|
|
+// Description: Writes the definition for a function that will call
|
|
|
|
|
+// the indicated C++ function or method.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+void InterfaceMakerPythonObj::
|
|
|
|
|
+write_function_for(ostream &out, InterfaceMaker::Function *func) {
|
|
|
|
|
+ Function::Remaps::const_iterator ri;
|
|
|
|
|
+ out << "/*\n"
|
|
|
|
|
+ << " * Python object wrapper for\n";
|
|
|
|
|
+ for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
|
|
|
|
|
+ FunctionRemap *remap = (*ri);
|
|
|
|
|
+ out << " * ";
|
|
|
|
|
+ remap->write_orig_prototype(out, 0);
|
|
|
|
|
+ out << "\n";
|
|
|
|
|
+ }
|
|
|
|
|
+ out << " */\n";
|
|
|
|
|
+
|
|
|
|
|
+ out << "static PyObject *"
|
|
|
|
|
+ << func->_name << "(PyObject *, PyObject *args) {\n";
|
|
|
|
|
+
|
|
|
|
|
+ // Now write out each instance of the overloaded function.
|
|
|
|
|
+ string expected_params = "Arguments must match one of:";
|
|
|
|
|
+
|
|
|
|
|
+ for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
|
|
|
|
|
+ FunctionRemap *remap = (*ri);
|
|
|
|
|
+ expected_params += "\\n ";
|
|
|
|
|
+ write_function_instance(out, 2, func, remap, expected_params);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // If we get here in the generated code, none of the parameters were
|
|
|
|
|
+ // valid. Generate an error exception. (We don't rely on the error
|
|
|
|
|
+ // already generated by ParseTuple(), because it only reports the
|
|
|
|
|
+ // error for one flavor of the function, whereas we might accept
|
|
|
|
|
+ // multiple flavors for the different overloaded C++ function
|
|
|
|
|
+ // signatures.
|
|
|
|
|
+
|
|
|
|
|
+ out << " PyErr_SetString(PyExc_TypeError, \"" << expected_params << "\");\n"
|
|
|
|
|
+ << " return (PyObject *)NULL;\n";
|
|
|
|
|
+
|
|
|
|
|
+ out << "}\n\n";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: InterfaceMakerPythonObj::write_function_instance
|
|
|
|
|
+// Access: Private
|
|
|
|
|
+// Description: Writes out the part of a function that handles a
|
|
|
|
|
+// single instance of an overloaded function.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+void InterfaceMakerPythonObj::
|
|
|
|
|
+write_function_instance(ostream &out, int indent_level,
|
|
|
|
|
+ InterfaceMaker::Function *func,
|
|
|
|
|
+ FunctionRemap *remap, string &expected_params) {
|
|
|
|
|
+ indent(out, indent_level) << "{\n";
|
|
|
|
|
+ indent(out, indent_level + 2) << "/* ";
|
|
|
|
|
+ remap->write_orig_prototype(out, 0);
|
|
|
|
|
+ out << " */\n\n";
|
|
|
|
|
+
|
|
|
|
|
+ string format_specifiers;
|
|
|
|
|
+ string parameter_list;
|
|
|
|
|
+ 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().
|
|
|
|
|
+
|
|
|
|
|
+ expected_params += remap->_cppfunc->get_simple_name();
|
|
|
|
|
+ expected_params += "(";
|
|
|
|
|
+
|
|
|
|
|
+ int pn;
|
|
|
|
|
+ for (pn = 0; pn < (int)remap->_parameters.size(); pn++) {
|
|
|
|
|
+ if (pn != 0) {
|
|
|
|
|
+ expected_params += ", ";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ indent(out, indent_level + 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 {
|
|
|
|
|
+ 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)";
|
|
|
|
|
+ }
|
|
|
|
|
+ expected_params += "string";
|
|
|
|
|
+
|
|
|
|
|
+ } else if (TypeManager::is_bool(type)) {
|
|
|
|
|
+ out << "PyObject *" << param_name;
|
|
|
|
|
+ format_specifiers += "O";
|
|
|
|
|
+ parameter_list += ", &" + param_name;
|
|
|
|
|
+ pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)";
|
|
|
|
|
+ expected_params += "bool";
|
|
|
|
|
+
|
|
|
|
|
+ } 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);";
|
|
|
|
|
+ expected_params += "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);";
|
|
|
|
|
+ expected_params += "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);";
|
|
|
|
|
+ expected_params += "unsigned int";
|
|
|
|
|
+
|
|
|
|
|
+ } else if (TypeManager::is_integer(type)) {
|
|
|
|
|
+ out << "int " << param_name;
|
|
|
|
|
+ format_specifiers += "i";
|
|
|
|
|
+ parameter_list += ", &" + param_name;
|
|
|
|
|
+ expected_params += "integer";
|
|
|
|
|
+
|
|
|
|
|
+ } else if (TypeManager::is_float(type)) {
|
|
|
|
|
+ out << "double " << param_name;
|
|
|
|
|
+ format_specifiers += "d";
|
|
|
|
|
+ parameter_list += ", &" + param_name;
|
|
|
|
|
+ expected_params += "float";
|
|
|
|
|
+
|
|
|
|
|
+ } else if (TypeManager::is_char_pointer(type)) {
|
|
|
|
|
+ out << "char *" << param_name;
|
|
|
|
|
+ format_specifiers += "s";
|
|
|
|
|
+ parameter_list += ", &" + param_name;
|
|
|
|
|
+ expected_params += "string";
|
|
|
|
|
+
|
|
|
|
|
+ } else if (TypeManager::is_pointer(type)) {
|
|
|
|
|
+ FunctionWriterPtrFromPython *writer = get_ptr_from_python(type);
|
|
|
|
|
+ writer->get_pointer_type()->output_instance(out, param_name, &parser);
|
|
|
|
|
+ format_specifiers += "O&";
|
|
|
|
|
+ parameter_list += ", &" + writer->get_name() + ", &" + param_name;
|
|
|
|
|
+ expected_params += writer->get_type()->get_preferred_name();
|
|
|
|
|
+
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // Ignore a parameter.
|
|
|
|
|
+ out << "PyObject *" << param_name;
|
|
|
|
|
+ format_specifiers += "O";
|
|
|
|
|
+ parameter_list += ", &" + param_name;
|
|
|
|
|
+ expected_params += "any";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (remap->_parameters[pn]._has_name) {
|
|
|
|
|
+ expected_params += " " + remap->_parameters[pn]._name;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ out << ";\n";
|
|
|
|
|
+ pexprs.push_back(pexpr_string);
|
|
|
|
|
+ }
|
|
|
|
|
+ expected_params += ")";
|
|
|
|
|
+
|
|
|
|
|
+ indent(out, indent_level + 2)
|
|
|
|
|
+ << "if (PyArg_ParseTuple(args, \"" << format_specifiers
|
|
|
|
|
+ << "\"" << parameter_list << ")) {\n";
|
|
|
|
|
+
|
|
|
|
|
+ if (!extra_convert.empty()) {
|
|
|
|
|
+ indent(out, indent_level + 3)
|
|
|
|
|
+ << extra_convert << "\n";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!extra_param_check.empty()) {
|
|
|
|
|
+ indent(out, indent_level + 4)
|
|
|
|
|
+ << "if (" << extra_param_check.substr(3) << ") {\n";
|
|
|
|
|
+ if (!extra_cleanup.empty()) {
|
|
|
|
|
+ indent(out, indent_level + 5)
|
|
|
|
|
+ << extra_cleanup << "\n";
|
|
|
|
|
+ }
|
|
|
|
|
+ indent(out, indent_level + 6)
|
|
|
|
|
+ << "PyErr_SetString(PyExc_TypeError, \"Invalid parameters.\");\n";
|
|
|
|
|
+ indent(out, indent_level + 6)
|
|
|
|
|
+ << "return (PyObject *)NULL;\n";
|
|
|
|
|
+ indent(out, indent_level + 4)
|
|
|
|
|
+ << "}\n";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (track_interpreter) {
|
|
|
|
|
+ indent(out, indent_level + 4)
|
|
|
|
|
+ << "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, indent_level + 4, false, "param0", pexprs);
|
|
|
|
|
+
|
|
|
|
|
+ CPPType *type = remap->_return_type->get_orig_type();
|
|
|
|
|
+ indent(out, indent_level + 4);
|
|
|
|
|
+ type->output_instance(out, "return_value", &parser);
|
|
|
|
|
+ out << " = " << return_expr << ";\n";
|
|
|
|
|
+
|
|
|
|
|
+ if (track_interpreter) {
|
|
|
|
|
+ indent(out, indent_level + 4)
|
|
|
|
|
+ << "in_interpreter = 1;\n";
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!extra_cleanup.empty()) {
|
|
|
|
|
+ indent(out, indent_level + 3)
|
|
|
|
|
+ << extra_cleanup << "\n";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
|
|
|
|
|
+ test_assert(out, indent_level + 4);
|
|
|
|
|
+ pack_return_value(out, indent_level + 4, remap, return_expr);
|
|
|
|
|
+
|
|
|
|
|
+ } else {
|
|
|
|
|
+ string return_expr =
|
|
|
|
|
+ remap->call_function(out, indent_level + 4, true, "param0", pexprs);
|
|
|
|
|
+ if (return_expr.empty()) {
|
|
|
|
|
+ if (track_interpreter) {
|
|
|
|
|
+ indent(out, indent_level + 4)
|
|
|
|
|
+ << "in_interpreter = 1;\n";
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!extra_cleanup.empty()) {
|
|
|
|
|
+ indent(out, indent_level + 3)
|
|
|
|
|
+ << extra_cleanup << "\n";
|
|
|
|
|
+ }
|
|
|
|
|
+ test_assert(out, indent_level + 4);
|
|
|
|
|
+ indent(out, indent_level + 4)
|
|
|
|
|
+ << "return Py_BuildValue(\"\");\n";
|
|
|
|
|
+
|
|
|
|
|
+ } else {
|
|
|
|
|
+ CPPType *type = remap->_return_type->get_temporary_type();
|
|
|
|
|
+ indent(out, indent_level + 4);
|
|
|
|
|
+ type->output_instance(out, "return_value", &parser);
|
|
|
|
|
+ out << " = " << return_expr << ";\n";
|
|
|
|
|
+ if (track_interpreter) {
|
|
|
|
|
+ indent(out, indent_level + 4)
|
|
|
|
|
+ << "in_interpreter = 1;\n";
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!extra_cleanup.empty()) {
|
|
|
|
|
+ indent(out, indent_level + 3)
|
|
|
|
|
+ << extra_cleanup << "\n";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
|
|
|
|
|
+ test_assert(out, indent_level + 4);
|
|
|
|
|
+ pack_return_value(out, indent_level + 4, remap, remap->_return_type->temporary_to_return(return_expr));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ indent(out, indent_level + 2) << "}\n";
|
|
|
|
|
+ indent(out, indent_level + 2)
|
|
|
|
|
+ << "PyErr_Clear();\n"; // Clear the error generated by ParseTuple()
|
|
|
|
|
+ indent(out, indent_level)
|
|
|
|
|
+ << "}\n";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: InterfaceMakerPythonObj::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 InterfaceMakerPythonObj::
|
|
|
|
|
+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 {
|
|
|
|
|
+ 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(type)) {
|
|
|
|
|
+ bool caller_manages = remap->_return_value_needs_management;
|
|
|
|
|
+
|
|
|
|
|
+ FunctionWriterPtrToPython *writer = get_ptr_to_python(type);
|
|
|
|
|
+ indent(out, indent_level)
|
|
|
|
|
+ << "return " << writer->get_name() << "(("
|
|
|
|
|
+ << writer->get_pointer_type()->get_local_name(&parser) << ")"
|
|
|
|
|
+ << return_expr << ", " << caller_manages << ");\n";
|
|
|
|
|
+
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // Return None.
|
|
|
|
|
+ indent(out, indent_level)
|
|
|
|
|
+ << "return Py_BuildValue(\"\");\n";
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: InterfaceMakerPythonObj::get_ptr_from_python
|
|
|
|
|
+// Access: Private
|
|
|
|
|
+// Description: Returns a FunctionWriter pointer suitable for
|
|
|
|
|
+// converting from a Python wrapper of the indicated
|
|
|
|
|
+// type to the corresponding C++ pointer.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+FunctionWriterPtrFromPython *InterfaceMakerPythonObj::
|
|
|
|
|
+get_ptr_from_python(CPPType *type) {
|
|
|
|
|
+ PtrConverter::iterator ci;
|
|
|
|
|
+ ci = _from_python.find(type);
|
|
|
|
|
+ if (ci != _from_python.end()) {
|
|
|
|
|
+ // We've previously used this type.
|
|
|
|
|
+ return (FunctionWriterPtrFromPython *)(*ci).second;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ FunctionWriter *writer =
|
|
|
|
|
+ _function_writers.add_writer(new FunctionWriterPtrFromPython(type));
|
|
|
|
|
+ _from_python.insert(PtrConverter::value_type(type, writer));
|
|
|
|
|
+ return (FunctionWriterPtrFromPython *)writer;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: InterfaceMakerPythonObj::get_ptr_to_python
|
|
|
|
|
+// Access: Private
|
|
|
|
|
+// Description: Returns a FunctionWriter pointer suitable for
|
|
|
|
|
+// converting from a C++ pointer of the indicated
|
|
|
|
|
+// type to the corresponding Python wrapper.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+FunctionWriterPtrToPython *InterfaceMakerPythonObj::
|
|
|
|
|
+get_ptr_to_python(CPPType *type) {
|
|
|
|
|
+ PtrConverter::iterator ci;
|
|
|
|
|
+ ci = _to_python.find(type);
|
|
|
|
|
+ if (ci != _to_python.end()) {
|
|
|
|
|
+ // We've previously used this type.
|
|
|
|
|
+ return (FunctionWriterPtrToPython *)(*ci).second;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ FunctionWriter *writer =
|
|
|
|
|
+ _function_writers.add_writer(new FunctionWriterPtrToPython(type));
|
|
|
|
|
+ _to_python.insert(PtrConverter::value_type(type, writer));
|
|
|
|
|
+ return (FunctionWriterPtrToPython *)writer;
|
|
|
|
|
+}
|