diff --git a/dtool/src/dtoolutil/test_pfstream.cxx b/dtool/src/dtoolutil/test_pfstream.cxx index 5cc92dc74d..a1959b336f 100644 --- a/dtool/src/dtoolutil/test_pfstream.cxx +++ b/dtool/src/dtoolutil/test_pfstream.cxx @@ -1,49 +1,49 @@ -// Filename: test_pfstream.cxx -// Created by: drose (31Jul02) -// -//////////////////////////////////////////////////////////////////// -// -// 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 -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "dtoolbase.h" -#include "pfstream.h" - -int -main(int argc, char *argv[]) { - if (argc < 2) { - cout << "test_pfstream command-line\n"; - return (1); - } - - // Build one command out of the arguments. - string cmd; - cmd = argv[1]; - for (int i = 2; i < argc; i++) { - cmd += " "; - cmd += argv[i]; - } - - cout << "Executing command:\n" << cmd << "\n"; - - IPipeStream in(cmd); - - char c; - c = in.get(); - while (in && !in.fail() && !in.eof()) { - cout.put(toupper(c)); - c = in.get(); - } - - return (0); -} +// Filename: test_pfstream.cxx +// Created by: drose (31Jul02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "dtoolbase.h" +#include "pfstream.h" + +int +main(int argc, char *argv[]) { + if (argc < 2) { + cout << "test_pfstream command-line\n"; + return (1); + } + + // Build one command out of the arguments. + string cmd; + cmd = argv[1]; + for (int i = 2; i < argc; i++) { + cmd += " "; + cmd += argv[i]; + } + + cout << "Executing command:\n" << cmd << "\n"; + + IPipeStream in(cmd); + + char c; + c = in.get(); + while (in && !in.fail() && !in.eof()) { + cout.put(toupper(c)); + c = in.get(); + } + + return (0); +} diff --git a/dtool/src/interrogate/interfaceMaker.cxx b/dtool/src/interrogate/interfaceMaker.cxx index 42df5a7d41..07a538151c 100644 --- a/dtool/src/interrogate/interfaceMaker.cxx +++ b/dtool/src/interrogate/interfaceMaker.cxx @@ -147,14 +147,14 @@ generate_wrappers() { record_object(type_index); - if(interrogate_type_is_enum(ti)) - { - int enum_count = interrogate_type_number_of_enum_values(ti); - for(int xx = 0; xx< enum_count; xx++) - { -// printf(" PyModule_AddIntConstant(module,\"%s\",%d)\n",interrogate_type_enum_value_name(ti,xx),interrogate_type_enum_value(ti,xx)); - } - } + if(interrogate_type_is_enum(ti)) + { + int enum_count = interrogate_type_number_of_enum_values(ti); + for(int xx = 0; xx< enum_count; xx++) + { +// printf(" PyModule_AddIntConstant(module,\"%s\",%d)\n",interrogate_type_enum_value_name(ti,xx),interrogate_type_enum_value(ti,xx)); + } + } ++ti; diff --git a/dtool/src/interrogate/interfaceMakerPython.cxx b/dtool/src/interrogate/interfaceMakerPython.cxx index 9400e0990a..1944c1adec 100644 --- a/dtool/src/interrogate/interfaceMakerPython.cxx +++ b/dtool/src/interrogate/interfaceMakerPython.cxx @@ -48,9 +48,9 @@ write_includes(ostream &out) { << "#else\n" << " #include \"Python.h\"\n" << "#endif\n" - << "#ifdef HAVE_LONG_LONG\n" - << "#undef HAVE_LONG_LONG\n" - << "#endif \n"; + << "#ifdef HAVE_LONG_LONG\n" + << "#undef HAVE_LONG_LONG\n" + << "#endif \n"; } diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index b11e3b8f05..53feb51ff0 100755 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -29,26 +29,26 @@ #include "cppStructType.h" #include "vector" #include "cppParameterList.h" -#include "algorithm" +#include "algorithm" + +#include +#include + -#include -#include - - extern bool inside_python_native; extern InterrogateType dummy_type; -extern std::string EXPORT_IMPORT_PREFEX; +extern std::string EXPORT_IMPORT_PREFEX; #define CLASS_PREFEX "Dtool_" #define INSTANCE_PREFEX "Dtool_" #define BASE_INSTANCE_NAME "Dtool_PyInstDef" #define MAX_COMMENT_SIZE 1024 - - -///////////////////////////////////////////////////////// -// Name Remaper... -// Snagged from ffi py code.... -///////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////// +// Name Remaper... +// Snagged from ffi py code.... +///////////////////////////////////////////////////////// struct RenameSet { char * _from; @@ -323,61 +323,61 @@ std::string methodNameFromCppName(std::string cppName, const std::string &class /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// -std::string make_safe_comment(const std::string & name_in) -{ - - - std::string name(name_in.substr(0,MAX_COMMENT_SIZE)); - - static const char safe_chars2[] = ",.[](){}:;'`~!@#$%^&*+\\=/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_- "; - std::string result = name; - - size_t pos = result.find_first_of("\\"); - while (pos != std::string::npos) - { - result.replace(pos,1,"_"); - pos = result.find_first_of("\\"); - } - - - - - pos = result.find_first_of("\n"); - while (pos != std::string::npos) - { - result.replace(pos,1,"\\n"); - pos = result.find_first_of("\n"); - } - - - pos = result.find_first_not_of(safe_chars2); - while (pos != std::string::npos) - { - result[pos] = ' '; - pos = result.find_first_not_of(safe_chars2); - } - - return result; -} -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -std::string make_safe_name(const std::string & name) -{ - return InterrogateBuilder::clean_identifier(name); - - static const char safe_chars2[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; - std::string result = name; - - size_t pos = result.find_first_not_of(safe_chars2); - while (pos != std::string::npos) - { - result[pos] = '_'; - pos = result.find_first_not_of(safe_chars2); - } - - return result; -} +std::string make_safe_comment(const std::string & name_in) +{ + + + std::string name(name_in.substr(0,MAX_COMMENT_SIZE)); + + static const char safe_chars2[] = ",.[](){}:;'`~!@#$%^&*+\\=/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_- "; + std::string result = name; + + size_t pos = result.find_first_of("\\"); + while (pos != std::string::npos) + { + result.replace(pos,1,"_"); + pos = result.find_first_of("\\"); + } + + + + + pos = result.find_first_of("\n"); + while (pos != std::string::npos) + { + result.replace(pos,1,"\\n"); + pos = result.find_first_of("\n"); + } + + + pos = result.find_first_not_of(safe_chars2); + while (pos != std::string::npos) + { + result[pos] = ' '; + pos = result.find_first_not_of(safe_chars2); + } + + return result; +} +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +std::string make_safe_name(const std::string & name) +{ + return InterrogateBuilder::clean_identifier(name); + + static const char safe_chars2[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; + std::string result = name; + + size_t pos = result.find_first_not_of(safe_chars2); + while (pos != std::string::npos) + { + result[pos] = '_'; + pos = result.find_first_not_of(safe_chars2); + } + + return result; +} bool isInplaceFunction(const std::string &cppName) { @@ -390,8 +390,8 @@ bool isInplaceFunction(const std::string &cppName) return false; } -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative::GetValideChildClasses( std::map< std::string ,CastDetails > &answer, CPPStructType * inclass, const std::string &up_cast_seed, bool downcastposible) { if(inclass == NULL) @@ -434,10 +434,10 @@ void InterfaceMakerPythonNative::GetValideChildClasses( std::map< std::string } } } -/////////////////////////////////////////////////////////////////////////////// -// Function : WriteReturnInstance -// -/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +// Function : WriteReturnInstance +// +/////////////////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative::WriteReturnInstance(ostream &out, int indent_level, std::string &return_expr, std::string &ows_memory_flag, const std::string &class_name, CPPType *ctype, bool inplace) { if(inplace == true) @@ -665,23 +665,23 @@ void InterfaceMakerPythonNative::write_ClasseDetails(ostream &out, Object * obj) if( (func)) { ostringstream GetThis; - GetThis << " "<_ptr_to_object;\n"; - out << " if(requested_type == &Dtool_"<second._is_legal_py_class) { - out << " if(requested_type == &Dtool_"<second._to_class_name)<<")\n"; - out << " return "<< di->second._up_cast_string << " local_this;\n"; - } + out << " if(requested_type == &Dtool_"<second._to_class_name)<<")\n"; + out << " return "<< di->second._up_cast_string << " local_this;\n"; + } } out << " return NULL;\n"; @@ -764,12 +764,12 @@ void InterfaceMakerPythonNative::write_ClasseDetails(ostream &out, Object * obj) { if(di->second._can_downcast && di->second._is_legal_py_class) { - out << " if(from_type == &Dtool_"<second._to_class_name)<<")\n"; - out << " {\n"; - out << " "<< di->second._to_class_name << "* other_this = ("<< di->second._to_class_name << "*)from_this;\n" ; + out << " if(from_type == &Dtool_"<second._to_class_name)<<")\n"; + out << " {\n"; + out << " "<< di->second._to_class_name << "* other_this = ("<< di->second._to_class_name << "*)from_this;\n" ; out << " return ("<< cClassName << "*)other_this;\n"; - out << " }\n"; - } + out << " }\n"; + } } out << " return (void *) NULL;\n"; out << "}\n"; @@ -799,23 +799,23 @@ void InterfaceMakerPythonNative::write_ClasseDeclarations(ostream &out, ostream } else { - out << "Define_Module_Class("<<_def->module_name << "," << class_name << "," <module_name << "," << class_name << "," <_itype._cpptype)) { out << "Define_Module_ClassRef_Private("<<_def->module_name << "," << class_name << "," << class_name <<"_localtype,"<< classNameFromCppName(c_class_name) <<");\n"; } else { - out << "Define_Module_Class_Private("<<_def->module_name<< "," << class_name << "," << class_name <<"_localtype,"<< classNameFromCppName(c_class_name) << ");\n"; - } - } - - - if(out_h != NULL) + out << "Define_Module_Class_Private("<<_def->module_name<< "," << class_name << "," << class_name <<"_localtype,"<< classNameFromCppName(c_class_name) << ");\n"; + } + } + + + if(out_h != NULL) *out_h << "extern \"C\" " << EXPORT_IMPORT_PREFEX << " struct Dtool_PyTypedObject Dtool_" << class_name <<";\n"; } //////////////////////////////////////////////////////////////////// @@ -850,17 +850,17 @@ void InterfaceMakerPythonNative::write_module_support(ostream &out,ostream *out_ Object *object = (*oi).second; if(!object->_itype.get_outer_class()) { - if(object->_itype.is_enum()) - { - int enum_count = object->_itype.number_of_enum_values(); - if(enum_count > 0) - { + if(object->_itype.is_enum()) + { + int enum_count = object->_itype.number_of_enum_values(); + if(enum_count > 0) + { out << "//********************************************************************\n"; out << "//*** Module Enums .." << object->_itype.get_scoped_name() << "\n"; out << "//********************************************************************\n"; } - for(int xx = 0; xx< enum_count; xx++) - out << " PyModule_AddIntConstant(module,\"" << classNameFromCppName(object->_itype.get_enum_value_name(xx)) <<"\","<< object->_itype.get_enum_value(xx) << ");\n"; + for(int xx = 0; xx< enum_count; xx++) + out << " PyModule_AddIntConstant(module,\"" << classNameFromCppName(object->_itype.get_enum_value_name(xx)) <<"\","<< object->_itype.get_enum_value(xx) << ");\n"; } } } @@ -877,9 +877,9 @@ void InterfaceMakerPythonNative::write_module_support(ostream &out,ostream *out_ record_function(dummy_type, func_index); } if(iman.has_int_value()) - out << " PyModule_AddIntConstant(module,\"" << classNameFromCppName(iman.get_name()) <<"\","<< iman.get_int_value() << ");\n"; + out << " PyModule_AddIntConstant(module,\"" << classNameFromCppName(iman.get_name()) <<"\","<< iman.get_int_value() << ");\n"; else - out << " PyModule_AddStringConstant(module,\"" << classNameFromCppName(iman.get_name()) <<"\",\""<< iman.get_definition().c_str() << "\");\n"; + out << " PyModule_AddStringConstant(module,\"" << classNameFromCppName(iman.get_name()) <<"\",\""<< iman.get_definition().c_str() << "\");\n"; } @@ -933,7 +933,7 @@ void InterfaceMakerPythonNative::write_module_support(ostream &out,ostream *out_ out << " { NULL, NULL ,0,NULL}\n" << "};\n\n"; out << "struct LibrayDef " << moduledefdef->library_name <<"_moddef = {python_simple_funcs,BuildInstants};\n"; - if(out_h != NULL) + if(out_h != NULL) *out_h << "extern struct LibrayDef " << moduledefdef->library_name <<"_moddef;\n"; } ///////////////////////////////////////////////////////////////////////////// @@ -967,175 +967,175 @@ void InterfaceMakerPythonNative::write_module(ostream &out,ostream *out_h, Inter // conventions for the slaot interface.. //////////////////////////////////////////////////////////////////// bool GetSlotedFunctinDef(const std::string &thimputstring, std::string &answer_location, int &wraper_type) -{ - wraper_type = -1; - - if(thimputstring.size() > 4 && thimputstring[0] == '_' && thimputstring[1] == '_') - { - if(thimputstring == "__add__") - { - answer_location = "tp_as_number->nb_add"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__sub__") - { - answer_location = "tp_as_number->nb_subtract"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__mul__") - { - answer_location = "tp_as_number->nb_multiply"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__div__") - { - answer_location = "tp_as_number->nb_divide"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__mod__") - { - answer_location = "tp_as_number->nb_remainder"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__lshift__") - { - answer_location = "tp_as_number->nb_lshift"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__rshift__") - { - answer_location = "tp_as_number->nb_rshift"; - wraper_type = 3; - return true; - } - - - if(thimputstring == "__xor__") - { - answer_location = "tp_as_number->nb_xor"; - wraper_type = 3; - return true; - } - - - if(thimputstring == "__and__") - { - answer_location = "tp_as_number->nb_and"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__or__") - { - answer_location = "tp_as_number->nb_or"; - wraper_type = 3; - return true; - } - - - if(thimputstring == "__iadd__") - { - answer_location = "tp_as_number->nb_inplace_add"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__isub__") - { - answer_location = "tp_as_number->nb_inplace_subtract"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__imul__") - { - answer_location = "tp_as_number->nb_inplace_multiply"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__idiv__") - { - answer_location = "tp_as_number->nb_inplace_divide"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__imod__") - { - answer_location = ".tp_as_number->nb_inplace_remainder"; - wraper_type = 3; - return true; - } - - - if(thimputstring == "__ilshift__") - { - answer_location = "tp_as_number->nb_inplace_lshift"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__irshift__") - { - answer_location = "tp_as_number->nb_inplace_rshift"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__iand__") - { - answer_location = "tp_as_number->nb_inplace_and"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__ixor__") - { - answer_location = "tp_as_number->nb_inplace_xor"; - wraper_type = 3; - return true; - } - - if(thimputstring == "__int__") - { - answer_location = "tp_as_number->nb_int"; - wraper_type = 2; - return true; - } - -// if(thimputstring == "__coerce__") -// { -// answer_location = "tp_as_number->nb_coerce"; -// return true; -// } - - // mapping methods - if(thimputstring == "__getitem__") - { - answer_location = "tp_as_mapping->mp_subscript"; - wraper_type = 3; - return true; - } - - //Direct methods - if(thimputstring == "__call__") - { - answer_location = "tp_call"; - //wraper_type = 1; - return true; +{ + wraper_type = -1; + + if(thimputstring.size() > 4 && thimputstring[0] == '_' && thimputstring[1] == '_') + { + if(thimputstring == "__add__") + { + answer_location = "tp_as_number->nb_add"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__sub__") + { + answer_location = "tp_as_number->nb_subtract"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__mul__") + { + answer_location = "tp_as_number->nb_multiply"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__div__") + { + answer_location = "tp_as_number->nb_divide"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__mod__") + { + answer_location = "tp_as_number->nb_remainder"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__lshift__") + { + answer_location = "tp_as_number->nb_lshift"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__rshift__") + { + answer_location = "tp_as_number->nb_rshift"; + wraper_type = 3; + return true; + } + + + if(thimputstring == "__xor__") + { + answer_location = "tp_as_number->nb_xor"; + wraper_type = 3; + return true; + } + + + if(thimputstring == "__and__") + { + answer_location = "tp_as_number->nb_and"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__or__") + { + answer_location = "tp_as_number->nb_or"; + wraper_type = 3; + return true; + } + + + if(thimputstring == "__iadd__") + { + answer_location = "tp_as_number->nb_inplace_add"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__isub__") + { + answer_location = "tp_as_number->nb_inplace_subtract"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__imul__") + { + answer_location = "tp_as_number->nb_inplace_multiply"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__idiv__") + { + answer_location = "tp_as_number->nb_inplace_divide"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__imod__") + { + answer_location = ".tp_as_number->nb_inplace_remainder"; + wraper_type = 3; + return true; + } + + + if(thimputstring == "__ilshift__") + { + answer_location = "tp_as_number->nb_inplace_lshift"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__irshift__") + { + answer_location = "tp_as_number->nb_inplace_rshift"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__iand__") + { + answer_location = "tp_as_number->nb_inplace_and"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__ixor__") + { + answer_location = "tp_as_number->nb_inplace_xor"; + wraper_type = 3; + return true; + } + + if(thimputstring == "__int__") + { + answer_location = "tp_as_number->nb_int"; + wraper_type = 2; + return true; + } + +// if(thimputstring == "__coerce__") +// { +// answer_location = "tp_as_number->nb_coerce"; +// return true; +// } + + // mapping methods + if(thimputstring == "__getitem__") + { + answer_location = "tp_as_mapping->mp_subscript"; + wraper_type = 3; + return true; + } + + //Direct methods + if(thimputstring == "__call__") + { + answer_location = "tp_call"; + //wraper_type = 1; + return true; } } return false; @@ -1317,11 +1317,11 @@ void InterfaceMakerPythonNative::write_module_class(ostream &out, Object *obj) out << "//////////////////\n"; out << "static long DTool_HashKey_"<get_key();\n"; out << "}\n\n"; @@ -1337,11 +1337,11 @@ void InterfaceMakerPythonNative::write_module_class(ostream &out, Object *obj) out << "//////////////////\n"; out << "static long DTool_HashKey_"<output(os);\n"; -// out << " return PyString_FromString(os.str().c_str());\n"; - out << " std::string ss = os.str();\n"; - out << " return PyString_FromStringAndSize(ss.data(),ss.length());\n"; + out << " local_this->output(os);\n"; +// out << " return PyString_FromString(os.str().c_str());\n"; + out << " std::string ss = os.str();\n"; + out << " return PyString_FromStringAndSize(ss.data(),ss.length());\n"; out << " };\n"; out << " return Py_BuildValue(\"\");\n"; out << "}\n"; @@ -1381,18 +1381,18 @@ void InterfaceMakerPythonNative::write_module_class(ostream &out, Object *obj) out << "//////////////////\n"; out << "static PyObject * Dtool_Str_"<write(os,0);\n"; + out << " local_this->write(os,0);\n"; else - out << " local_this->write(os);\n"; -// out << " return PyString_FromString(os.str().c_str());\n"; - out << " std::string ss = os.str();\n"; - out << " return PyString_FromStringAndSize(ss.data(),ss.length());\n"; + out << " local_this->write(os);\n"; +// out << " return PyString_FromString(os.str().c_str());\n"; + out << " std::string ss = os.str();\n"; + out << " return PyString_FromStringAndSize(ss.data(),ss.length());\n"; out << " };\n"; out << " return Py_BuildValue(\"\");\n"; out << "}\n"; @@ -1506,13 +1506,13 @@ void InterfaceMakerPythonNative::write_module_class(ostream &out, Object *obj) } else { - if(nested_obj->_itype.is_enum()) - { + if(nested_obj->_itype.is_enum()) + { out << " // Enum "<< nested_obj->_itype.get_scoped_name() << ";\n"; - int enum_count = nested_obj->_itype.number_of_enum_values(); - for(int xx = 0; xx< enum_count; xx++) - out << " PyDict_SetItemString(Dtool_" << ClassName << ".As_PyTypeObject().tp_dict,\"" << classNameFromCppName(nested_obj->_itype.get_enum_value_name(xx)) <<"\",PyInt_FromLong("<< nested_obj->_itype.get_enum_value(xx) << "));\n"; - + int enum_count = nested_obj->_itype.number_of_enum_values(); + for(int xx = 0; xx< enum_count; xx++) + out << " PyDict_SetItemString(Dtool_" << ClassName << ".As_PyTypeObject().tp_dict,\"" << classNameFromCppName(nested_obj->_itype.get_enum_value_name(xx)) <<"\",PyInt_FromLong("<< nested_obj->_itype.get_enum_value(xx) << "));\n"; + } } } @@ -1526,7 +1526,7 @@ void InterfaceMakerPythonNative::write_module_class(ostream &out, Object *obj) out << " Py_INCREF(&Dtool_"<< ClassName << ".As_PyTypeObject());\n"; out << " PyDict_SetItemString(Dtool_"<::iterator sfi; @@ -1538,12 +1538,12 @@ void InterfaceMakerPythonNative::write_module_class(ostream &out, Object *obj) out << "\",PyCFunction_New(&Dtool_Methods_"<< ClassName <<"[" << sfi->first << "],&Dtool_"<< ClassName<< ".As_PyObject()));\n"; } - - - if(is_runtime_typed) - out << " RegisterRuntimeClass(&Dtool_"<_parameters.size() == 1 || (remap->_has_this && remap->_parameters.size() == 2)) { indent(out,indent_level+4) << "// Special Case to Make operator work \n"; - indent(out,indent_level+4) << "if(PyTuple_Check(args) || (kwds != NULL && PyDict_Check(kwds)))\n"; - indent(out,indent_level+4) << " (PyArg_ParseTupleAndKeywords(args,kwds, \"" << format_specifiers1<< "\",key_word_list" << parameter_list << "));\n"; - indent(out,indent_level+4) << "else\n"; - indent(out,indent_level+4) << " (PyArg_Parse(args, \"" << format_specifiers1<< "\"" << parameter_list << "));\n"; - indent(out,indent_level+4) << "if(!PyErr_Occurred())\n"; + indent(out,indent_level+4) << "if(PyTuple_Check(args) || (kwds != NULL && PyDict_Check(kwds)))\n"; + indent(out,indent_level+4) << " (PyArg_ParseTupleAndKeywords(args,kwds, \"" << format_specifiers1<< "\",key_word_list" << parameter_list << "));\n"; + indent(out,indent_level+4) << "else\n"; + indent(out,indent_level+4) << " (PyArg_Parse(args, \"" << format_specifiers1<< "\"" << parameter_list << "));\n"; + indent(out,indent_level+4) << "if(!PyErr_Occurred())\n"; } else indent(out,indent_level+4) << "if (PyArg_ParseTupleAndKeywords(args,kwds, \"" << format_specifiers1 << "\",key_word_list" << parameter_list << "))\n"; diff --git a/dtool/src/interrogate/interfaceMakerPythonObj.cxx b/dtool/src/interrogate/interfaceMakerPythonObj.cxx index 4eb38ac477..d2f0633a04 100644 --- a/dtool/src/interrogate/interfaceMakerPythonObj.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonObj.cxx @@ -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 -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#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(" + - 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 +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#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(" + + 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; +} diff --git a/dtool/src/interrogate/interfaceMakerPythonSimple.cxx b/dtool/src/interrogate/interfaceMakerPythonSimple.cxx index 10d1dc0210..16fc1fbba2 100644 --- a/dtool/src/interrogate/interfaceMakerPythonSimple.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonSimple.cxx @@ -1,497 +1,497 @@ -// 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 -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#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 { - out << "char *" << param_name - << "_str; int " << param_name << "_len"; - format_specifiers += "s#"; - parameter_list += ", &" + param_name - + "_str, &" + param_name + "_len"; - pexpr_string = "basic_string(" + - 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 { - 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 +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#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 { + out << "char *" << param_name + << "_str; int " << param_name << "_len"; + format_specifiers += "s#"; + parameter_list += ", &" + param_name + + "_str, &" + param_name + "_len"; + pexpr_string = "basic_string(" + + 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 { + 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"; + } +} diff --git a/dtool/src/interrogate/interrogateBuilder.cxx b/dtool/src/interrogate/interrogateBuilder.cxx index a2e47e96bd..41ab2e5998 100644 --- a/dtool/src/interrogate/interrogateBuilder.cxx +++ b/dtool/src/interrogate/interrogateBuilder.cxx @@ -326,8 +326,8 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int EXPORT_IMPORT_PREFEX = std::string("EXPCL_") + def->module_name; - for (size_t i=0; i> (istream &in, InterrogateType::EnumValue &d); #include #include -struct Dtool_PyTypedObject; -typedef std::map< int , Dtool_PyTypedObject *> RunTimeTypeDictionary; -typedef std::set RunTimeTypeList; - -EXPCL_DTOOLCONFIG RunTimeTypeDictionary & GetRunTimeDictionary(); -EXPCL_DTOOLCONFIG RunTimeTypeList & GetRunTimeTypeList(); +struct Dtool_PyTypedObject; +typedef std::map< int , Dtool_PyTypedObject *> RunTimeTypeDictionary; +typedef std::set RunTimeTypeList; + +EXPCL_DTOOLCONFIG RunTimeTypeDictionary & GetRunTimeDictionary(); +EXPCL_DTOOLCONFIG RunTimeTypeList & GetRunTimeTypeList(); #endif diff --git a/dtool/src/interrogatedb/py_panda.h b/dtool/src/interrogatedb/py_panda.h index 81468f825d..84ada20127 100755 --- a/dtool/src/interrogatedb/py_panda.h +++ b/dtool/src/interrogatedb/py_panda.h @@ -15,90 +15,90 @@ // panda3d-general@lists.sourceforge.net . // //////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////// -// Too do list .. -// We need a better dispatcher for the functions.. The behavior today is -// try one till it works or you run out of possibilities.. This is anything but optimal -// for performance and is treading on thin ice for function python or c++ will -// course there types to other types. -// -// The linking step will produce allot of warnings -// warning LNK4049: locally defined symbol.. -// -// Get a second coder to review this file and the generated code .. -// -////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +// Too do list .. +// We need a better dispatcher for the functions.. The behavior today is +// try one till it works or you run out of possibilities.. This is anything but optimal +// for performance and is treading on thin ice for function python or c++ will +// course there types to other types. +// +// The linking step will produce allot of warnings +// warning LNK4049: locally defined symbol.. +// +// Get a second coder to review this file and the generated code .. +// +////////////////////////////////////////////////////////////////////////////////////////////// #include #include -#include - -#ifndef NO_RUNTIME_TYPES - +#include + +#ifndef NO_RUNTIME_TYPES + #include "pandabase.h" #include "typedObject.h" #include "typeRegistry.h" #endif - -#ifdef HAVE_LONG_LONG -#undef HAVE_LONG_LONG -#endif - -#include "Python.h" + +#ifdef HAVE_LONG_LONG +#undef HAVE_LONG_LONG +#endif + +#include "Python.h" #include "structmember.h" -#ifdef HAVE_LONG_LONG -#undef HAVE_LONG_LONG -#endif - -using namespace std; - -/////////////////////////////////////////////////////////////////////////////////// -// this is tempory .. untill this is glued better into the panda build system -/////////////////////////////////////////////////////////////////////////////////// - -#ifdef _WIN32 -#define EXPORT_THIS __declspec(dllexport) -#define IMPORT_THIS extern __declspec(dllimport) -#else -#define EXPORT_THIS -#define IMPORT_THIS extern -#endif -/////////////////////////////////////////////////////////////////////////////////// - -struct Dtool_PyTypedObject; -typedef std::map< int , Dtool_PyTypedObject *> RunTimeTypeDictionary; -typedef std::set RunTimeTypeList; - -EXPCL_DTOOLCONFIG RunTimeTypeDictionary & GetRunTimeDictionary(); -EXPCL_DTOOLCONFIG RunTimeTypeList & GetRunTimeTypeList(); - - -////////////////////////////////////////////////////////// -// used to stamp dtool instance.. -#define PY_PANDA_SIGNITURE 0xdeadbeaf -typedef void * ( * ConvertFunctionType )(PyObject *,Dtool_PyTypedObject * ); -typedef void * ( * ConvertFunctionType1 )(void *, Dtool_PyTypedObject *); -typedef void ( *FreeFunction )(PyObject *); -typedef void ( *PyModuleClassInit)(PyObject *module); -inline Dtool_PyTypedObject * Dtool_RuntimeTypeDtoolType(int type); -inline void Dtool_Deallocate_General(PyObject * self); -inline int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2); -// -//////////////////////////////////////////////////////////////////////// -// THIS IS THE INSTANCE CONTAINER FOR ALL panda py objects.... -//////////////////////////////////////////////////////////////////////// -struct Dtool_PyInstDef -{ - PyObject_HEAD - void * _ptr_to_object; - bool _memory_rules; - unsigned long _signiture; - struct Dtool_PyTypedObject * _My_Type; -}; - -//////////////////////////////////////////////////////////////////////// -// A Offset Dictionary Definign How to read the Above Object.. -//////////////////////////////////////////////////////////////////////// +#ifdef HAVE_LONG_LONG +#undef HAVE_LONG_LONG +#endif + +using namespace std; + +/////////////////////////////////////////////////////////////////////////////////// +// this is tempory .. untill this is glued better into the panda build system +/////////////////////////////////////////////////////////////////////////////////// + +#ifdef _WIN32 +#define EXPORT_THIS __declspec(dllexport) +#define IMPORT_THIS extern __declspec(dllimport) +#else +#define EXPORT_THIS +#define IMPORT_THIS extern +#endif +/////////////////////////////////////////////////////////////////////////////////// + +struct Dtool_PyTypedObject; +typedef std::map< int , Dtool_PyTypedObject *> RunTimeTypeDictionary; +typedef std::set RunTimeTypeList; + +EXPCL_DTOOLCONFIG RunTimeTypeDictionary & GetRunTimeDictionary(); +EXPCL_DTOOLCONFIG RunTimeTypeList & GetRunTimeTypeList(); + + +////////////////////////////////////////////////////////// +// used to stamp dtool instance.. +#define PY_PANDA_SIGNITURE 0xdeadbeaf +typedef void * ( * ConvertFunctionType )(PyObject *,Dtool_PyTypedObject * ); +typedef void * ( * ConvertFunctionType1 )(void *, Dtool_PyTypedObject *); +typedef void ( *FreeFunction )(PyObject *); +typedef void ( *PyModuleClassInit)(PyObject *module); +inline Dtool_PyTypedObject * Dtool_RuntimeTypeDtoolType(int type); +inline void Dtool_Deallocate_General(PyObject * self); +inline int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2); +// +//////////////////////////////////////////////////////////////////////// +// THIS IS THE INSTANCE CONTAINER FOR ALL panda py objects.... +//////////////////////////////////////////////////////////////////////// +struct Dtool_PyInstDef +{ + PyObject_HEAD + void * _ptr_to_object; + bool _memory_rules; + unsigned long _signiture; + struct Dtool_PyTypedObject * _My_Type; +}; + +//////////////////////////////////////////////////////////////////////// +// A Offset Dictionary Definign How to read the Above Object.. +//////////////////////////////////////////////////////////////////////// static PyMemberDef standard_type_members[] = { {"this", T_INT, offsetof(Dtool_PyInstDef,_ptr_to_object),READONLY,"C++ This if any"}, {"this_ownership", T_INT, offsetof(Dtool_PyInstDef, _memory_rules), READONLY,"C++ 'this' ownership rules"}, @@ -106,32 +106,32 @@ static PyMemberDef standard_type_members[] = { {"this_metatype", T_OBJECT, offsetof(Dtool_PyInstDef, _My_Type), READONLY,"The dtool meta object"}, {NULL} /* Sentinel */ }; - -//////////////////////////////////////////////////////////////////////// -// The Class Definition Structor For a Dtool python type. -//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// The Class Definition Structor For a Dtool python type. +//////////////////////////////////////////////////////////////////////// struct Dtool_PyTypedObject { // Standard Python Fearures.. PyTypeObject _PyType; // My Class Level Features.. - char * _name; // cpp name for the object + char * _name; // cpp name for the object bool _Dtool_IsRunTimeCapable; // derived from TypedObject - ConvertFunctionType _Dtool_UpcastInterface; // The Upcast Function By Slot - ConvertFunctionType1 _Dtool_DowncastInterface; // The Downcast Function By Slot - FreeFunction _Dtool_FreeInstance; + ConvertFunctionType _Dtool_UpcastInterface; // The Upcast Function By Slot + ConvertFunctionType1 _Dtool_DowncastInterface; // The Downcast Function By Slot + FreeFunction _Dtool_FreeInstance; PyModuleClassInit _Dtool_ClassInit; // The init function pointer // some convience functions.. inline PyTypeObject & As_PyTypeObject(void) { return _PyType; }; inline PyObject & As_PyObject(void) { return (PyObject &)_PyType; }; }; - - -//////////////////////////////////////////////////////////////////////// -// Macro's from Hell.. May want to Just Add this to the Code generator.. -//////////////////////////////////////////////////////////////////////// -#define Define_Dtool_Class(MODULE_NAME, CLASS_NAME, PUBLIC_NAME) \ -static PyNumberMethods Dtool_PyNumberMethods_##CLASS_NAME ={\ + + +//////////////////////////////////////////////////////////////////////// +// Macro's from Hell.. May want to Just Add this to the Code generator.. +//////////////////////////////////////////////////////////////////////// +#define Define_Dtool_Class(MODULE_NAME, CLASS_NAME, PUBLIC_NAME) \ +static PyNumberMethods Dtool_PyNumberMethods_##CLASS_NAME ={\ 0,/*binaryfunc nb_add*/\ 0,/*binaryfunc nb_subtract*/\ 0,/*binaryfunc nb_multiply*/\ @@ -170,29 +170,29 @@ static PyNumberMethods Dtool_PyNumberMethods_##CLASS_NAME ={\ 0,/*binaryfunc nb_true_divide*/\ 0,/*binaryfunc nb_inplace_floor_divide*/\ 0,/*binaryfunc nb_inplace_true_divide*/\ - };\ -static PyMappingMethods Dtool_PyMappingMethods_##CLASS_NAME ={\ + };\ +static PyMappingMethods Dtool_PyMappingMethods_##CLASS_NAME ={\ 0,/*inquiry mp_length */\ 0,/*binaryfunc mp_subscript */\ 0,/*objobjargproc mp_ass_subscript */\ -};\ -EXPORT_THIS Dtool_PyTypedObject Dtool_##CLASS_NAME = {\ -{\ - PyObject_HEAD_INIT(NULL)\ - 0,\ - #MODULE_NAME "." #PUBLIC_NAME, /*type name with module */ \ - sizeof(Dtool_PyInstDef), /* tp_basicsize*/ \ - 0, /*tp_itemsize*/ \ - &Dtool_Deallocate_General, /*Dtool_Deallocate_##CLASS_NAME,*/ /*tp_dealloc*/\ - 0, /*tp_print*/\ - 0, /*tp_getattr*/\ - 0, /*tp_setattr*/\ - 0, /*tp_compare*/\ - 0, /*tp_repr*/\ - &Dtool_PyNumberMethods_##CLASS_NAME, /*tp_as_number*/\ - 0, /*tp_as_sequence*/\ - &Dtool_PyMappingMethods_##CLASS_NAME, /*tp_as_mapping*/\ - 0, /*tp_hash */\ +};\ +EXPORT_THIS Dtool_PyTypedObject Dtool_##CLASS_NAME = {\ +{\ + PyObject_HEAD_INIT(NULL)\ + 0,\ + #MODULE_NAME "." #PUBLIC_NAME, /*type name with module */ \ + sizeof(Dtool_PyInstDef), /* tp_basicsize*/ \ + 0, /*tp_itemsize*/ \ + &Dtool_Deallocate_General, /*Dtool_Deallocate_##CLASS_NAME,*/ /*tp_dealloc*/\ + 0, /*tp_print*/\ + 0, /*tp_getattr*/\ + 0, /*tp_setattr*/\ + 0, /*tp_compare*/\ + 0, /*tp_repr*/\ + &Dtool_PyNumberMethods_##CLASS_NAME, /*tp_as_number*/\ + 0, /*tp_as_sequence*/\ + &Dtool_PyMappingMethods_##CLASS_NAME, /*tp_as_mapping*/\ + 0, /*tp_hash */\ 0, /* tp_call */\ 0, /* tp_str */\ PyObject_GenericGetAttr, /* tp_getattro */\ @@ -217,29 +217,29 @@ EXPORT_THIS Dtool_PyTypedObject Dtool_##CLASS_NAME = {\ Dtool_Init_##CLASS_NAME, /* tp_init */\ PyType_GenericAlloc, /* tp_alloc */\ Dtool_new_##CLASS_NAME, /* tp_new */\ - _PyObject_Del, /* tp_free */\ -},\ - #CLASS_NAME, \ - false,\ - Dtool_UpcastInterface_##CLASS_NAME, \ - Dtool_DowncastInterface_##CLASS_NAME, \ - Dtool_FreeInstance_##CLASS_NAME, \ - Dtool_PyModuleClassInit_##CLASS_NAME\ -}; - - -//////////////////////////////////////////////////////////////////////// -// The Fast Deallocator.. for Our instances.. -//////////////////////////////////////////////////////////////////////// -inline void Dtool_Deallocate_General(PyObject * self) -{ + _PyObject_Del, /* tp_free */\ +},\ + #CLASS_NAME, \ + false,\ + Dtool_UpcastInterface_##CLASS_NAME, \ + Dtool_DowncastInterface_##CLASS_NAME, \ + Dtool_FreeInstance_##CLASS_NAME, \ + Dtool_PyModuleClassInit_##CLASS_NAME\ +}; + + +//////////////////////////////////////////////////////////////////////// +// The Fast Deallocator.. for Our instances.. +//////////////////////////////////////////////////////////////////////// +inline void Dtool_Deallocate_General(PyObject * self) +{ ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_FreeInstance(self); self->ob_type->tp_free(self); -} -//////////////////////////////////////////////////////////////////////// -// More Macro(s) to Implement class functions.. Usally used if C++ needs type information -//////////////////////////////////////////////////////////////////////// -#define Define_Dtool_new(CLASS_NAME,CNAME)\ +} +//////////////////////////////////////////////////////////////////////// +// More Macro(s) to Implement class functions.. Usally used if C++ needs type information +//////////////////////////////////////////////////////////////////////// +#define Define_Dtool_new(CLASS_NAME,CNAME)\ PyObject *Dtool_new_##CLASS_NAME(PyTypeObject *type, PyObject *args, PyObject *kwds)\ {\ PyObject * self = type->tp_alloc(type, 0);\ @@ -249,398 +249,398 @@ PyObject *Dtool_new_##CLASS_NAME(PyTypeObject *type, PyObject *args, PyObject *k ((Dtool_PyInstDef *)self)->_My_Type = &Dtool_##CLASS_NAME;\ return self;\ }\ -//////////////////////////////////////////////////////////////////////// -/// Delete functions.. -//////////////////////////////////////////////////////////////////////// -#define Define_Dtool_FreeInstance_Private(CLASS_NAME,CNAME)\ -static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self)\ -{\ -}\ - -#define Define_Dtool_FreeInstance(CLASS_NAME,CNAME)\ -static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self)\ -{\ - if(((Dtool_PyInstDef *)self)->_ptr_to_object != NULL)\ - if(((Dtool_PyInstDef *)self)->_memory_rules)\ - {\ - delete ((CNAME *)((Dtool_PyInstDef *)self)->_ptr_to_object);\ - }\ -}\ - -#define Define_Dtool_FreeInstanceRef(CLASS_NAME,CNAME)\ -static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self)\ -{\ - if(((Dtool_PyInstDef *)self)->_ptr_to_object != NULL)\ - if(((Dtool_PyInstDef *)self)->_memory_rules)\ - {\ - unref_delete((CNAME *)((Dtool_PyInstDef *)self)->_ptr_to_object);\ - }\ -}\ - -//////////////////////////////////////////////////////////////////////// -/// Simple Recognition Functions.. -//////////////////////////////////////////////////////////////////////// -inline bool DtoolCanThisBeAPandaInstance(PyObject *self) -{ - // simple sanity check for the class type..size.. will stop basic foobars.. - if(self->ob_type->tp_basicsize >= sizeof(Dtool_PyInstDef)) - { - Dtool_PyInstDef * pyself = (Dtool_PyInstDef *) self; - if(pyself->_signiture == PY_PANDA_SIGNITURE) - return true; - } - return false; -} -//////////////////////////////////////////////////////////////////////// -// Function : DTOOL_Call_ExtractThisPointerForType -// -// These are the rapers that allow for down and upcast from type .. -// needed by the Dtool py interface.. Be very carefull if you muck with these -// as the generated code depends on how this is set up.. -//////////////////////////////////////////////////////////////////////// -inline void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject * classdef, void ** answer) -{ - if(DtoolCanThisBeAPandaInstance(self)) - *answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self,classdef); - else - answer = NULL; -}; - - -inline void * DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef) -{ - if(self != NULL) - { - if(DtoolCanThisBeAPandaInstance(self)) - return ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self,classdef); - else - PyErr_SetString(PyExc_TypeError, "Failed Dtool Type Check .."); - } - else - PyErr_SetString(PyExc_TypeError, "Self Is Null"); - - return NULL; -}; - -inline void * DTOOL_Call_GetPointerThis(PyObject *self) -{ - if(self != NULL) - { - if(DtoolCanThisBeAPandaInstance(self)) - { - Dtool_PyInstDef * pyself = (Dtool_PyInstDef *) self; - return pyself->_ptr_to_object; - } - } - - return NULL; -}; - -//////////////////////////////////////////////////////////////////////// -// Function : DTool_CreatePyInstanceTyped -// -// this function relies on the behavior of typed objects in the panda system. -// -//////////////////////////////////////////////////////////////////////// -inline PyObject * DTool_CreatePyInstanceTyped(void * local_this_in, Dtool_PyTypedObject & known_class_type, bool memory_rules, int RunTimeType) -{ - if(local_this_in == NULL ) - { - // Lets don't be stupid.. - PyErr_SetString(PyExc_TypeError, "C Function Return Null 'this'"); - return NULL; - } - ///////////////////////////////////////////////////// - // IF the calss is posibly a run time typed object - ///////////////////////////////////////////////////// - if(RunTimeType > 0) - { - ///////////////////////////////////////////////////// - // get best fit class... - ///////////////////////////////////////////////////// - Dtool_PyTypedObject * target_class = Dtool_RuntimeTypeDtoolType(RunTimeType); - if(target_class != NULL) - { - ///////////////////////////////////////////////////// - // cast to the type... - ////////////////////////////////////////////////////// - void * new_local_this = target_class->_Dtool_DowncastInterface(local_this_in,&known_class_type); - if(new_local_this != NULL) - { - ///////////////////////////////////////////// - // ask class to allocate a instance.. - ///////////////////////////////////////////// - Dtool_PyInstDef * self = (Dtool_PyInstDef *) target_class->As_PyTypeObject().tp_new(&target_class->As_PyTypeObject(), NULL,NULL); - if(self != NULL) - { +//////////////////////////////////////////////////////////////////////// +/// Delete functions.. +//////////////////////////////////////////////////////////////////////// +#define Define_Dtool_FreeInstance_Private(CLASS_NAME,CNAME)\ +static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self)\ +{\ +}\ + +#define Define_Dtool_FreeInstance(CLASS_NAME,CNAME)\ +static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self)\ +{\ + if(((Dtool_PyInstDef *)self)->_ptr_to_object != NULL)\ + if(((Dtool_PyInstDef *)self)->_memory_rules)\ + {\ + delete ((CNAME *)((Dtool_PyInstDef *)self)->_ptr_to_object);\ + }\ +}\ + +#define Define_Dtool_FreeInstanceRef(CLASS_NAME,CNAME)\ +static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self)\ +{\ + if(((Dtool_PyInstDef *)self)->_ptr_to_object != NULL)\ + if(((Dtool_PyInstDef *)self)->_memory_rules)\ + {\ + unref_delete((CNAME *)((Dtool_PyInstDef *)self)->_ptr_to_object);\ + }\ +}\ + +//////////////////////////////////////////////////////////////////////// +/// Simple Recognition Functions.. +//////////////////////////////////////////////////////////////////////// +inline bool DtoolCanThisBeAPandaInstance(PyObject *self) +{ + // simple sanity check for the class type..size.. will stop basic foobars.. + if(self->ob_type->tp_basicsize >= sizeof(Dtool_PyInstDef)) + { + Dtool_PyInstDef * pyself = (Dtool_PyInstDef *) self; + if(pyself->_signiture == PY_PANDA_SIGNITURE) + return true; + } + return false; +} +//////////////////////////////////////////////////////////////////////// +// Function : DTOOL_Call_ExtractThisPointerForType +// +// These are the rapers that allow for down and upcast from type .. +// needed by the Dtool py interface.. Be very carefull if you muck with these +// as the generated code depends on how this is set up.. +//////////////////////////////////////////////////////////////////////// +inline void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject * classdef, void ** answer) +{ + if(DtoolCanThisBeAPandaInstance(self)) + *answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self,classdef); + else + answer = NULL; +}; + + +inline void * DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef) +{ + if(self != NULL) + { + if(DtoolCanThisBeAPandaInstance(self)) + return ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self,classdef); + else + PyErr_SetString(PyExc_TypeError, "Failed Dtool Type Check .."); + } + else + PyErr_SetString(PyExc_TypeError, "Self Is Null"); + + return NULL; +}; + +inline void * DTOOL_Call_GetPointerThis(PyObject *self) +{ + if(self != NULL) + { + if(DtoolCanThisBeAPandaInstance(self)) + { + Dtool_PyInstDef * pyself = (Dtool_PyInstDef *) self; + return pyself->_ptr_to_object; + } + } + + return NULL; +}; + +//////////////////////////////////////////////////////////////////////// +// Function : DTool_CreatePyInstanceTyped +// +// this function relies on the behavior of typed objects in the panda system. +// +//////////////////////////////////////////////////////////////////////// +inline PyObject * DTool_CreatePyInstanceTyped(void * local_this_in, Dtool_PyTypedObject & known_class_type, bool memory_rules, int RunTimeType) +{ + if(local_this_in == NULL ) + { + // Lets don't be stupid.. + PyErr_SetString(PyExc_TypeError, "C Function Return Null 'this'"); + return NULL; + } + ///////////////////////////////////////////////////// + // IF the calss is posibly a run time typed object + ///////////////////////////////////////////////////// + if(RunTimeType > 0) + { + ///////////////////////////////////////////////////// + // get best fit class... + ///////////////////////////////////////////////////// + Dtool_PyTypedObject * target_class = Dtool_RuntimeTypeDtoolType(RunTimeType); + if(target_class != NULL) + { + ///////////////////////////////////////////////////// + // cast to the type... + ////////////////////////////////////////////////////// + void * new_local_this = target_class->_Dtool_DowncastInterface(local_this_in,&known_class_type); + if(new_local_this != NULL) + { + ///////////////////////////////////////////// + // ask class to allocate a instance.. + ///////////////////////////////////////////// + Dtool_PyInstDef * self = (Dtool_PyInstDef *) target_class->As_PyTypeObject().tp_new(&target_class->As_PyTypeObject(), NULL,NULL); + if(self != NULL) + { self->_ptr_to_object = new_local_this; self->_memory_rules = memory_rules; self->_signiture = PY_PANDA_SIGNITURE; - self->_My_Type = target_class; - return (PyObject *)self; - } - } - } - } - - ///////////////////////////////////////////////////// - // if we get this far .. just wrap the thing in the known type ?? - // better than aborting...I guess.... - ///////////////////////////////////////////////////// - Dtool_PyInstDef * self = (Dtool_PyInstDef *) known_class_type.As_PyTypeObject().tp_new(&known_class_type.As_PyTypeObject(), NULL,NULL); - if(self != NULL) - { + self->_My_Type = target_class; + return (PyObject *)self; + } + } + } + } + + ///////////////////////////////////////////////////// + // if we get this far .. just wrap the thing in the known type ?? + // better than aborting...I guess.... + ///////////////////////////////////////////////////// + Dtool_PyInstDef * self = (Dtool_PyInstDef *) known_class_type.As_PyTypeObject().tp_new(&known_class_type.As_PyTypeObject(), NULL,NULL); + if(self != NULL) + { self->_ptr_to_object = local_this_in; self->_memory_rules = memory_rules; self->_signiture = PY_PANDA_SIGNITURE; - self->_My_Type = &known_class_type; - } - return (PyObject *)self; -}; - -//////////////////////////////////////////////////////////////////////// -// DTool_CreatePyInstance .. wrapper function to finalize the existance of a general -// dtool py instance.. -//////////////////////////////////////////////////////////////////////// -inline PyObject * DTool_CreatePyInstance(void * local_this, Dtool_PyTypedObject & in_classdef, bool memory_rules) -{ - if(local_this == NULL) - { - PyErr_SetString(PyExc_TypeError, "C Function Return Null 'this' "); - return NULL; - } - - Dtool_PyTypedObject * classdef = &in_classdef; - Dtool_PyInstDef * self = (Dtool_PyInstDef *) classdef->As_PyTypeObject().tp_new(&classdef->As_PyTypeObject(), NULL,NULL); - if(self != NULL) - { + self->_My_Type = &known_class_type; + } + return (PyObject *)self; +}; + +//////////////////////////////////////////////////////////////////////// +// DTool_CreatePyInstance .. wrapper function to finalize the existance of a general +// dtool py instance.. +//////////////////////////////////////////////////////////////////////// +inline PyObject * DTool_CreatePyInstance(void * local_this, Dtool_PyTypedObject & in_classdef, bool memory_rules) +{ + if(local_this == NULL) + { + PyErr_SetString(PyExc_TypeError, "C Function Return Null 'this' "); + return NULL; + } + + Dtool_PyTypedObject * classdef = &in_classdef; + Dtool_PyInstDef * self = (Dtool_PyInstDef *) classdef->As_PyTypeObject().tp_new(&classdef->As_PyTypeObject(), NULL,NULL); + if(self != NULL) + { self->_ptr_to_object = local_this; self->_memory_rules = memory_rules; - self->_My_Type = classdef; - } - return (PyObject *)self; -}; -/////////////////////////////////////////////////////////////////////////////// -// Macro(s) class definition .. Used to allocate storage and -// init some values for a Dtool Py Type object. -///////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// + self->_My_Type = classdef; + } + return (PyObject *)self; +}; +/////////////////////////////////////////////////////////////////////////////// +// Macro(s) class definition .. Used to allocate storage and +// init some values for a Dtool Py Type object. +///////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// //struct Dtool_PyTypedObject Dtool_##CLASS_NAME; \ -#define Define_Module_Class_Internal(MODULE_NAME,CLASS_NAME,CNAME)\ +#define Define_Module_Class_Internal(MODULE_NAME,CLASS_NAME,CNAME)\ extern EXPORT_THIS Dtool_PyTypedObject Dtool_##CLASS_NAME; \ extern struct PyMethodDef Dtool_Methods_##CLASS_NAME[];\ int Dtool_Init_##CLASS_NAME(PyObject *self, PyObject *args, PyObject *kwds);\ PyObject * Dtool_new_##CLASS_NAME(PyTypeObject *type, PyObject *args, PyObject *kwds);\ -void * Dtool_UpcastInterface_##CLASS_NAME(PyObject *self, Dtool_PyTypedObject *requested_type);\ -void * Dtool_DowncastInterface_##CLASS_NAME(void *self, Dtool_PyTypedObject *requested_type);\ -void Dtool_PyModuleClassInit_##CLASS_NAME(PyObject *module); - -/////////////////////////////////////////////////////////////////////////////// -#define Define_Module_Class(MODULE_NAME,CLASS_NAME,CNAME,PUBLIC_NAME)\ -Define_Module_Class_Internal(MODULE_NAME,CLASS_NAME,CNAME)\ -Define_Dtool_new(CLASS_NAME,CNAME)\ -Define_Dtool_FreeInstance(CLASS_NAME,CNAME)\ -Define_Dtool_Class(MODULE_NAME,CLASS_NAME,PUBLIC_NAME) - -/////////////////////////////////////////////////////////////////////////////// -#define Define_Module_Class_Private(MODULE_NAME,CLASS_NAME,CNAME,PUBLIC_NAME)\ -Define_Module_Class_Internal(MODULE_NAME,CLASS_NAME,CNAME)\ -Define_Dtool_new(CLASS_NAME,CNAME)\ -Define_Dtool_FreeInstance_Private(CLASS_NAME,CNAME)\ -Define_Dtool_Class(MODULE_NAME,CLASS_NAME,PUBLIC_NAME) - -/////////////////////////////////////////////////////////////////////////////// -#define Define_Module_ClassRef_Private(MODULE_NAME,CLASS_NAME,CNAME,PUBLIC_NAME)\ -Define_Module_Class_Internal(MODULE_NAME,CLASS_NAME,CNAME)\ -Define_Dtool_new(CLASS_NAME,CNAME)\ -Define_Dtool_FreeInstance_Private(CLASS_NAME,CNAME)\ -Define_Dtool_Class(MODULE_NAME,CLASS_NAME,PUBLIC_NAME) - -/////////////////////////////////////////////////////////////////////////////// -#define Define_Module_ClassRef(MODULE_NAME,CLASS_NAME,CNAME,PUBLIC_NAME)\ -Define_Module_Class_Internal(MODULE_NAME,CLASS_NAME,CNAME)\ -Define_Dtool_new(CLASS_NAME,CNAME)\ -Define_Dtool_FreeInstanceRef(CLASS_NAME,CNAME)\ -Define_Dtool_Class(MODULE_NAME,CLASS_NAME,PUBLIC_NAME) - - -/////////////////////////////////////////////////////////////////////////////// -/// Th Finalizer for simple instances.. -/////////////////////////////////////////////////////////////////////////////// -inline int DTool_PyInit_Finalize(PyObject * self, void * This, Dtool_PyTypedObject *type, bool memory_rules) -{ - // lets put some code in here that checks to see the memory is properly configured.. - // prior to my call .. - - ((Dtool_PyInstDef *)self)->_My_Type = type; - ((Dtool_PyInstDef *)self)->_ptr_to_object = This; - ((Dtool_PyInstDef *)self)->_memory_rules = memory_rules; - return 0; -} - -/////////////////////////////////////////////////////////////////////////////// -/// A heler function to glu methed definition together .. that can not be done at -// code generation time becouse of multiple generation passes in interigate.. -// -/////////////////////////////////////////////////////////////////////////////// -typedef std::map MethodDefmap; - -inline void Dtool_Accum_MethDefs(PyMethodDef in[], MethodDefmap &themap) -{ - for(; in->ml_name != NULL; in++) - { - if(themap.find(in->ml_name) == themap.end()) - { - themap[in->ml_name] = in; - } - } -} - -/////////////////////////////////////////////////////////////////////////////// -// ** HACK ** allert.. -// -// Need to keep a runtime type dictionary ... that is forward declared of typed object. -// We rely on the fact that typed objects are uniquly defined by an integer. -// -/////////////////////////////////////////////////////////////////////////////// - -inline void RegisterRuntimeClass(Dtool_PyTypedObject * otype, int class_id) -{ - if(class_id > 0) - { - GetRunTimeDictionary()[class_id] = otype; - GetRunTimeTypeList().insert(class_id); - otype->_Dtool_IsRunTimeCapable = true; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -inline Dtool_PyTypedObject * Dtool_RuntimeTypeDtoolType(int type) -{ - RunTimeTypeDictionary::iterator di = GetRunTimeDictionary().find(type); - if(di != GetRunTimeDictionary().end()) - return di->second; - else - { - int type2 = get_best_parent_from_Set(type,GetRunTimeTypeList()); - di = GetRunTimeDictionary().find(type2); - if(di != GetRunTimeDictionary().end()) - return di->second; - } - return NULL; -}; -/////////////////////////////////////////////////////////////////////////////// -//// We need a way to runtime merge compile units into a python "Module" .. this is done with the -/// fallowing structors and code.. along with the support of interigate_module -/////////////////////////////////////////////////////////////////////////////// -struct LibrayDef -{ - typedef void ( *ConstantFunction )(PyObject *); - - PyMethodDef * _methods; - ConstantFunction _constants; -}; -/////////////////////////////////////////////////////////////////////////////// -inline void Dtool_PyModuleInitHelper( LibrayDef *defs[], char * modulename) -{ - // the module level function inits.... - MethodDefmap functions; - for(int xx = 0; defs[xx] != NULL; xx++) - Dtool_Accum_MethDefs(defs[xx]->_methods,functions); - - PyMethodDef *newdef = new PyMethodDef[functions.size()+1]; - MethodDefmap::iterator mi; - int offset = 0; - for(mi = functions.begin(); mi != functions.end(); mi++, offset++) - newdef[offset] = *mi->second; - newdef[offset].ml_doc = NULL; - newdef[offset].ml_name = NULL; - newdef[offset].ml_meth = NULL; - newdef[offset].ml_flags = 0; - - PyObject * module = Py_InitModule(modulename,newdef); - - if(module == NULL) - { - PyErr_SetString(PyExc_TypeError, "Py_InitModule Returned NULL ???"); - return; - } - - - // the constant inits... enums, classes ... - for(int y = 0; defs[y] != NULL; y++) - defs[y]->_constants(module); - - PyModule_AddIntConstant(module,"Dtool_PyNavtiveInterface",1); -} -/////////////////////////////////////////////////////////////////////////////// -/// HACK.... Be carefull -// -// Dtool_BarrowThisRefrence -// This function can be used to grab the "THIS" pointer from an object and use it -// Required to support fom historical inharatence in the for of "is this instance of".. -// -/////////////////////////////////////////////////////////////////////////////// -inline PyObject * Dtool_BarrowThisRefrence(PyObject * self, PyObject * args ) -{ - PyObject *from_in = NULL; - PyObject *to_in = NULL; - if(PyArg_ParseTuple(args, "OO", &to_in, &from_in)) - { - - if(DtoolCanThisBeAPandaInstance(from_in) && DtoolCanThisBeAPandaInstance(to_in)) - { - Dtool_PyInstDef * from = (Dtool_PyInstDef *) from_in; - Dtool_PyInstDef * to = (Dtool_PyInstDef *) to_in; - if(from->_My_Type == to->_My_Type) - { - to->_memory_rules = false; - to->_ptr_to_object = from->_ptr_to_object; - return Py_BuildValue(""); - } - PyErr_SetString(PyExc_TypeError, "Must Be Same Type??"); - } - else - PyErr_SetString(PyExc_TypeError, "One of thesee does not appear to be DTOOL Instance ??"); - } - return (PyObject *) NULL; -} -////////////////////////////////////////////////////////////////////////////////////////////// -// We do expose a dictionay for dtool classes .. this should be removed at some point.. -////////////////////////////////////////////////////////////////////////////////////////////// -inline PyObject * Dtool_AddToDictionary(PyObject * self1, PyObject * args ) -{ - - PyObject * self; - PyObject * subject; - PyObject * key; - if(PyArg_ParseTuple(args, "OSO", &self, &key, &subject)) - { - PyObject * dict = ((PyTypeObject *)self)->tp_dict; - if(dict == NULL && !PyDict_Check(dict)) - PyErr_SetString(PyExc_TypeError, "No dictionary On Object"); - else - PyDict_SetItem(dict,key,subject); - - } - if(PyErr_Occurred()) - return (PyObject *)NULL; - return Py_BuildValue(""); - -} -/////////////////////////////////////////////////////////////////////////////////// -/* -inline long DTool_HashKey(PyObject * inst) -{ - long outcome = (long)inst; +void * Dtool_UpcastInterface_##CLASS_NAME(PyObject *self, Dtool_PyTypedObject *requested_type);\ +void * Dtool_DowncastInterface_##CLASS_NAME(void *self, Dtool_PyTypedObject *requested_type);\ +void Dtool_PyModuleClassInit_##CLASS_NAME(PyObject *module); + +/////////////////////////////////////////////////////////////////////////////// +#define Define_Module_Class(MODULE_NAME,CLASS_NAME,CNAME,PUBLIC_NAME)\ +Define_Module_Class_Internal(MODULE_NAME,CLASS_NAME,CNAME)\ +Define_Dtool_new(CLASS_NAME,CNAME)\ +Define_Dtool_FreeInstance(CLASS_NAME,CNAME)\ +Define_Dtool_Class(MODULE_NAME,CLASS_NAME,PUBLIC_NAME) + +/////////////////////////////////////////////////////////////////////////////// +#define Define_Module_Class_Private(MODULE_NAME,CLASS_NAME,CNAME,PUBLIC_NAME)\ +Define_Module_Class_Internal(MODULE_NAME,CLASS_NAME,CNAME)\ +Define_Dtool_new(CLASS_NAME,CNAME)\ +Define_Dtool_FreeInstance_Private(CLASS_NAME,CNAME)\ +Define_Dtool_Class(MODULE_NAME,CLASS_NAME,PUBLIC_NAME) + +/////////////////////////////////////////////////////////////////////////////// +#define Define_Module_ClassRef_Private(MODULE_NAME,CLASS_NAME,CNAME,PUBLIC_NAME)\ +Define_Module_Class_Internal(MODULE_NAME,CLASS_NAME,CNAME)\ +Define_Dtool_new(CLASS_NAME,CNAME)\ +Define_Dtool_FreeInstance_Private(CLASS_NAME,CNAME)\ +Define_Dtool_Class(MODULE_NAME,CLASS_NAME,PUBLIC_NAME) + +/////////////////////////////////////////////////////////////////////////////// +#define Define_Module_ClassRef(MODULE_NAME,CLASS_NAME,CNAME,PUBLIC_NAME)\ +Define_Module_Class_Internal(MODULE_NAME,CLASS_NAME,CNAME)\ +Define_Dtool_new(CLASS_NAME,CNAME)\ +Define_Dtool_FreeInstanceRef(CLASS_NAME,CNAME)\ +Define_Dtool_Class(MODULE_NAME,CLASS_NAME,PUBLIC_NAME) + + +/////////////////////////////////////////////////////////////////////////////// +/// Th Finalizer for simple instances.. +/////////////////////////////////////////////////////////////////////////////// +inline int DTool_PyInit_Finalize(PyObject * self, void * This, Dtool_PyTypedObject *type, bool memory_rules) +{ + // lets put some code in here that checks to see the memory is properly configured.. + // prior to my call .. + + ((Dtool_PyInstDef *)self)->_My_Type = type; + ((Dtool_PyInstDef *)self)->_ptr_to_object = This; + ((Dtool_PyInstDef *)self)->_memory_rules = memory_rules; + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +/// A heler function to glu methed definition together .. that can not be done at +// code generation time becouse of multiple generation passes in interigate.. +// +/////////////////////////////////////////////////////////////////////////////// +typedef std::map MethodDefmap; + +inline void Dtool_Accum_MethDefs(PyMethodDef in[], MethodDefmap &themap) +{ + for(; in->ml_name != NULL; in++) + { + if(themap.find(in->ml_name) == themap.end()) + { + themap[in->ml_name] = in; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// ** HACK ** allert.. +// +// Need to keep a runtime type dictionary ... that is forward declared of typed object. +// We rely on the fact that typed objects are uniquly defined by an integer. +// +/////////////////////////////////////////////////////////////////////////////// + +inline void RegisterRuntimeClass(Dtool_PyTypedObject * otype, int class_id) +{ + if(class_id > 0) + { + GetRunTimeDictionary()[class_id] = otype; + GetRunTimeTypeList().insert(class_id); + otype->_Dtool_IsRunTimeCapable = true; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +inline Dtool_PyTypedObject * Dtool_RuntimeTypeDtoolType(int type) +{ + RunTimeTypeDictionary::iterator di = GetRunTimeDictionary().find(type); + if(di != GetRunTimeDictionary().end()) + return di->second; + else + { + int type2 = get_best_parent_from_Set(type,GetRunTimeTypeList()); + di = GetRunTimeDictionary().find(type2); + if(di != GetRunTimeDictionary().end()) + return di->second; + } + return NULL; +}; +/////////////////////////////////////////////////////////////////////////////// +//// We need a way to runtime merge compile units into a python "Module" .. this is done with the +/// fallowing structors and code.. along with the support of interigate_module +/////////////////////////////////////////////////////////////////////////////// +struct LibrayDef +{ + typedef void ( *ConstantFunction )(PyObject *); + + PyMethodDef * _methods; + ConstantFunction _constants; +}; +/////////////////////////////////////////////////////////////////////////////// +inline void Dtool_PyModuleInitHelper( LibrayDef *defs[], char * modulename) +{ + // the module level function inits.... + MethodDefmap functions; + for(int xx = 0; defs[xx] != NULL; xx++) + Dtool_Accum_MethDefs(defs[xx]->_methods,functions); + + PyMethodDef *newdef = new PyMethodDef[functions.size()+1]; + MethodDefmap::iterator mi; + int offset = 0; + for(mi = functions.begin(); mi != functions.end(); mi++, offset++) + newdef[offset] = *mi->second; + newdef[offset].ml_doc = NULL; + newdef[offset].ml_name = NULL; + newdef[offset].ml_meth = NULL; + newdef[offset].ml_flags = 0; + + PyObject * module = Py_InitModule(modulename,newdef); + + if(module == NULL) + { + PyErr_SetString(PyExc_TypeError, "Py_InitModule Returned NULL ???"); + return; + } + + + // the constant inits... enums, classes ... + for(int y = 0; defs[y] != NULL; y++) + defs[y]->_constants(module); + + PyModule_AddIntConstant(module,"Dtool_PyNavtiveInterface",1); +} +/////////////////////////////////////////////////////////////////////////////// +/// HACK.... Be carefull +// +// Dtool_BarrowThisRefrence +// This function can be used to grab the "THIS" pointer from an object and use it +// Required to support fom historical inharatence in the for of "is this instance of".. +// +/////////////////////////////////////////////////////////////////////////////// +inline PyObject * Dtool_BarrowThisRefrence(PyObject * self, PyObject * args ) +{ + PyObject *from_in = NULL; + PyObject *to_in = NULL; + if(PyArg_ParseTuple(args, "OO", &to_in, &from_in)) + { + + if(DtoolCanThisBeAPandaInstance(from_in) && DtoolCanThisBeAPandaInstance(to_in)) + { + Dtool_PyInstDef * from = (Dtool_PyInstDef *) from_in; + Dtool_PyInstDef * to = (Dtool_PyInstDef *) to_in; + if(from->_My_Type == to->_My_Type) + { + to->_memory_rules = false; + to->_ptr_to_object = from->_ptr_to_object; + return Py_BuildValue(""); + } + PyErr_SetString(PyExc_TypeError, "Must Be Same Type??"); + } + else + PyErr_SetString(PyExc_TypeError, "One of thesee does not appear to be DTOOL Instance ??"); + } + return (PyObject *) NULL; +} +////////////////////////////////////////////////////////////////////////////////////////////// +// We do expose a dictionay for dtool classes .. this should be removed at some point.. +////////////////////////////////////////////////////////////////////////////////////////////// +inline PyObject * Dtool_AddToDictionary(PyObject * self1, PyObject * args ) +{ + + PyObject * self; + PyObject * subject; + PyObject * key; + if(PyArg_ParseTuple(args, "OSO", &self, &key, &subject)) + { + PyObject * dict = ((PyTypeObject *)self)->tp_dict; + if(dict == NULL && !PyDict_Check(dict)) + PyErr_SetString(PyExc_TypeError, "No dictionary On Object"); + else + PyDict_SetItem(dict,key,subject); + + } + if(PyErr_Occurred()) + return (PyObject *)NULL; + return Py_BuildValue(""); + +} +/////////////////////////////////////////////////////////////////////////////////// +/* +inline long DTool_HashKey(PyObject * inst) +{ + long outcome = (long)inst; PyObject * func = PyObject_GetAttrString(inst, "__hash__"); if (func == NULL) { - if(DtoolCanThisBeAPandaInstance(inst)) - if(((Dtool_PyInstDef *)inst)->_ptr_to_object != NULL) - outcome = (long)((Dtool_PyInstDef *)inst)->_ptr_to_object; + if(DtoolCanThisBeAPandaInstance(inst)) + if(((Dtool_PyInstDef *)inst)->_ptr_to_object != NULL) + outcome = (long)((Dtool_PyInstDef *)inst)->_ptr_to_object; } else { @@ -662,10 +662,10 @@ inline long DTool_HashKey(PyObject * inst) } Py_DECREF(res); } - return outcome; -} -*/ - + return outcome; +} +*/ + /* Compare v to w. Return -1 if v < w or exception (PyErr_Occurred() true in latter case). 0 if v == w. @@ -673,7 +673,7 @@ inline long DTool_HashKey(PyObject * inst) XXX The docs (C API manual) say the return value is undefined in case XXX of error. */ - + inline int DTOOL_PyObject_Compare_old(PyObject *v1, PyObject *v2) { // if we are related.. @@ -726,11 +726,11 @@ inline int DTOOL_PyObject_Compare_old(PyObject *v1, PyObject *v2) if(v1 > v2) return 1; return 0; -} - - - - +} + + + + inline int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2) { // First try compare to function.. @@ -781,96 +781,96 @@ inline int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2) if(v1 > v2) return 1; return 0; -} - - -#ifdef PANDA_LIBRARY_NAME_libexpress -#define DTOOL_CREATE_SUPPER_BASE -#endif - -#ifdef DTOOL_CREATE_SUPPER_BASE - -class EmptyClass -{ -}; -Define_Module_Class_Private(pandaexpress,DTOOL_SUPPER_BASE,EmptyClass,DTOOL_SUPPER_BASE111); - -static PyObject * GetSupperBase(PyObject * self) -{ - Py_INCREF(&(Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject())); // order is important .. this is used for static functions - return (PyObject *)&Dtool_DTOOL_SUPPER_BASE; -}; - - -PyMethodDef Dtool_Methods_DTOOL_SUPPER_BASE[]= { - { "DtoolGetSupperBase",(PyCFunction ) &GetSupperBase, METH_NOARGS,"Will Return SUPPERbase Class"}, - { NULL, NULL } -}; - +} + + +#ifdef PANDA_LIBRARY_NAME_libexpress +#define DTOOL_CREATE_SUPPER_BASE +#endif + +#ifdef DTOOL_CREATE_SUPPER_BASE + +class EmptyClass +{ +}; +Define_Module_Class_Private(pandaexpress,DTOOL_SUPPER_BASE,EmptyClass,DTOOL_SUPPER_BASE111); + +static PyObject * GetSupperBase(PyObject * self) +{ + Py_INCREF(&(Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject())); // order is important .. this is used for static functions + return (PyObject *)&Dtool_DTOOL_SUPPER_BASE; +}; + + +PyMethodDef Dtool_Methods_DTOOL_SUPPER_BASE[]= { + { "DtoolGetSupperBase",(PyCFunction ) &GetSupperBase, METH_NOARGS,"Will Return SUPPERbase Class"}, + { NULL, NULL } +}; + static long DTool_HashKey_Methods_DTOOL_SUPPER_BASE(PyObject * self) { - void * local_this =DTOOL_Call_GetPointerThis(self); - if(local_this == NULL) - { - return -1; + void * local_this =DTOOL_Call_GetPointerThis(self); + if(local_this == NULL) + { + return -1; }; return (long)local_this; }; - - -inline void Dtool_PyModuleClassInit_DTOOL_SUPPER_BASE(PyObject *module) -{ - static bool initdone = false; - if(!initdone) - { - - initdone = true; - Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_dict = PyDict_New(); - PyDict_SetItemString(Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_dict,"DtoolClassDict",Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_dict); - + + +inline void Dtool_PyModuleClassInit_DTOOL_SUPPER_BASE(PyObject *module) +{ + static bool initdone = false; + if(!initdone) + { + + initdone = true; + Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_dict = PyDict_New(); + PyDict_SetItemString(Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_dict,"DtoolClassDict",Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_dict); + // __hash__ Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_hash = &DTool_HashKey_Methods_DTOOL_SUPPER_BASE; Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_compare = &DTOOL_PyObject_Compare; - - if(PyType_Ready(&Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject()) < 0) - { - PyErr_SetString(PyExc_TypeError, "PyType_Ready(Dtool_DTOOL_SUPPER_BASE)"); - return; - } - Py_INCREF(&Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject()); - - PyDict_SetItemString(Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_dict,"DtoolGetSupperBase",PyCFunction_New(&Dtool_Methods_DTOOL_SUPPER_BASE[0],&Dtool_DTOOL_SUPPER_BASE.As_PyObject())); - - } - - if(module != NULL) - { - Py_INCREF(&Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject()); - PyModule_AddObject(module, "DTOOL_SUPPER_BASE",(PyObject *)&Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject()); - } -} - -inline void * Dtool_DowncastInterface_DTOOL_SUPPER_BASE(void *from_this, Dtool_PyTypedObject *from_type) -{ - return (void *) NULL; -} - -inline void * Dtool_UpcastInterface_DTOOL_SUPPER_BASE(PyObject *self, Dtool_PyTypedObject *requested_type) -{ - return NULL; -} - -int Dtool_Init_DTOOL_SUPPER_BASE(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyErr_SetString(PyExc_TypeError, "Error Can Not Init SUPPER BASE"); - return -1; -} - - -#else -IMPORT_THIS struct Dtool_PyTypedObject Dtool_DTOOL_SUPPER_BASE; -#endif // DTOOL_CREATE_SUPPER_BASE - - -#endif // PY_PANDA_H_ - + + if(PyType_Ready(&Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject()) < 0) + { + PyErr_SetString(PyExc_TypeError, "PyType_Ready(Dtool_DTOOL_SUPPER_BASE)"); + return; + } + Py_INCREF(&Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject()); + + PyDict_SetItemString(Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_dict,"DtoolGetSupperBase",PyCFunction_New(&Dtool_Methods_DTOOL_SUPPER_BASE[0],&Dtool_DTOOL_SUPPER_BASE.As_PyObject())); + + } + + if(module != NULL) + { + Py_INCREF(&Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject()); + PyModule_AddObject(module, "DTOOL_SUPPER_BASE",(PyObject *)&Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject()); + } +} + +inline void * Dtool_DowncastInterface_DTOOL_SUPPER_BASE(void *from_this, Dtool_PyTypedObject *from_type) +{ + return (void *) NULL; +} + +inline void * Dtool_UpcastInterface_DTOOL_SUPPER_BASE(PyObject *self, Dtool_PyTypedObject *requested_type) +{ + return NULL; +} + +int Dtool_Init_DTOOL_SUPPER_BASE(PyObject *self, PyObject *args, PyObject *kwds) +{ + PyErr_SetString(PyExc_TypeError, "Error Can Not Init SUPPER BASE"); + return -1; +} + + +#else +IMPORT_THIS struct Dtool_PyTypedObject Dtool_DTOOL_SUPPER_BASE; +#endif // DTOOL_CREATE_SUPPER_BASE + + +#endif // PY_PANDA_H_ + diff --git a/dtool/src/pystub/pystub.cxx b/dtool/src/pystub/pystub.cxx index 1f453d1174..372186aab7 100644 --- a/dtool/src/pystub/pystub.cxx +++ b/dtool/src/pystub/pystub.cxx @@ -83,16 +83,16 @@ extern "C" { EXPCL_DTOOLCONFIG int PyObject_GenericGetAttr(...); EXPCL_DTOOLCONFIG int PyArg_Parse(...); EXPCL_DTOOLCONFIG int PyDict_Type(...); - EXPCL_DTOOLCONFIG int PyArg_ParseTupleAndKeywords(...); - EXPCL_DTOOLCONFIG int PyDict_Size(...); + EXPCL_DTOOLCONFIG int PyArg_ParseTupleAndKeywords(...); + EXPCL_DTOOLCONFIG int PyDict_Size(...); EXPCL_DTOOLCONFIG extern void *PyExc_AssertionError; EXPCL_DTOOLCONFIG extern void *_Py_NoneStruct; }; -int PyArg_ParseTupleAndKeywords(...) { return 0; } -int PyDict_Size(...){ return 0; } +int PyArg_ParseTupleAndKeywords(...) { return 0; } +int PyDict_Size(...){ return 0; } int PyArg_ParseTuple(...) { return 0; } int PyErr_Occurred(...) { return 0; } int PyErr_SetString(...) { return 0; }