| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512 |
- // 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";
- }
- }
|