diff --git a/dtool/src/interrogate/Sources.pp b/dtool/src/interrogate/Sources.pp index 12d68e5a36..5c0506dd94 100644 --- a/dtool/src/interrogate/Sources.pp +++ b/dtool/src/interrogate/Sources.pp @@ -16,6 +16,7 @@ interfaceMakerC.h \ interfaceMakerPython.h interfaceMakerPythonObj.h \ interfaceMakerPythonSimple.h \ + interfaceMakerPythonNative.h \ interrogate.h interrogateBuilder.h parameterRemap.I \ parameterRemap.h parameterRemapBasicStringRefToString.h \ parameterRemapBasicStringToString.h \ @@ -37,6 +38,7 @@ interfaceMakerC.cxx \ interfaceMakerPython.cxx interfaceMakerPythonObj.cxx \ interfaceMakerPythonSimple.cxx \ + interfaceMakerPythonNative.cxx \ interrogate.cxx interrogateBuilder.cxx parameterRemap.cxx \ parameterRemapBasicStringRefToString.cxx \ parameterRemapBasicStringToString.cxx \ diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index 6e4e803e54..efd804fe09 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/dtool/src/interrogate/functionRemap.cxx @@ -18,7 +18,7 @@ #include "functionRemap.h" #include "typeManager.h" -#include "interrogate.h" +#include "interrogate.h" #include "parameterRemap.h" #include "parameterRemapThis.h" #include "interfaceMaker.h" @@ -32,6 +32,8 @@ #include "interrogateType.h" #include "notify.h" +extern bool inside_python_native; + //////////////////////////////////////////////////////////////////// // Function: FunctionRemap::Constructor // Access: Public @@ -43,6 +45,7 @@ FunctionRemap(const InterrogateType &itype, const InterrogateFunction &ifunc, InterfaceMaker *interface) { _return_type = (ParameterRemap *)NULL; _void_return = true; + _ForcedVoidReturn = false; _has_this = false; _first_true_parameter = 0; _num_default_parameters = num_default_parameters; @@ -98,8 +101,7 @@ get_parameter_name(int n) const { // are returning a value, or the empty string if we // return nothing. //////////////////////////////////////////////////////////////////// -string FunctionRemap:: -call_function(ostream &out, int indent_level, bool convert_result, +string FunctionRemap::call_function(ostream &out, int indent_level, bool convert_result, const string &container, const vector_string &pexprs) const { string return_expr; @@ -114,8 +116,10 @@ call_function(ostream &out, int indent_level, bool convert_result, InterfaceMaker::indent(out, indent_level) << "unref_delete(" << container << ");\n"; } else { - InterfaceMaker::indent(out, indent_level) - << "delete " << container << ";\n"; + if(inside_python_native) + InterfaceMaker::indent(out, indent_level) << "Dtool_Py_Delete(self); \n"; + else + InterfaceMaker::indent(out, indent_level) << " delete " << container << ";\n"; } } else if (_type == T_typecast_method) { @@ -342,7 +346,8 @@ get_call_str(const string &container, const vector_string &pexprs) const { call << _expression; } - } else if (_type == T_setter) { + } else if (_type == T_setter) + { if (!container.empty()) { call << "(" << container << ")->" << _expression; } else { @@ -353,6 +358,7 @@ get_call_str(const string &container, const vector_string &pexprs) const { _parameters[0]._remap->pass_parameter(call, get_parameter_expr(_first_true_parameter, pexprs)); } else { + if (_type == T_constructor) { // Constructors are called differently. call << _cpptype->get_local_name(&parser); @@ -547,6 +553,7 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface) { // If our return type isn't something we can deal with, treat the // function as if it returns NULL. _void_return = true; + _ForcedVoidReturn = true; CPPType *void_type = TypeManager::get_void_type(); _return_type = interface->remap_parameter(_cpptype, void_type); assert(_return_type != (ParameterRemap *)NULL); diff --git a/dtool/src/interrogate/functionRemap.h b/dtool/src/interrogate/functionRemap.h index 2effdba98d..59bc4dc121 100644 --- a/dtool/src/interrogate/functionRemap.h +++ b/dtool/src/interrogate/functionRemap.h @@ -87,6 +87,7 @@ public: Parameters _parameters; ParameterRemap *_return_type; bool _void_return; + bool _ForcedVoidReturn; bool _has_this; int _first_true_parameter; int _num_default_parameters; @@ -109,16 +110,10 @@ public: CPPFunctionType *_ftype; bool _is_valid; - private: - string - get_call_str(const string &container, const vector_string &pexprs) const; - - string - get_parameter_expr(int n, const vector_string &pexprs) const; - - bool - setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface); + string get_call_str(const string &container, const vector_string &pexprs) const; + string get_parameter_expr(int n, const vector_string &pexprs) const; + bool setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface); }; #endif diff --git a/dtool/src/interrogate/interfaceMaker.cxx b/dtool/src/interrogate/interfaceMaker.cxx index 2e3dcfbb55..42df5a7d41 100644 --- a/dtool/src/interrogate/interfaceMaker.cxx +++ b/dtool/src/interrogate/interfaceMaker.cxx @@ -41,8 +41,9 @@ #include "cppParameterList.h" #include "notify.h" -static InterrogateType dummy_type; + InterrogateType dummy_type; + //////////////////////////////////////////////////////////////////// // Function: InterfaceMaker::Function::Constructor // Access: Public @@ -58,7 +59,7 @@ Function(const string &name, { _has_this = false; } - + //////////////////////////////////////////////////////////////////// // Function: InterfaceMaker::Function::Destructor // Access: Public @@ -135,45 +136,83 @@ void InterfaceMaker:: generate_wrappers() { InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + // We use a while loop rather than a simple for loop, because we // might increase the number of types recursively during the // traversal. int ti = 0; - while (ti < idb->get_num_all_types()) { - TypeIndex type_index = idb->get_all_type(ti); - record_object(type_index); + while (ti < idb->get_num_all_types()) + { + TypeIndex type_index = idb->get_all_type(ti); + 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)); + } + } + + ++ti; +// printf(" New Type %d\n",ti); + } + + int gi = 0; + while( gi = idb->get_num_global_elements()) + { + printf(" Global Type = %d",gi); + TypeIndex type_index = idb->get_global_element(gi); + record_object(type_index); + } int num_functions = idb->get_num_global_functions(); - for (int fi = 0; fi < num_functions; fi++) { + for (int fi = 0; fi < num_functions; fi++) + { FunctionIndex func_index = idb->get_global_function(fi); record_function(dummy_type, func_index); } + + int num_manifests = idb->get_num_global_manifests(); - for (int mi = 0; mi < num_manifests; mi++) { + for (int mi = 0; mi < num_manifests; mi++) + { ManifestIndex manifest_index = idb->get_global_manifest(mi); const InterrogateManifest &iman = idb->get_manifest(manifest_index); - if (iman.has_getter()) { + if (iman.has_getter()) + { FunctionIndex func_index = iman.get_getter(); record_function(dummy_type, func_index); } + printf(" Manafests %d\n",mi); } + + int num_elements = idb->get_num_global_elements(); - for (int ei = 0; ei < num_elements; ei++) { + for (int ei = 0; ei < num_elements; ei++) + { + printf(" Element %d\n",ei); + ElementIndex element_index = idb->get_global_element(ei); const InterrogateElement &ielement = idb->get_element(element_index); - if (ielement.has_getter()) { + if (ielement.has_getter()) + { FunctionIndex func_index = ielement.get_getter(); record_function(dummy_type, func_index); } - if (ielement.has_setter()) { + if (ielement.has_setter()) + { FunctionIndex func_index = ielement.get_setter(); record_function(dummy_type, func_index); } } + } //////////////////////////////////////////////////////////////////// @@ -195,7 +234,7 @@ write_includes(ostream &) { // write_functions(). //////////////////////////////////////////////////////////////////// void InterfaceMaker:: -write_prototypes(ostream &out) { +write_prototypes(ostream &out,ostream *out_h) { _function_writers.write_prototypes(out); } @@ -217,7 +256,7 @@ write_functions(ostream &out) { // support a module file. //////////////////////////////////////////////////////////////////// void InterfaceMaker:: -write_module(ostream &, InterrogateModuleDef *) { +write_module(ostream &, ostream *out_h,InterrogateModuleDef *) { } @@ -256,7 +295,8 @@ remap_parameter(CPPType *struct_type, CPPType *param_type) { if (manage_reference_counts) { if (TypeManager::is_pointer_to_base(param_type) || - TypeManager::is_const_ref_to_pointer_to_base(param_type)) { + TypeManager::is_const_ref_to_pointer_to_base(param_type)) + { CPPType *pt_type = TypeManager::unwrap_reference(param_type); // Don't convert PointerTo<>'s to pointers for methods of the @@ -370,15 +410,18 @@ make_function_remap(const InterrogateType &itype, CPPInstance *cppfunc, int num_default_parameters) { FunctionRemap *remap = new FunctionRemap(itype, ifunc, cppfunc, num_default_parameters, this); - if (remap->_is_valid) { - if (separate_overloading()) { + if (remap->_is_valid) + { + if (separate_overloading()) + { hash_function_signature(remap); remap->_unique_name = get_unique_prefix() + _def->library_hash_name + remap->_hash; remap->_wrapper_name = get_wrapper_prefix() + _def->library_hash_name + remap->_hash; remap->_reported_name = remap->_wrapper_name; - if (true_wrapper_names) { + if (true_wrapper_names) + { remap->_reported_name = InterrogateBuilder::clean_identifier(remap->_cppfunc->get_local_name(&parser)); } @@ -454,17 +497,21 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) { Function *func = new Function(wrapper_name, itype, ifunc); _functions.push_back(func); + +// printf(" Function Name = %s\n",ifunc.get_name().c_str()); + // Now get all the valid FunctionRemaps for the function. - if (ifunc._instances != (InterrogateFunction::Instances *)NULL) { + if (ifunc._instances != (InterrogateFunction::Instances *)NULL) + { InterrogateFunction::Instances::const_iterator ii; - for (ii = ifunc._instances->begin(); - ii != ifunc._instances->end(); - ++ii) { + for (ii = ifunc._instances->begin();ii != ifunc._instances->end();++ii) + { CPPInstance *cppfunc = (*ii).second; CPPFunctionType *ftype = cppfunc->_type->as_function_type(); int max_default_parameters = 0; - if (separate_overloading()) { + if (separate_overloading()) + { // Count up the number of default parameters this function might // take. CPPParameterList *parameters = ftype->_parameters; @@ -556,16 +603,18 @@ record_object(TypeIndex type_index) { Function *function; - int num_constructors = itype.number_of_constructors(); - for (int ci = 0; ci < num_constructors; ci++) { - function = record_function(itype, itype.get_constructor(ci)); - object->_constructors.push_back(function); - } + int num_constructors = itype.number_of_constructors(); + for (int ci = 0; ci < num_constructors; ci++) + { + function = record_function(itype, itype.get_constructor(ci)); + object->_constructors.push_back(function); + } - if (itype.has_destructor() && !itype.destructor_is_inherited()) { - function = record_function(itype, itype.get_destructor()); - object->_destructor = function; - } + if (itype.has_destructor() && !itype.destructor_is_inherited()) + { + function = record_function(itype, itype.get_destructor()); + object->_destructor = function; + } int num_methods = itype.number_of_methods(); int mi; @@ -581,11 +630,14 @@ record_object(TypeIndex type_index) { } int num_derivations = itype.number_of_derivations(); - for (int di = 0; di < num_derivations; di++) { - if (itype.derivation_has_upcast(di)) { + for (int di = 0; di < num_derivations; di++) + { + if (itype.derivation_has_upcast(di)) + { record_function(itype, itype.derivation_get_upcast(di)); } - if (itype.derivation_has_downcast(di)) { + if (itype.derivation_has_downcast(di)) + { // Downcasts are methods of the base class, not the child class. TypeIndex base_type_index = itype.get_derivation(di); const InterrogateType &base_type = idb->get_type(base_type_index); @@ -594,21 +646,25 @@ record_object(TypeIndex type_index) { } int num_elements = itype.number_of_elements(); - for (int ei = 0; ei < num_elements; ei++) { + for (int ei = 0; ei < num_elements; ei++) + { ElementIndex element_index = itype.get_element(ei); const InterrogateElement &ielement = idb->get_element(element_index); - if (ielement.has_getter()) { + if (ielement.has_getter()) + { FunctionIndex func_index = ielement.get_getter(); record_function(itype, func_index); } - if (ielement.has_setter()) { + if (ielement.has_setter()) + { FunctionIndex func_index = ielement.get_setter(); record_function(itype, func_index); } } int num_nested = itype.number_of_nested_types(); - for (int ni = 0; ni < num_nested; ni++) { + for (int ni = 0; ni < num_nested; ni++) + { TypeIndex nested_index = itype.get_nested_type(ni); record_object(nested_index); } @@ -796,3 +852,4 @@ write_spam_message(ostream &out, FunctionRemap *remap) const { out << "\\n\";\n" " }\n"; } + diff --git a/dtool/src/interrogate/interfaceMaker.h b/dtool/src/interrogate/interfaceMaker.h index ec3a063c5d..80c4b8ce44 100644 --- a/dtool/src/interrogate/interfaceMaker.h +++ b/dtool/src/interrogate/interfaceMaker.h @@ -56,13 +56,13 @@ public: virtual void generate_wrappers(); virtual void write_includes(ostream &out); - virtual void write_prototypes(ostream &out); + virtual void write_prototypes(ostream &out, ostream *out_h); virtual void write_functions(ostream &out); + virtual void write_module_support(ostream &out,ostream *out_h,InterrogateModuleDef *moduledefdef) {}; - virtual void write_module(ostream &out, InterrogateModuleDef *def); + virtual void write_module(ostream &out, ostream *out_h,InterrogateModuleDef *def); - virtual ParameterRemap * - remap_parameter(CPPType *struct_type, CPPType *param_type); + virtual ParameterRemap * remap_parameter(CPPType *struct_type, CPPType *param_type); virtual bool synthesize_this_parameter(); virtual bool separate_overloading(); @@ -71,7 +71,7 @@ public: static ostream &indent(ostream &out, int indent_level); -protected: +public: class Function { public: Function(const string &name, @@ -126,8 +126,7 @@ protected: record_function_wrapper(InterrogateFunction &ifunc, FunctionWrapperIndex wrapper_index); - Object * - record_object(TypeIndex type_index); + virtual Object * record_object(TypeIndex type_index); void hash_function_signature(FunctionRemap *remap); diff --git a/dtool/src/interrogate/interfaceMakerC.cxx b/dtool/src/interrogate/interfaceMakerC.cxx index dff98b9787..1a0c41c0b5 100644 --- a/dtool/src/interrogate/interfaceMakerC.cxx +++ b/dtool/src/interrogate/interfaceMakerC.cxx @@ -15,7 +15,7 @@ // panda3d-general@lists.sourceforge.net . // //////////////////////////////////////////////////////////////////// - + #include "interfaceMakerC.h" #include "interrogateBuilder.h" #include "interrogate.h" @@ -56,7 +56,7 @@ InterfaceMakerC:: // write_functions(). //////////////////////////////////////////////////////////////////// void InterfaceMakerC:: -write_prototypes(ostream &out) { +write_prototypes(ostream &out,ostream *out_h) { Functions::iterator fi; for (fi = _functions.begin(); fi != _functions.end(); ++fi) { Function *func = (*fi); @@ -64,7 +64,7 @@ write_prototypes(ostream &out) { } out << "\n"; - InterfaceMaker::write_prototypes(out); + InterfaceMaker::write_prototypes(out,out_h); } //////////////////////////////////////////////////////////////////// diff --git a/dtool/src/interrogate/interfaceMakerC.h b/dtool/src/interrogate/interfaceMakerC.h index f4793688e3..2d7095fcf7 100644 --- a/dtool/src/interrogate/interfaceMakerC.h +++ b/dtool/src/interrogate/interfaceMakerC.h @@ -37,7 +37,7 @@ public: InterfaceMakerC(InterrogateModuleDef *def); virtual ~InterfaceMakerC(); - virtual void write_prototypes(ostream &out); + virtual void write_prototypes(ostream &out,ostream *out_h); virtual void write_functions(ostream &out); virtual bool synthesize_this_parameter(); diff --git a/dtool/src/interrogate/interfaceMakerPython.cxx b/dtool/src/interrogate/interfaceMakerPython.cxx index 0e01318eb1..9400e0990a 100644 --- a/dtool/src/interrogate/interfaceMakerPython.cxx +++ b/dtool/src/interrogate/interfaceMakerPython.cxx @@ -47,7 +47,11 @@ write_includes(ostream &out) { << " #include \"Python/Python.h\"\n" << "#else\n" << " #include \"Python.h\"\n" - << "#endif\n\n"; + << "#endif\n" + << "#ifdef HAVE_LONG_LONG\n" + << "#undef HAVE_LONG_LONG\n" + << "#endif \n"; + } //////////////////////////////////////////////////////////////////// diff --git a/dtool/src/interrogate/interfaceMakerPython.h b/dtool/src/interrogate/interfaceMakerPython.h index 60c929b4e1..b60f6caa3a 100644 --- a/dtool/src/interrogate/interfaceMakerPython.h +++ b/dtool/src/interrogate/interfaceMakerPython.h @@ -40,7 +40,7 @@ public: virtual void write_includes(ostream &out); protected: - void test_assert(ostream &out, int indent_level) const; + virtual void test_assert(ostream &out, int indent_level) const; }; #endif diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx new file mode 100755 index 0000000000..719e30cd0c --- /dev/null +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -0,0 +1,2874 @@ +// Filename: interfaceMakerPythonNative.cxx +//////////////////////////////////////////////////////////////////// +// +// 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 "interfaceMakerPythonNative.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" +#include "cppPointerType.h" +#include "cppTypeDeclaration.h" +#include "cppStructType.h" +#include "vector" +#include "cppParameterList.h" +#include "algorithm" + +#include +#include + + +extern bool inside_python_native; +extern InterrogateType dummy_type; +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.... +///////////////////////////////////////////////////////// +struct RenameSet +{ + char * _from; + char * _to; + int function_type; +}; +/////////////////////////////////////////////////////////////////////////////////////// +RenameSet methodRenameDictionary[] = { + "operator==" , "eq", 0, + "operator!=" , "ne", 0, + "operator<<" , "__lshift__", 0, + "operator>>" , "__rshift__", 0, + "operator<" , "lessThan", 0, + "operator>" , "greaterThan", 0, + "operator<=" , "lessThanOrEqual", 0, + "operator>=" , "greaterThanOrEqual", 0, + "operator=" , "assign", 0, + "operator()" , "__call__", 0, + "operator[]" , "__getitem__", 0, + "operator++" , "increment", 0, + "operator--" , "decrement", 0, + "operator^" , "__xor__", 0, + "operator%" , "__mod__", 0, + "operator!" , "logicalNot", 0, + "operator~" , "bitwiseNot", 0, + "operator&" , "__and__", 0, + "operator&&" , "logicalAnd", 0, + "operator|" , "__or__", 0, + "operator||" , "logicalOr", 0, + "operator+" , "__add__", 0, + "operator-" , "__sub__", 0, + "operator*" , "__mul__", 0, + "operator/" , "__div__", 0, + "operator+=" , "__iadd__", 0, + "operator-=" , "__isub__", 0, + "operator*=" , "__imul__", 0, + "operator/=" , "__idiv__", 0, + "operator," , "concatenate", 0, + "operator|=" , "__ior__", 0, + "operator&=" , "__iand__", 0, + "operator^=" , "__ixor__", 0, + "operator~=" , "bitwiseNotEqual", 0, + "operator->" , "dereference", 0, + "operator<<=" , "__ilshift__", 0, + "operator>>=" , "__irshift__", 0, + "print" , "Cprint", 0, + "CInterval.setT" , "_priv__cSetT", 0, + NULL,NULL,-1 + }; +/////////////////////////////////////////////////////////////////////////////////////// +RenameSet classRenameDictionary[] = { + "Loader" , "PandaLoader",0, + "String" , "CString",0, + "LMatrix4f" , "Mat4",0, + "LMatrix3f" , "Mat3",0, + "LVecBase4f" , "VBase4",0, + "LVector4f" , "Vec4",0, + "LPoint4f" , "Point4",0, + "LVecBase3f" , "VBase3",0, + "LVector3f" , "Vec3",0, + "LPoint3f" , "Point3",0, + "LVecBase2f" , "VBase2",0, + "LVector2f" , "Vec2",0, + "LPoint2f" , "Point2",0, + "LQuaternionf" , "Quat",0, + "LMatrix4d" , "Mat4D",0, + "LMatrix3d" , "Mat3D",0, + "LVecBase4d" , "VBase4D",0, + "LVector4d" , "Vec4D",0, + "LPoint4d" , "Point4D",0, + "LVecBase3d" , "VBase3D",0, + "LVector3d" , "Vec3D",0, + "LPoint3d" , "Point3D",0, + "LVecBase2d" , "VBase2D",0, + "LVector2d" , "Vec2D",0, + "LPoint2d" , "Point2D",0, + "LQuaterniond" , "QuatD",0, + "Plane" , "PlaneBase",0, + "Planef" , "Plane",0, + "Planed" , "PlaneD",0, + "Frustum" , "FrustumBase",0, + "Frustumf" , "Frustum",0, + "Frustumd" , "FrustumD",0, + NULL,NULL,-1 + }; + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +char * pythonKeywords[] = { + "and", + "del", + "for", + "is", + "raise", + "assert", + "elif", + "from", + "lambda", + "return", + "break", + "else", + "global", + "not", + "try", + "class", + "except", + "if", + "or", + "while", + "continue", + "exec", + "import", + "pass", + "def", + "finally", + "in", + "print", + NULL}; +/////////////////////////////////////////////////////////////////////////////////////// +std::string checkKeyword(std::string & cppName) +{ + for(int x = 0; pythonKeywords[x] != NULL; x++) + { + if(cppName == pythonKeywords[x]) + { + return std::string("_")+cppName; + } + } + return cppName; +} +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +std::string classNameFromCppName(const std::string &cppName) +{ + //# initialize to empty string + std::string className = ""; + //# These are the characters we want to strip out of the name + const std::string badChars("!@#$%^&*()<>,.-=+~{}? "); + int nextCap = 0; + int firstChar = 1; + for(std::string::const_iterator chr = cppName.begin(); chr != cppName.end(); chr++) + { + if (badChars.find(*chr) != std::string::npos) + { + } + else if (*chr == '_') + { + nextCap = 1; + } + else if (nextCap || firstChar) + { + className += toupper(*chr); + nextCap = 0; + firstChar = 0; + } + else + { + className += * chr; + } + } + for(int x = 0; classRenameDictionary[x]._from != NULL; x++) + { + if(className == classRenameDictionary[x]._from) + className = classRenameDictionary[x]._to; + } + + if (className.empty()) + { + std::string text = "** ERROR ** Renaming class: " + cppName + " to empty string"; + printf("%s",text.c_str()); + } + + + //# FFIConstants.notify.debug('Renaming class: ' + cppName + ' to: ' + className) + //# Note we do not have to check for keywords because class name are capitalized + return className; +} +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +std::string nonClassNameFromCppName(const std::string &cppName_in) +{ + std::string className = classNameFromCppName(cppName_in); + //# Make the first character lowercase + std::string newName; + int pass = 0; + for(std::string::const_iterator chr = className.begin(); chr != className.end(); chr++) + { + if(pass == 0) + newName += toupper(*chr); + else + newName += tolower(*chr); + pass++; + } + //# Mangle names that happen to be python keywords so they are not anymore + //newName = checkKeyword(newName) + return newName; +} +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +std::string methodNameFromCppName(std::string cppName, const std::string &className) +{ + std::string methodName; + std::string badChars(" "); + int nextCap = 0; + for(std::string::const_iterator chr = cppName.begin(); chr != cppName.end(); chr++) + { + if (badChars.find(*chr) != std::string::npos) + { + } + else if (*chr == '_') + { + nextCap = 1; + } + else if (nextCap) + { + methodName += toupper(*chr); + nextCap = 0; + } + else + { + methodName += *chr; + } + } + + std::string LookUpName = methodName; + for(int x = 0; classRenameDictionary[x]._from != NULL; x++) + { + if(methodName == methodRenameDictionary[x]._from || (cppName == methodRenameDictionary[x]._from && methodRenameDictionary[x].function_type != 0) ) + { + methodName = methodRenameDictionary[x]._to; + } + } + + if(className.size() > 0) + { + LookUpName = className + '.' + methodName; + for(int x = 0; classRenameDictionary[x]._from != NULL; x++) + { + if(methodName == methodRenameDictionary[x]._from) + methodName = methodRenameDictionary[x]._to; + } + } + + +// # Mangle names that happen to be python keywords so they are not anymore + methodName = checkKeyword(methodName); + return methodName; +} +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + +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; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::GetValideChildClasses( std::map< std::string ,CastDetails > &answer, CPPStructType * inclass, const std::string &up_cast_seed, bool downcastposible) +{ + if(inclass == NULL) + return; + + CPPStructType::Derivation::const_iterator bi; + for (bi = inclass->_derivation.begin(); + bi != inclass->_derivation.end(); + ++bi) + { + + const CPPStructType::Base &base = (*bi); +// if (base._vis <= V_public) + // downcastposible = false; + CPPStructType *base_type = TypeManager::resolve_type(base._base)->as_struct_type(); + if(base_type != NULL) + { + std::string scoped_name = base_type->get_fully_scoped_name(); + + if(answer.find(scoped_name) == answer.end()) + { + answer[scoped_name]._can_downcast = downcastposible; + answer[scoped_name]._to_class_name = scoped_name; + answer[scoped_name]._structType = base_type; + + if(base._is_virtual) + answer[scoped_name]._can_downcast = false; + + std::string local_up_cast("( "); + local_up_cast += scoped_name + " *)"+ up_cast_seed +""; + answer[scoped_name]._up_cast_string = local_up_cast; + answer[scoped_name]._is_legal_py_class = isCppTypeLegal(base_type); + } + else + { + answer[scoped_name]._can_downcast = false; + } + + GetValideChildClasses(answer,base_type, answer[scoped_name]._up_cast_string,answer[scoped_name]._can_downcast); + } + } +} +/////////////////////////////////////////////////////////////////////////////// +// Function : WriteCreateInstance +// +/////////////////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::WriteCreateInstance(ostream &out, int indent_level, std::string &return_expr, std::string &ows_memory_flag, const std::string &class_name, CPPType *ctype) +{ + indent(out, indent_level)<<"if("<< return_expr<< " == NULL)\n"; + indent(out, indent_level)<<"{\n"; + indent(out, indent_level)<<" Py_INCREF(Py_None);\n"; + indent(out, indent_level)<<" return Py_None;\n"; + indent(out, indent_level)<<"}\n"; + + if(IsPandaTypedObject(ctype->as_struct_type())) + { + std::string typestr = "((TypedObject *)" + return_expr + ")->get_type_index()"; + + indent(out, indent_level)<<"return DTool_CreatePyInstanceTyped((void *)" << return_expr <<"," << CLASS_PREFEX << make_safe_name(class_name) << ","<< ows_memory_flag<<","<_itype.is_global() && isFunctionLegal(func)) + write_prototype_for(out_code, func); + } + + Objects::iterator oi; + for (oi = _objects.begin(); oi != _objects.end(); ++oi) + { + Object *object = (*oi).second; + if(object->_itype.is_class() ||object->_itype.is_struct()) + { + if(isCppTypeLegal(object->_itype._cpptype)) + { + if(isExportThisRun(object->_itype._cpptype)) + { + write_prototypes_class(out_code,out_h,object); + } + else + //write_prototypes_class_external(out_code,object); + _external_imports.insert(make_safe_name(object->_itype.get_scoped_name())); + } + } + } + + out_code << "//********************************************************************\n"; + out_code << "//*** prototypes for .. Extrernal Objects \n"; + out_code << "//********************************************************************\n"; + + for(std::set< std::string >::iterator ii = _external_imports.begin(); ii != _external_imports.end(); ii++) + out_code << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" <<*ii <<";\n"; + + + inside_python_native = false; +} +///////////////////////////////////////////////////////////////////////////////////////////// +// Function : write_prototypes_class_external +// +// Description : Output enough enformation to a declartion of a externally +// generated dtool type object +///////////////////////////////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::write_prototypes_class_external(ostream &out, Object * obj) +{ + std::string class_name = make_safe_name(obj->_itype.get_scoped_name()); + std::string c_class_name = obj->_itype.get_true_name(); + + + out << "//********************************************************************\n"; + out << "//*** prototypes for external.. " << class_name <<"\n"; + out << "//********************************************************************\n"; + + out << "typedef "<< c_class_name <<" "<< class_name <<"_localtype;\n"; + out << "Define_Module_Class_Forward("<< _def->module_name << ", "<< class_name << "," << class_name <<"_localtype,"<< classNameFromCppName(c_class_name) << ");\n"; + +} +///////////////////////////////////////// //////////////////////////////////////////////////// +// Function : write_prototypes_class +// +///////////////////////////////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::write_prototypes_class(ostream &out_code,ostream *out_h, Object * obj) +{ + std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); + Functions::iterator fi; + + out_code << "//********************************************************************\n"; + out_code << "//*** prototypes for .. " << ClassName <<"\n"; + out_code << "//********************************************************************\n"; + + for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) + { + Function *func = (*fi); + write_prototype_for(out_code, func); + } + + for (fi = obj->_constructors.begin(); fi != obj->_constructors.end(); ++fi) + { + Function *func = (*fi); + std::string fname = "int Dtool_Init_"+ClassName+"(PyObject *self, PyObject *args, PyObject *kwds)"; + write_prototype_for_name(out_code, func,fname); + + } + write_ClasseDeclarations(out_code,out_h,obj); +} + +//////////////////////////////////////////////////////////////////// +// Function: InterfaceMakerPythonNative::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 InterfaceMakerPythonNative::write_functions(ostream &out) +{ + inside_python_native = true; + + out << "//********************************************************************\n"; + out << "//*** Functions for .. Global \n" ; + out << "//********************************************************************\n"; + Functions::iterator fi; + for (fi = _functions.begin(); fi != _functions.end(); ++fi) + { + Function *func = (*fi); + if(!func->_itype.is_global() && isFunctionLegal(func)) + write_function_for_top(out, func,""); + } + + Objects::iterator oi; + for (oi = _objects.begin(); oi != _objects.end(); ++oi) + { + Object *object = (*oi).second; + if(object->_itype.is_class() ||object->_itype.is_struct()) + { + if(isCppTypeLegal(object->_itype._cpptype)) + if(isExportThisRun(object->_itype._cpptype)) + write_ClasseDetails(out,object); + } + } + +// Objects::iterator oi; + for (oi = _objects.begin(); oi != _objects.end(); ++oi) + { + Object *object = (*oi).second; + if(!object->_itype.get_outer_class()) + { + if(object->_itype.is_class() ||object->_itype.is_struct()) + if(isCppTypeLegal(object->_itype._cpptype)) + if(isExportThisRun(object->_itype._cpptype)) + write_module_class(out,object); + } + } + inside_python_native = true; + +} +//////////////////////////////////////////////////////////// +// Function : write_ClasseDetails +//////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::write_ClasseDetails(ostream &out, Object * obj) +{ + Functions::iterator fi; + + //std::string cClassName = obj->_itype.get_scoped_name(); + std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); + std::string cClassName = obj->_itype.get_true_name(); + + out << "//********************************************************************\n"; + out << "//*** Functions for .. "<< cClassName <<" \n" ; + out << "//********************************************************************\n"; + + for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) + { + Function *func = (*fi); + if(isFunctionLegal(func)) + { + ostringstream GetThis; + GetThis << " "<_constructors.size() == 0) + { + std::string fname = "int Dtool_Init_"+ClassName+"(PyObject *self, PyObject *args, PyObject *kwds)"; + out << fname << "\n"; + out << "{\n"; + out << " PyErr_SetString(PyExc_TypeError, \"Error Can Not Init Constant Class (" << cClassName << ")\");\n"; + out << " return -1;\n" ; + out << "}\n"; + + } + else + { + for (fi = obj->_constructors.begin(); fi != obj->_constructors.end(); ++fi) + { + Function *func = (*fi); + std::string fname = "int Dtool_Init_"+ClassName+"(PyObject *self, PyObject *args, PyObject *kwds) "; + + write_function_for_name(out, func,fname,"",ClassName); + } + } + + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + + std::map< string ,CastDetails > details; + std::map< string ,CastDetails >::iterator di; + TypeIndex pp_type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(obj->_itype._cpptype)),false); + GetValideChildClasses(details,obj->_itype._cpptype->as_struct_type()); + for(di = details.begin(); di != details.end(); di++) + { + //InterrogateType ptype =idb->get_type(di->first); + if(di->second._is_legal_py_class && !isExportThisRun(di->second._structType)) + _external_imports.insert(make_safe_name(di->second._to_class_name)); + //out << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(di->second._to_class_name) <<";\n"; + } + + + + { // the Cast Converter + + out << "inline void * Dtool_UpcastInterface_"<< ClassName << "(PyObject *self, Dtool_PyTypedObject *requested_type)\n"; + out << "{\n"; + out << " Dtool_PyTypedObject *SelfType = ((Dtool_PyInstDef *)self)->_My_Type;\n"; + out << " if(SelfType != &Dtool_" << ClassName <<")\n"; + out << " {\n"; + out << " printf(\""<_My_Type->_name,requested_type->_name);fflush(NULL);\n";; + out << " return NULL;\n"; + out << " }\n"; + out << " \n"; + out << " "<_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 << " return NULL;\n"; + out << "}\n"; + + out << "inline void * Dtool_DowncastInterface_"<< ClassName << "(void *from_this, Dtool_PyTypedObject *from_type)\n"; + out << "{\n"; + out << " if(from_this == NULL || from_type == NULL)\n"; + out << " return NULL;\n"; + out << " if(from_type == &Dtool_" << ClassName<<")\n"; + out << " return from_this;\n"; + for(di = details.begin(); di != details.end(); di++) + { + 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 << " return ("<< cClassName << "*)other_this;\n"; + out << " }\n"; + } + } + out << " return (void *) NULL;\n"; + out << "}\n"; + + } + +} +//////////////////////////////////////////////////////////// +/// Function : write_ClasseDeclarations +// +// +//////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::write_ClasseDeclarations(ostream &out, ostream *out_h,Object * obj ) +{ + + const InterrogateType &itype = obj->_itype; + std::string class_name = make_safe_name(obj->_itype.get_scoped_name()); + std::string c_class_name = itype.get_true_name(); + std::string class_struct_name = std::string(CLASS_PREFEX) +class_name; + + out << "typedef "<< c_class_name <<" "<< class_name <<"_localtype;\n"; + if(obj->_constructors.size() >0) + { + if(TypeManager::is_reference_count(obj->_itype._cpptype)) + { + out << "Define_Module_ClassRef("<< _def->module_name<<"," << class_name << "," << class_name <<"_localtype,"<< classNameFromCppName(c_class_name) <<");\n"; + } + else + { + out << "Define_Module_Class("<<_def->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_h << "extern \"C\" " << EXPORT_IMPORT_PREFEX << " struct Dtool_PyTypedObject Dtool_" << class_name <<";\n"; +} +//////////////////////////////////////////////////////////////////// +// Function: InterfaceMakerPythonNative::write_module +// Access: Public, Virtual +// Description: Generates whatever additional code is required to +// support a module file. +//////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::write_sub_module(ostream &out, Object *obj) +{ + //Object * obj = _objects[_embeded_index] ; + std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); + out << "//********************************************************************\n"; + out << "//*** Module Init Updcall .." << obj->_itype.get_scoped_name() << "\n"; + out << "//********************************************************************\n"; + out << " Dtool_PyModuleClassInit_"<< ClassName <<"(module);\n"; +} +///////////////////////////////////////////////////////////////////////////// +// Function : write_module_support +///////////////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::write_module_support(ostream &out,ostream *out_h,InterrogateModuleDef *moduledefdef) +{ + out << "//********************************************************************\n"; + out << "//*** Module Object Linker .. \n"; + out << "//********************************************************************\n"; + + out << "static void BuildInstants(PyObject * module)\n"; + out << "{\n"; + Objects::iterator oi; + for (oi = _objects.begin(); oi != _objects.end(); ++oi) + { + 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) + { + 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"; + } + } + } + + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + int num_manifests = idb->get_num_global_manifests(); + for (int mi = 0; mi < num_manifests; mi++) + { + ManifestIndex manifest_index = idb->get_global_manifest(mi); + const InterrogateManifest &iman = idb->get_manifest(manifest_index); + if (iman.has_getter()) + { + FunctionIndex func_index = iman.get_getter(); + record_function(dummy_type, func_index); + } + if(iman.has_int_value()) + 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"; + + } + + + + for (oi = _objects.begin(); oi != _objects.end(); ++oi) + { + Object *object = (*oi).second; + if(!object->_itype.get_outer_class()) + { + if(object->_itype.is_class() ||object->_itype.is_struct()) + if(isCppTypeLegal(object->_itype._cpptype)) + if(isExportThisRun(object->_itype._cpptype)) + write_sub_module(out,object); + } + } + + + out << "}\n"; + + bool force_base_functions = true; + + out << "static PyMethodDef python_simple_funcs[] = {\n"; + Functions::iterator fi; + for (fi = _functions.begin(); fi != _functions.end(); ++fi) + { + Function *func = (*fi); + if(!func->_itype.is_global() && isFunctionLegal(func)) + { + { + out << " { \"" << methodNameFromCppName( func->_ifunc.get_name(),"") << "\", &" + << func->_name << ", METH_VARARGS ," << func->_name << "_comment},\n"; + } + } + } + + if(force_base_functions) + { + out << " //Support Function For Dtool_types ... for know in each module ??\n"; + out << " {\"Dtool_BarrowThisRefrence\", &Dtool_BarrowThisRefrence,METH_VARARGS,\"Used to barrow 'this' poiner ( to, from)\\n Assumes no ownership\"}, \n"; + out << " {\"Dtool_AddToDictionary\", &Dtool_AddToDictionary,METH_VARARGS,\"Used to Items Into a types (tp_dict)\"}, \n"; + } + + out << " { NULL, NULL ,NULL,NULL}\n" << "};\n\n"; + + out << "struct LibrayDef " << moduledefdef->library_name <<"_moddef = {python_simple_funcs,BuildInstants};\n"; + if(out_h != NULL) + *out_h << "extern struct LibrayDef " << moduledefdef->library_name <<"_moddef;\n"; +} +///////////////////////////////////////////////////////////////////////////// +///// Function : write_module +///////////////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::write_module(ostream &out,ostream *out_h, InterrogateModuleDef *moduledefdef) +{ + InterfaceMakerPython::write_module(out,out_h, moduledefdef); + Objects::iterator oi; + + out << "//********************************************************************\n"; + out << "//*** Py Init Code For .. GlobalScope\n" ; + out << "//********************************************************************\n"; + + out << "#ifdef _WIN32\n" + << "extern \"C\" __declspec(dllexport) void init" << moduledefdef->module_name << "();\n" + << "#else\n" + << "extern \"C\" void init" << moduledefdef->module_name << "();\n" + << "#endif\n\n"; + + out << "void init" << moduledefdef->module_name << "() {\n"; + out << " LibrayDef * refs[] = {&" << moduledefdef->library_name << "_moddef,NULL};\n"; + out << " Dtool_PyModuleInitHelper(refs,\"" << moduledefdef->module_name << "\");\n"; + out << "}\n\n"; +} +//////////////////////////////////////////////////////////////////// +/// Function : GetSlotedFunctinDef +// +// This function is used to define special behavior for class functions.. +// main use is to encode the slot pointer logic and function call +// 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"; + return true; + } + + if(thimputstring == "__sub__") + { + answer_location = "tp_as_number->nb_subtract"; + return true; + } + + if(thimputstring == "__mul__") + { + answer_location = "tp_as_number->nb_multiply"; + return true; + } + + if(thimputstring == "__div__") + { + answer_location = "tp_as_number->nb_divide"; + return true; + } + + if(thimputstring == "__mod__") + { + answer_location = "tp_as_number->nb_remainder"; + return true; + } + + if(thimputstring == "__lshift__") + { + answer_location = "tp_as_number->nb_lshift"; + return true; + } + + if(thimputstring == "__rshift__") + { + answer_location = "tp_as_number->nb_rshift"; + return true; + } + + + if(thimputstring == "__xor__") + { + answer_location = "tp_as_number->nb_xor"; + return true; + } + + + if(thimputstring == "__and__") + { + answer_location = "tp_as_number->nb_and"; + return true; + } + + if(thimputstring == "__or__") + { + answer_location = "tp_as_number->nb_or"; + return true; + } + + + if(thimputstring == "__iadd__") + { + answer_location = "tp_as_number->nb_inplace_add"; + return true; + } + + if(thimputstring == "__isub__") + { + answer_location = "tp_as_number->nb_inplace_subtract"; + return true; + } + + if(thimputstring == "__imul__") + { + answer_location = "tp_as_number->nb_inplace_multiply"; + return true; + } + + if(thimputstring == "__idiv__") + { + answer_location = "tp_as_number->nb_inplace_divide"; + return true; + } + + if(thimputstring == "__imod__") + { + answer_location = ".tp_as_number->nb_inplace_remainder"; + return true; + } + + + if(thimputstring == "__ilshift__") + { + answer_location = "tp_as_number->nb_inplace_lshift"; + return true; + } + + if(thimputstring == "__irshift__") + { + answer_location = "tp_as_number->nb_inplace_rshift"; + return true; + } + + if(thimputstring == "__iand__") + { + answer_location = "tp_as_number->nb_inplace_and"; + return true; + } + + if(thimputstring == "__ixor__") + { + answer_location = "tp_as_number->nb_inplace_xor"; + 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"; + return true; + } + + //Direct methods + if(thimputstring == "__call__") + { + answer_location = "tp_call"; + wraper_type = 1; + return true; + } + } + return false; +}; +///////////////////////////////////////////////////////////////////////////////////////////// +// Function :write_module_class +///////////////////////////////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::write_module_class(ostream &out, Object *obj) +{ + + bool has_local_hash = false; + bool has_local_repr = false; + bool has_local_str = false; + + { + int num_nested = obj->_itype.number_of_nested_types(); + for (int ni = 0; ni < num_nested; ni++) + { + TypeIndex nested_index = obj->_itype.get_nested_type(ni); + Object * nested_obj = _objects[nested_index]; + if(nested_obj->_itype.is_class() ||nested_obj->_itype.is_struct()) + { + write_module_class(out,nested_obj); + } + } + } + + bool is_runtime_typed = IsPandaTypedObject(obj->_itype._cpptype->as_struct_type()); + + + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + + std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); + std::string cClassName = obj->_itype.get_true_name(); + std::string export_calss_name = classNameFromCppName(obj->_itype.get_name()); + + Functions::iterator fi; + out << "//********************************************************************\n"; + out << "//*** Py Init Code For .. "<< ClassName <<" | " << export_calss_name <<"\n" ; + out << "//********************************************************************\n"; + out << "static PyMethodDef Dtool_Methods_"<< ClassName << "[]= {\n"; + + + + std::map static_functions; + std::map normal_Operator_functions; + std::map > wraped_Operator_functions; + // function Table + int x; + for (x = 0, fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi,x++) + { + Function *func = (*fi); + std::string temp0; + int temp1; + if(!GetSlotedFunctinDef( methodNameFromCppName( func->_ifunc.get_name(),export_calss_name),temp0,temp1)) + { + + out << " { \"" << methodNameFromCppName( func->_ifunc.get_name(),export_calss_name) << "\", &" + << func->_name << ", METH_VARARGS ," << func->_name << "_comment},\n"; + if(!isFunctionWithThis(func)) + static_functions[x] = func; + } + else + { + if(temp1 > 0) + { + wraped_Operator_functions[func] = std::pair< std::string, int>(temp0,temp1); + out << " { \"" << methodNameFromCppName( func->_ifunc.get_name(),export_calss_name) << "\", &" + << func->_name << ", METH_VARARGS ," << func->_name << "_comment},\n"; + if(!isFunctionWithThis(func)) + static_functions[x] = func; + + } + else + { + normal_Operator_functions[func] = temp0; + + out << " { \"" << methodNameFromCppName( func->_ifunc.get_name(),export_calss_name) << "\", &" + << func->_name << ", METH_VARARGS ," << func->_name << "_comment},\n"; + if(!isFunctionWithThis(func)) + static_functions[x] = func; + } + } + } + + + + out << " { NULL, NULL }\n" + << "};\n\n"; + + int num_derivations = obj->_itype.number_of_derivations(); + for (int di = 0; di < num_derivations; di++) + { + TypeIndex d_type_Index = obj->_itype.get_derivation(di); + if(!interrogate_type_is_unpublished(d_type_Index)) + { + const InterrogateType &d_itype = idb->get_type(d_type_Index); + if(isCppTypeLegal(d_itype._cpptype)) + { + if(!isExportThisRun(d_itype._cpptype)) + { + _external_imports.insert(make_safe_name(d_itype.get_scoped_name().c_str())); + + //out << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(d_itype.get_scoped_name().c_str()) <<";\n"; + } + } + } + } + + std::vector< std::string > bases; + for (int di = 0; di < num_derivations; di++) + { + TypeIndex d_type_Index = obj->_itype.get_derivation(di); + if(!interrogate_type_is_unpublished(d_type_Index)) + { + + const InterrogateType &d_itype = idb->get_type(d_type_Index); + if(isCppTypeLegal(d_itype._cpptype)) + { + bases.push_back(make_safe_name(d_itype.get_scoped_name().c_str())); + } + } + } + + + + + { + std::map >::iterator rfi; // wraped_Operator_functions; + for(rfi = wraped_Operator_functions.begin(); rfi != wraped_Operator_functions.end(); rfi++) + { + if(rfi->second.second == 1) + { + Function *func = rfi->first; + out << "//////////////////\n"; + out << "// Required TO Convert the calling Conventions.. \n"; + out << "// " <second.first <<" = "<< methodNameFromCppName( func->_ifunc.get_name(),export_calss_name) <<"\n"; + out << "//////////////////\n"; + out << "PyObject * " << func->_name << methodNameFromCppName( func->_ifunc.get_name(),export_calss_name) << "( PyObject * self, PyObject * args, PyObject *dict)\n"; + out << "{\n"; + out << " return "<< func->_name <<"(self,args);\n"; + out << "}\n\n"; + } + else if(rfi->second.second == 2) + { + Function *func = rfi->first; + out << "//////////////////\n"; + out << "// Required TO Convert the calling Conventions.. \n"; + out << "// " <second.first <<" = "<< methodNameFromCppName( func->_ifunc.get_name(),export_calss_name) <<"\n"; + out << "//////////////////\n"; + out << "PyObject * " << func->_name << methodNameFromCppName( func->_ifunc.get_name(),export_calss_name) << "( PyObject * self)\n"; + out << "{\n"; + out << " return "<< func->_name <<"(self,Py_None);\n"; + out << "}\n\n"; + } + } + + if(HasAGetKeyFunction(obj->_itype)) + { + out << "//////////////////\n"; + out << "// A LocalHash(GetKey) Function for this type"; + out << "// " <GetKey();\n"; + out << "}\n\n"; + has_local_hash = true; + } + else + { + if(bases.size() == 0) + { + out << "//////////////////\n"; + out << "// A LocalHash(This Pointer) Function for this type"; + out << "// " <_itype)) + { + out << "//////////////////\n"; + out << "// A __repr__ Function\n"; + out << "// " <output(os);\n"; + out << " return PyString_FromString(os.str().c_str());\n"; + out << " };\n"; + out << " return Py_BuildValue(\"\");\n"; + out << "}\n"; + has_local_repr = true; + } + + if(NeedsAStrFunction(obj->_itype)) + { + out << "//////////////////\n"; + out << "// A __str__ Function\n"; + out << "// " <write(os);\n"; + out << " return PyString_FromString(os.str().c_str());\n"; + out << " };\n"; + out << " return Py_BuildValue(\"\");\n"; + out << "}\n"; + has_local_str = true; + } + + + } + + + + + out << "void Dtool_PyModuleClassInit_" << ClassName << "(PyObject *module)\n"; + out << "{\n"; + out << " static bool initdone = false;\n"; + out << " if(!initdone)\n"; + out << " {\n"; + out << " initdone = true;\n"; +// out << " memset(Dtool_"<< ClassName << ".As_PyTypeObject().tp_as_number,0,sizeof(PyNumberMethods));\n"; +// out << " memset(Dtool_"<< ClassName << ".As_PyTypeObject().tp_as_mapping,0,sizeof(PyMappingMethods));\n"; +// out << " static Dtool_PyTypedObject *InheritsFrom[] = {"; + + + + + if(bases.size() > 0) + { + out << " // Dependent Objects \n"; + std::string format1= ""; + std::string format2= ""; + for(std::vector< std::string >::iterator bi = bases.begin(); bi != bases.end(); bi++) + { + format1 += "O"; + format2 += ",&Dtool_" + *bi + ".As_PyTypeObject()"; + out << " Dtool_"<< make_safe_name(*bi) << "._Dtool_ClassInit(NULL);\n"; + } + + out << " Dtool_"<::iterator sfi; + for(sfi= static_functions.begin(); sfi != static_functions.end(); sfi++) + { + out << " // Static Method " << methodNameFromCppName( sfi->second->_ifunc.get_name(),export_calss_name) << "\n"; + out << " PyDict_SetItemString(Dtool_" << ClassName << ".As_PyTypeObject().tp_dict,\"" ; + out << methodNameFromCppName( sfi->second->_ifunc.get_name(),export_calss_name) ; + out << "\",PyCFunction_New(&Dtool_Methods_"<< ClassName <<"[" << sfi->first << "],&Dtool_"<< ClassName<< ".As_PyObject()));\n"; + } + + + // the standard call functions + std::map::iterator ofi; + for(ofi = normal_Operator_functions.begin(); ofi != normal_Operator_functions.end(); ofi++) + { + Function *func = ofi->first; + out << " // " << ofi->second <<" = "<< methodNameFromCppName( func->_ifunc.get_name(),export_calss_name) <<"\n"; + out << " Dtool_" << ClassName <<".As_PyTypeObject()." << ofi->second <<" = &" << func->_name <<";\n"; + } + + + // wraped functions... + { + std::map >::iterator rfi; // wraped_Operator_functions; + for(rfi = wraped_Operator_functions.begin(); rfi != wraped_Operator_functions.end(); rfi++) + { + Function *func = rfi->first; + out << " // " << rfi->second.first <<" = "<< methodNameFromCppName( func->_ifunc.get_name(),export_calss_name) <<"\n"; + out << " Dtool_" << ClassName <<".As_PyTypeObject()." << rfi->second.first <<" = &" << func->_name << methodNameFromCppName( func->_ifunc.get_name(),export_calss_name)<<";\n"; + } + } + + // __hash__ + if(has_local_hash == true) + { + out << " // __hash__\n"; + out << " Dtool_" << ClassName <<".As_PyTypeObject().tp_hash = &DTool_HashKey_"<_itype.number_of_nested_types(); + for (int ni = 0; ni < num_nested; ni++) + { + TypeIndex nested_index = obj->_itype.get_nested_type(ni); + Object * nested_obj = _objects[nested_index]; + if(nested_obj->_itype.is_class() ||nested_obj->_itype.is_struct()) + { + std::string ClassName1 = make_safe_name(nested_obj->_itype.get_scoped_name()); + std::string ClassName2 = make_safe_name(nested_obj->_itype.get_name()); + out << " // Nested Object "<< ClassName1 << ";\n"; + out << " Dtool_" << ClassName1 << "._Dtool_ClassInit(NULL);\n"; + out << " PyDict_SetItemString(Dtool_" << ClassName << ".As_PyTypeObject().tp_dict,\"" << classNameFromCppName(ClassName2) <<"\",(PyObject *)&Dtool_" << ClassName1 << ".As_PyTypeObject());\n"; + } + else + { + 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"; + + } + } + } + + out << " PyType_Ready(&Dtool_"<< ClassName << ".As_PyTypeObject());\n"; + out << " PyDict_SetItemString(Dtool_"<_name+"(PyObject *self, PyObject *args)"; + + + write_prototype_for_name(out,func,fname); +} +//////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::write_prototype_for_name(ostream &out, InterfaceMaker::Function *func, const std::string &function_namename) +{ + 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 << function_namename <<";\n"; +// } +} + +//////////////////////////////////////////////////////////////////// +// Function: InterfaceMakerPythonNative::write_function_for +// Access: Private +// Description: Writes the definition for a function that will call +// the indicated C++ function or method. +//////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::write_function_for_top(ostream &out, InterfaceMaker::Function *func, const std::string &PreProcess) +{ + std::string fname = "PyObject *"+func->_name+"(PyObject *self, PyObject *args)"; + + + write_function_for_name(out,func,fname,PreProcess,""); +} +//////////////////////////////////////////////////////////////////// +/// Function : write_function_for_name +// +// Wrap a complete name override function for Py..... +//////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::write_function_for_name( + ostream &out1, + InterfaceMaker::Function *func, + const std::string &function_name, + const std::string &PreProcess, + const std::string &ClassName) +{ + ostringstream forward_decl; + ostringstream out; + + std::map > MapSets; + std::map >::iterator mii; + std::set::iterator sii; + + + Function::Remaps::const_iterator ri; + out1 << "/************************************\n" << " * Python type method wrapper for\n"; + for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) + { + FunctionRemap *remap = (*ri); + if(isRemapLegal(*remap)) + { + int parameter_size = remap->_parameters.size(); + if(remap->_has_this && remap->_type != FunctionRemap::T_constructor) + parameter_size --; + + MapSets[parameter_size].insert(remap); + out1 << " * "; + remap->write_orig_prototype(out1, 0); + out1 << "\n"; + } + else + { + out1 << " * Rejected Remap ["; + remap->write_orig_prototype(out1, 0); + out1 << "]\n"; + } + + } + out1 << " *************************************/\n"; + out << function_name << " {\n"; + if(isFunctionWithThis(func)) + out << PreProcess; + + + if(MapSets.empty()) + return; + + + std::string FunctionComment = func->_ifunc._comment; + if(FunctionComment.size() > 2) + FunctionComment += "\n"; + + + if(MapSets.size() > 1) + { + string expected_params; + std::string argString; + + for(mii = MapSets.begin(); mii != MapSets.end(); mii ++) + { + + if(MapSets.begin() != mii) + argString += ","; + char buffer[30]; + sprintf(buffer,"%d",mii->first); + argString += buffer; + } + + indent(out,4) << "int parameter_count = 1;\n"; + indent(out,4) << "if(PyTuple_Check(args))\n"; + indent(out,4) << " parameter_count = PyTuple_Size(args);\n" ; + indent(out,4) << "switch(parameter_count)\n"; + indent(out,4) << "{\n"; + bool constructor = false; + for(mii = MapSets.begin(); mii != MapSets.end(); mii ++) + { + indent(out,4) << "case(" << mii->first << "):\n"; + indent(out,8) << "{\n"; + + write_function_forset(out,func,mii->second,expected_params,8,forward_decl,ClassName + function_name); + if((*mii->second.begin())->_type == FunctionRemap::T_constructor) + constructor = true; + + + indent(out,8)<< "}\n"; + indent(out,8)<< "break;\n"; + } + + indent(out,4)<< "default:\n"; + indent(out,8)<< "{\n"; + //indent(out,12)<< "PyString_FromFormat(\"("<_ifunc.get_name(),"") <<") Wrong Number Of Arguments(%d) must be: " << argString <<"\",parameter_count);\n"; + indent(out,12)<< "PyErr_Format(PyExc_TypeError, \"("<_ifunc.get_name(),"") <<") Wrong Number Of Arguments(%d) must be: " << argString <<"\",parameter_count);\n"; + if (constructor) + indent(out,12) << "return -1;\n"; + else + indent(out,12) << "return (PyObject *) NULL; \n"; + + indent(out,8)<< "}\n"; + indent(out,8)<< "break;\n"; + indent(out,4)<< "}\n"; + + out << " if(!PyErr_Occurred()) // let error pass on \n"; + out << " PyErr_SetString(PyExc_TypeError, \"Arguments must match one of:\\n" << expected_params << " \"); \n"; + if (constructor) + indent(out,4) << "return -1;\n"; + else + indent(out,4) << "return (PyObject *) NULL; \n"; + + FunctionComment += expected_params; + } + else + { + string expected_params = ""; + bool constructor = false; + for(mii = MapSets.begin(); mii != MapSets.end(); mii ++) + { + write_function_forset(out,func,mii->second,expected_params,4,forward_decl,ClassName + function_name); + if((*mii->second.begin())->_type == FunctionRemap::T_constructor) + constructor = true; + } + + out << " if(!PyErr_Occurred())\n"; + out << " PyErr_SetString(PyExc_TypeError, \"Must Match :\\n" << expected_params << " \"); \n"; + if (constructor) + indent(out,4) << "return -1;\n"; + else + indent(out,4) << "return (PyObject *) NULL; \n"; + FunctionComment += expected_params; + } + + out << "}\n\n"; + + out << "#ifndef NDEBUG\n"; + out << "static char * " << func->_name << "_comment = \"" << make_safe_comment(FunctionComment) << " \";\n"; + out << "#else\n"; + out << "static char * " << func->_name << "_comment = \"" << "\";\n"; + out << "#endif\n"; + + out << "\n"; + + + out1 << forward_decl.str(); + out1 << out.str(); +} +//////////////////////////////////////////////////////// +// Function : GetParnetDepth +// +// Support Function used to Sort the name based overrides.. For know must be complex to simple +//////////////////////////////////////////////////////// +int GetParnetDepth(CPPType *type) +{ + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + int answer = 0; +// printf(" %s\n",type->get_local_name().c_str()); + + if (TypeManager::is_basic_string_char(type)) { + } else if (TypeManager::is_bool(type)) { + } else if (TypeManager::is_unsigned_longlong(type)) { + } else if (TypeManager::is_longlong(type)) { + } else if (TypeManager::is_integer(type)) { + } else if (TypeManager::is_float(type)) { + } else if (TypeManager::is_char_pointer(type)) { + } else if (TypeManager::is_pointer_to_PyObject(type)) { + } else if (TypeManager::is_pointer(type) ||TypeManager::is_reference(type) || TypeManager::is_struct(type) ) + { + answer ++; + int deepest = 0; + TypeIndex type_index = builder.get_type(TypeManager::unwrap(type),false); + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + const InterrogateType &itype = idb->get_type(type_index); + + if(itype.is_class() ||itype.is_struct()) + { + + int num_derivations = itype.number_of_derivations(); + for (int di = 0; di < num_derivations; di++) + { + TypeIndex d_type_Index = itype.get_derivation(di); + const InterrogateType &d_itype = idb->get_type(d_type_Index); + int this_one = GetParnetDepth(d_itype._cpptype); + if(this_one > deepest) + deepest = this_one; + } + } + answer += deepest; +// printf(" Class Name %s %d\n",itype.get_name().c_str(),answer); + } else + { + int yy = 0; + } + + +// printf(" Class Name %s %d\n",itype.get_name().c_str(),answer); + return answer; +} +//////////////////////////////////////////////////////// +// The Core sort function for remap calling orders.. +////////////////////////////////////////////////////////// +int RemapCompareLesss(FunctionRemap * in1 , FunctionRemap * in2) +{ + if(in1->_parameters.size() != in2->_parameters.size()) + return (in1->_parameters.size() > in2->_parameters.size()); + + int pcount = in1->_parameters.size(); + for(int x = 0; x< pcount; x++) + { + CPPType *orig_type1 = in1->_parameters[x]._remap->get_orig_type(); + CPPType *orig_type2 = in2->_parameters[x]._remap->get_orig_type(); + + int pd1 = GetParnetDepth(orig_type1); + int pd2 = GetParnetDepth(orig_type2); + if(pd1 != pd2) + return pd1> pd2; + } + + // ok maybe something to do with return strength.. + + return false; +} +////////////////////////////////////////////////////////// +// Convience for the sort behavior.. +/////////////////////////////////////////////////////////// +std::vector< FunctionRemap * > SortFunctionSet(std::set< FunctionRemap *> &remaps) +{ + std::vector< FunctionRemap * > out; + for(std::set< FunctionRemap *>::iterator ii = remaps.begin(); ii!= remaps.end(); ii++) + out.push_back(*ii); + + + std::sort(out.begin(), out.end(), RemapCompareLesss); + + return out; +} +/////////////////////////////////////////////////////////// +// Function : write_function_forset +// +// A set is defined as all rempas that have the same number of paramaters.. +/////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::write_function_forset(ostream &out, InterfaceMaker::Function *func, + std::set< FunctionRemap *> &remapsin, string &expected_params, int indent_level,ostream &forward_decl, const std::string &functionname) +{ + + if(remapsin.size() > 1) + { +// printf("---------------------------- Start Sort ----- %s , %s\n",func->_name.c_str(),functionname.c_str()); + std::vector remaps = SortFunctionSet(remapsin); + + std::vector::iterator sii; + for(sii = remaps.begin(); sii != remaps.end(); sii ++) + { + FunctionRemap *remap = (*sii); + if(isRemapLegal(*remap)) + { + + indent(out,indent_level)<< "{ // -2 " ; + remap->write_orig_prototype(out, 0); out << "\n" ; + + write_function_instance(out, func, remap,expected_params,indent_level,false,forward_decl,functionname); + + indent(out,indent_level+4)<< "PyErr_Clear(); \n"; + indent(out,indent_level)<< "}\n\n"; + } + } + } + else + { + std::set::iterator sii; + for(sii = remapsin.begin(); sii != remapsin.end(); sii ++) + { + FunctionRemap *remap = (*sii); + if(isRemapLegal(*remap)) + { + + indent(out,indent_level)<< "// 1-" ;remap->write_orig_prototype(out, 0); out << "\n" ; +// indent(out,indent_level)<< "do{\n"; + write_function_instance(out, func, remap,expected_params,indent_level,true,forward_decl,functionname); + // indent(out,indent_level)<< "}while(false);\n"; + } + } + } +} + + +//////////////////////////////////////////////////////////////////// +// Function: InterfaceMakerPythonNative::write_function_instance +// Access: Private +// Description: Writes out the particular function that handles a +// single instance of an overloaded function. +//////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::write_function_instance(ostream &out, InterfaceMaker::Function *func1, + FunctionRemap *remap, string &expected_params, int indent_level, bool errors_fatal, ostream &ForwardDeclrs, const std::string &functionnamestr) +{ + string format_specifiers; + string parameter_list; + string container; + vector_string pexprs; + string extra_convert; + string extra_param_check; + string extra_cleanup; + string pname_for_pyobject; + + bool isconstructor = false; + if (remap->_type == FunctionRemap::T_constructor ) + isconstructor = true; + + // 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, 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)) { + indent(out,indent_level+4)<< "char *" << param_name; + format_specifiers += "s"; + parameter_list += ", &" + param_name; + } + else + { + indent(out,indent_level+4) << "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)) { + indent(out,indent_level+4) << "PyObject *" << param_name; + format_specifiers += "O"; + parameter_list += ", &" + param_name; + pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)"; + expected_params += "bool"; + pname_for_pyobject += param_name; + + + } else if (TypeManager::is_unsigned_longlong(type)) { + indent(out,indent_level+4) << "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 += "unsigned long long"; + pname_for_pyobject += param_name; + + + } else if (TypeManager::is_longlong(type)) { + indent(out,indent_level+4) << "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 long"; + pname_for_pyobject += param_name; + + } else if (TypeManager::is_integer(type)) { + indent(out,indent_level+4) << "int " << param_name; + format_specifiers += "i"; + parameter_list += ", &" + param_name; + expected_params += "int"; + + } else if (TypeManager::is_float(type)) { + indent(out,indent_level+4) << "double " << param_name; + format_specifiers += "d"; + parameter_list += ", &" + param_name; + expected_params += "float "; + + } else if (TypeManager::is_char_pointer(type)) { + indent(out,indent_level+4) << "char *" << param_name; + format_specifiers += "s"; + parameter_list += ", &" + param_name; + expected_params += "string"; + + } + else if (TypeManager::is_pointer_to_PyObject(type)) + { + indent(out,indent_level+4) << "PyObject *" << param_name; + format_specifiers += "O"; + parameter_list += ", &" + param_name; + pexpr_string = param_name; + pname_for_pyobject += param_name; + expected_params += "PyObject"; + } + else if (TypeManager::is_pointer(type)) + { + expected_params += type->get_preferred_name(); + if (!remap->_has_this || pn != 0 ) + { + indent(out,indent_level+4) << "PyObject *" << param_name; + format_specifiers += "O"; + parameter_list += ", &" + param_name; + pname_for_pyobject += param_name; + + TypeIndex p_type_index = builder.get_type(TypeManager::unwrap(type),false); + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + const InterrogateType &p_itype = idb->get_type(p_type_index); + + //make_safe_name(itype.get_scoped_name()) + extra_convert += p_itype.get_scoped_name()+" *" + param_name + "_this = ("+p_itype.get_scoped_name()+" *)"; + // need to a forward scope for this class.. + if(!isExportThisRun(p_itype._cpptype)) + { + _external_imports.insert(make_safe_name(p_itype.get_scoped_name())); + //ForwardDeclrs << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(p_itype.get_scoped_name()) << ";\n"; + } + + extra_convert += "DTOOL_Call_GetPointerThisClass(" + param_name + ",&Dtool_"+make_safe_name(p_itype.get_scoped_name())+");\n"; + extra_param_check += "|| (" + param_name + "_this == NULL)"; + pexpr_string = param_name + "_this"; + } + + } + else + { + // Ignore a parameter. + indent(out,indent_level+4) << "PyObject *" << param_name; + format_specifiers += "O"; + parameter_list += ", &" + param_name; + expected_params += "any"; + pname_for_pyobject += param_name; + + } + + if (remap->_parameters[pn]._has_name) { + expected_params += " " + remap->_parameters[pn]._name; + } + + if (remap->_has_this && pn == 0) + { + container = "local_this"; + } + else + { + out << ";\n"; + } + + + pexprs.push_back(pexpr_string); + } + expected_params += ")\\n"; + + + + if(!format_specifiers.empty()) + { + std::string format_specifiers1 = format_specifiers + ":" + functionnamestr; + + if(remap->_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))\n"; + indent(out,indent_level+4) << " (PyArg_ParseTuple(args, \"" << format_specifiers1<< "\"" << 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_ParseTuple(args, \"" << format_specifiers1 << "\"" << parameter_list << "))\n"; + } + indent(out,indent_level+4) << "{\n"; + + if (!extra_convert.empty()) + { + indent(out,indent_level+8) << extra_convert << "\n"; + } + + int extra_indent_level =indent_level+8; + + if (!extra_param_check.empty()) + { + indent(out,extra_indent_level) << "if (!(" << extra_param_check.substr(3) << "))\n"; + indent(out,extra_indent_level) <<"{\n"; + extra_indent_level+=4; + } + + + 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 tt; + string return_expr = remap->call_function(out, extra_indent_level, false, container, pexprs); + CPPType *type = remap->_return_type->get_orig_type(); + indent(out,extra_indent_level); + type->output_instance(out, "return_value", &parser); + // type->output_instance(tt, "return_value", &parser); + out << " = " << return_expr << ";\n"; + + if (track_interpreter) { + indent(out,extra_indent_level) << "in_interpreter = 1;\n"; + } + if (!extra_cleanup.empty()) { + indent(out,extra_indent_level) << extra_cleanup << "\n"; + } + + return_expr = manage_return_value(out, 4, remap, "return_value"); + do_assert_init(out, extra_indent_level,isconstructor); + pack_return_value(out, extra_indent_level, remap, return_expr,ForwardDeclrs); + + } + else + { + string return_expr = remap->call_function(out, extra_indent_level, true, container, pexprs); + if (return_expr.empty()) + { + if (track_interpreter) { + indent(out,extra_indent_level) << "in_interpreter = 1;\n"; + } + if (!extra_cleanup.empty()) { + indent(out,extra_indent_level) << extra_cleanup << "\n"; + } + do_assert_init(out, extra_indent_level,isconstructor); + indent(out,extra_indent_level) << "return Py_BuildValue(\"\");\n"; + + } + else + { + CPPType *type = remap->_return_type->get_temporary_type(); + indent(out,extra_indent_level); + type->output_instance(out, "return_value", &parser); + out << " = " << return_expr << ";\n"; + if (track_interpreter) { + indent(out,extra_indent_level) << "in_interpreter = 1;\n"; + } + if (!extra_cleanup.empty()) { + indent(out,extra_indent_level) << extra_cleanup << "\n"; + } + + return_expr = manage_return_value(out, extra_indent_level, remap, "return_value"); + do_assert_init(out, extra_indent_level,isconstructor); + pack_return_value(out, extra_indent_level, remap, remap->_return_type->temporary_to_return(return_expr),ForwardDeclrs); + } + } + + if (!extra_param_check.empty()) + { + extra_indent_level-=4; + indent(out,extra_indent_level)<< "}\n"; + } + + indent(out,indent_level+4) << "}\n"; +} + +//////////////////////////////////////////////////////////////////// +// Function: InterfaceMakerPythonNative::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 InterfaceMakerPythonNative::pack_return_value(ostream &out, int indent_level, + FunctionRemap *remap, string return_expr, ostream &ForwardDeclrs) +{ + 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(), (int)" << 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_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)) + { + if (TypeManager::is_struct(orig_type) || TypeManager::is_ref_to_anything(orig_type)) + { + if( TypeManager::is_ref_to_anything(orig_type)) + { + TypeIndex type_index = builder.get_type(TypeManager::unwrap(type),false); + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + const InterrogateType &itype = idb->get_type(type_index); + std::string ows_memory_flag("true"); + + if(remap->_return_value_needs_management) + ows_memory_flag = "true"; + else + ows_memory_flag = "false"; + + if(!isExportThisRun(itype._cpptype)) + { + _external_imports.insert(make_safe_name(itype.get_scoped_name())); + //ForwardDeclrs << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; + } + + WriteCreateInstance(out,indent_level,return_expr,ows_memory_flag,itype.get_scoped_name(),itype._cpptype); + // indent(out, indent_level) + // <<"return DTool_CreatePyInstance((void *)" << return_expr <<"," << CLASS_PREFEX << make_safe_name(itype.get_scoped_name()) << ","<_type == FunctionRemap::T_constructor ) + { + // should only reach this in the INIT function a a Class .. IE the PY exists before the CPP object + // this is were we type to returned a class/struct.. ie CPP TYpe + + + TypeIndex type_index = builder.get_type(TypeManager::unwrap(orig_type),false); + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + const InterrogateType &itype = idb->get_type(type_index); + indent(out, indent_level) + <<"return DTool_PyInit_Finalize(self, " << return_expr <<",&"<_return_value_needs_management) + ows_memory_flag = "true"; + else + ows_memory_flag = "false"; + + if(remap->_manage_reference_count) + { + TypeIndex type_index = builder.get_type(TypeManager::unwrap(type),false); + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + const InterrogateType &itype = idb->get_type(type_index); + + if(!isExportThisRun(itype._cpptype)) + { + _external_imports.insert(make_safe_name(itype.get_scoped_name())); + //ForwardDeclrs << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; + } + + // ForwardDeclrs << "extern \"C\" struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; + WriteCreateInstance(out,indent_level,return_expr,ows_memory_flag,itype.get_scoped_name(),itype._cpptype); + //indent(out, indent_level) + // <<"return DTool_CreatePyInstance((void *)" << return_expr <<"," << CLASS_PREFEX << make_safe_name(itype.get_scoped_name()) << ","<get_type(type_index); + + if(!isExportThisRun(itype._cpptype)) + { + _external_imports.insert(make_safe_name(itype.get_scoped_name())); + //ForwardDeclrs << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; + } + + // ForwardDeclrs << "extern \"C\" struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; + //indent(out, indent_level) + // <<"return DTool_CreatePyInstance((void *)" << return_expr <<"," << CLASS_PREFEX << make_safe_name(itype.get_scoped_name()) << ","<as_pointer_type()->_pointing_at) ) + { + TypeIndex type_index = builder.get_type(TypeManager::unwrap(orig_type),false); + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + const InterrogateType &itype = idb->get_type(type_index); + + std::string ows_memory_flag("true"); + if(remap->_return_value_needs_management) + ows_memory_flag ="true"; + else + ows_memory_flag = "false"; + + if(!isExportThisRun(itype._cpptype)) + { + _external_imports.insert(make_safe_name(itype.get_scoped_name())); + //ForwardDeclrs << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; + } + + // ForwardDeclrs << "extern \"C\" struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; + WriteCreateInstance(out,indent_level,return_expr,ows_memory_flag,itype.get_scoped_name(),itype._cpptype); + + //indent(out, indent_level) + // << "return DTool_CreatePyInstance((void *)" << return_expr <<","<get_type(type_index); + + if(!isCppTypeLegal(itype._cpptype)) + { + return (Object *)NULL; + } + + Object *object = new Object(itype); + bool inserted = _objects.insert(Objects::value_type(type_index, object)).second; + assert(inserted); + + Function *function; + + int num_constructors = itype.number_of_constructors(); + for (int ci = 0; ci < num_constructors; ci++) + { + function = record_function(itype, itype.get_constructor(ci)); + if(isFunctionLegal(function)) + object->_constructors.push_back(function); + } + +// destructor are handled in a much difrent fashion.. +// if (itype.has_destructor() && !itype.destructor_is_inherited()) +// { +// function = record_function(itype, itype.get_destructor()); +// object->_destructor = function; +// } + + int num_methods = itype.number_of_methods(); + int mi; + for (mi = 0; mi < num_methods; mi++) + { + function = record_function(itype, itype.get_method(mi)); + if(isFunctionLegal(function)) + object->_methods.push_back(function); + + } + + int num_casts = itype.number_of_casts(); + for (mi = 0; mi < num_casts; mi++) + { + function = record_function(itype, itype.get_cast(mi)); + if(isFunctionLegal(function)) + object->_methods.push_back(function); + } + + int num_derivations = itype.number_of_derivations(); + for (int di = 0; di < num_derivations; di++) + { + TypeIndex d_type_Index = itype.get_derivation(di); + const InterrogateType &d_itype = idb->get_type(d_type_Index); + + if(!interrogate_type_is_unpublished(d_type_Index)) + { + if (itype.derivation_has_upcast(di)) + { + function = record_function(itype, itype.derivation_get_upcast(di)); + if(isFunctionLegal(function)) + object->_methods.push_back(function); + } + if (itype.derivation_has_downcast(di)) + { + // Downcasts are methods of the base class, not the child class. + TypeIndex base_type_index = itype.get_derivation(di); + + const InterrogateType &base_type = idb->get_type(base_type_index); + function = record_function(base_type, itype.derivation_get_downcast(di)); + + if(isFunctionLegal(function)) + { + Object * pobject = record_object(base_type_index); + if(pobject != NULL) + pobject->_methods.push_back(function); + } + } + } + } + + int num_elements = itype.number_of_elements(); + for (int ei = 0; ei < num_elements; ei++) + { + ElementIndex element_index = itype.get_element(ei); + const InterrogateElement &ielement = idb->get_element(element_index); + if (ielement.has_getter()) + { + FunctionIndex func_index = ielement.get_getter(); + record_function(itype, func_index); + } + if (ielement.has_setter()) + { + FunctionIndex func_index = ielement.get_setter(); + record_function(itype, func_index); + } + } + + int num_nested = itype.number_of_nested_types(); + for (int ni = 0; ni < num_nested; ni++) + { + TypeIndex nested_index = itype.get_nested_type(ni); + record_object(nested_index); + } + return object; +} +//////////////////////////////////////////////////////////////////// +// Function: InterfaceMaker::generate_wrappers +// Access: Public, Virtual +// Description: Walks through the set of functions in the database +// and generates wrappers for each function, storing +// these in the database. No actual code should be +// output yet; this just updates the database with the +// wrapper information. +//////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::generate_wrappers() +{ + inside_python_native = true; + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + + // We use a while loop rather than a simple for loop, because we + // might increase the number of types recursively during the + // traversal. + + int ti = 0; + while (ti < idb->get_num_all_types()) + { + TypeIndex type_index = idb->get_all_type(ti); + record_object(type_index); + ++ti; + } + + int gi = 0; + while( gi = idb->get_num_global_elements()) + { + printf(" Global Type = %d",gi); + TypeIndex type_index = idb->get_global_element(gi); + record_object(type_index); + + } + + int num_functions = idb->get_num_global_functions(); + for (int fi = 0; fi < num_functions; fi++) + { + FunctionIndex func_index = idb->get_global_function(fi); + record_function(dummy_type, func_index); + } + + + + int num_manifests = idb->get_num_global_manifests(); + for (int mi = 0; mi < num_manifests; mi++) + { + ManifestIndex manifest_index = idb->get_global_manifest(mi); + const InterrogateManifest &iman = idb->get_manifest(manifest_index); + if (iman.has_getter()) + { + FunctionIndex func_index = iman.get_getter(); + record_function(dummy_type, func_index); + } + } + + int num_elements = idb->get_num_global_elements(); + for (int ei = 0; ei < num_elements; ei++) + { + printf(" Element %d\n",ei); + + ElementIndex element_index = idb->get_global_element(ei); + const InterrogateElement &ielement = idb->get_element(element_index); + if (ielement.has_getter()) + { + FunctionIndex func_index = ielement.get_getter(); + record_function(dummy_type, func_index); + } + if (ielement.has_setter()) + { + FunctionIndex func_index = ielement.get_setter(); + record_function(dummy_type, func_index); + } + } + inside_python_native = false; +} +////////////////////////////////////////////// +// Function :isCppTypeLegal +// +// is the cpp object supported by by the dtool_py interface.. +////////////////////////////////////////////// +bool InterfaceMakerPythonNative::isCppTypeLegal(CPPType *ctype) +{ + if(ctype == NULL) + return false; + + if(builder.in_ignoretype(ctype->get_local_name(&parser))) + return false; + + bool answer = false; + CPPType *type = TypeManager::unwrap(ctype); + //CPPType *type = ctype; + + if(TypeManager::is_basic_string_char(type)) + { + return true; + answer = true; + } + else if(TypeManager::is_simple(type)) + { + return true; + answer = true; + } + else if(builder.in_forcetype(ctype->get_local_name(&parser))) + { + return true; + } + else if(TypeManager::IsExported(type) == true) + { + answer = true; + } + else if(TypeManager::is_pointer_to_PyObject(ctype) == true) + { + return true; + } + + return answer; +} +////////////////////////////////////////////// +// Function :isExportThisRun +// +////////////////////////////////////////////// +bool InterfaceMakerPythonNative::isExportThisRun(CPPType *ctype) +{ + CPPType *type = TypeManager::unwrap(ctype); + if(TypeManager::IsLocal(ctype)) + return true; + + if(builder.in_forcetype(ctype->get_local_name(&parser))) + return true; + + return false; +} + +////////////////////////////////////////////// +// Function : isExportThisRun +///////////////////////////////////////////// +bool InterfaceMakerPythonNative::isExportThisRun(Function *func) +{ + if(func == NULL || !isFunctionLegal(func)) + return false; + + Function::Remaps::const_iterator ri; + for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) + { + FunctionRemap *remap = (*ri); + return isExportThisRun(remap->_cpptype); + } + + return false; +} +////////////////////////////////////////////// +// Function : isRemapLegal +////////////////////////////////////////////// +bool InterfaceMakerPythonNative::isRemapLegal( FunctionRemap &remap) +{ + // return must be legal and managable.. + if(!isCppTypeLegal(remap._return_type->get_orig_type())) + return false; + + // ouch .. bad things will happen here .. do not even try.. + if(remap._ForcedVoidReturn) + return false; + + // all params must be legal + for (int pn = 0; pn < (int)remap._parameters.size(); pn++) + { + CPPType *orig_type = remap._parameters[pn]._remap->get_orig_type(); + if(!isCppTypeLegal(orig_type)) + return false; + } + + // ok all looks ok. + return true; +} +//////////////////////////////////////////////////////////////////////// +// Function : isFunctionLegal +//////////////////////////////////////////////////////////////////////// +bool InterfaceMakerPythonNative::isFunctionLegal( Function *func) +{ + Function::Remaps::const_iterator ri; + for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) + { + FunctionRemap *remap = (*ri); + if(isRemapLegal(*remap)) + return true; + } + + return false; +} +//////////////////////////////////////////////////////////////////////// +// Function : isFunctionWithThis +// +// If any rempas have a this .. this function has a this..( of self) to python.. +//////////////////////////////////////////////////////////////////////// +bool InterfaceMakerPythonNative::isFunctionWithThis( Function *func) +{ + Function::Remaps::const_iterator ri; + for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) + { + FunctionRemap *remap = (*ri); + if(remap->_has_this) + return true; + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: InterfaceMakerPython::test_assert +// Access: Protected +// Description: Outputs code to check to see if an assertion has +// failed while the C++ code was executing, and report +// this failure back to Python. +//////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative::do_assert_init(ostream &out, int indent_level, bool constructor) const { + if (watch_asserts) { + out << "#ifndef NDEBUG\n"; + indent(out, indent_level) + << "Notify *notify = Notify::ptr();\n"; + indent(out, indent_level) + << "if (notify->has_assert_failed()) {\n"; + indent(out, indent_level + 2) + << "PyErr_SetString(PyExc_AssertionError, notify->get_assert_error_message().c_str());\n"; + indent(out, indent_level + 2) + << "notify->clear_assert_failed();\n"; + if(constructor) + indent(out, indent_level + 2) << "return -1;\n"; + else + indent(out, indent_level + 2) << "return (PyObject *)NULL;\n"; + indent(out, indent_level) + << "}\n"; + indent(out, indent_level) + << "if (PyErr_Occurred()) {\n"; + if(constructor) + indent(out, indent_level + 2) << "return -1;\n"; + else + indent(out, indent_level + 2) << "return (PyObject *)NULL;\n"; + indent(out, indent_level) + << "}\n"; + out << "#endif\n"; + } +} +//////////////////////////////////////////////////////// +// Function : IsRunTimeTyped +/////////////////////////////////////////////////////// +bool InterfaceMakerPythonNative::IsRunTimeTyped(const InterrogateType &itype) +{ + TypeIndex ptype_id = itype.get_outer_class(); + if(ptype_id > 0) + { + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + + InterrogateType ptype = idb->get_type(ptype_id); + return IsRunTimeTyped(ptype); + } + + + if(itype.get_name() == "TypedObject") + return true; + + return false; +}; + +////////////////////////////////////////////////////////// +// Function : DoesInheritFromIsClass +// +// Helper function to check cpp class inharatience.. +/////////////////////////////////////////////////////////// +bool InterfaceMakerPythonNative::DoesInheritFromIsClass( const CPPStructType * inclass, const std::string &name) +{ + if(inclass == NULL) + return false; + + CPPStructType::Derivation::const_iterator bi; + for (bi = inclass->_derivation.begin(); + bi != inclass->_derivation.end(); + ++bi) + { + + const CPPStructType::Base &base = (*bi); + + CPPStructType *base_type = TypeManager::resolve_type(base._base)->as_struct_type(); + if(base_type != NULL) + { + std::string scoped_name = base_type->get_fully_scoped_name(); + if(scoped_name == name) + return true; + + if(DoesInheritFromIsClass(base_type,name) == true) + return true; + } + } + return false; +} + +//////////////////////////////////////////////////////////////////////////////////////////// +// Function : HasAGetKeyFunction +// +// does the class have a supportable GetKey for hash usage.. +////////////////////////////////////////////////////////////////////////////////////////// +bool InterfaceMakerPythonNative::HasAGetKeyFunction(const InterrogateType &itype_class) +{ + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + + int num_methods = itype_class.number_of_methods(); + int mi; + for (mi = 0; mi < num_methods; mi++) + { + FunctionIndex func_index = itype_class.get_method(mi); + const InterrogateFunction &ifunc = idb->get_function(func_index); + if(ifunc.get_name() == "GetKey") + { + if (ifunc._instances != (InterrogateFunction::Instances *)NULL) + { + InterrogateFunction::Instances::const_iterator ii; + for (ii = ifunc._instances->begin();ii != ifunc._instances->end();++ii) + { + CPPInstance *cppinst = (*ii).second; + CPPFunctionType *cppfunc = cppinst->_type->as_function_type(); + + if(cppfunc != NULL) + { + if(cppfunc->_parameters != NULL && cppfunc->_return_type != NULL && TypeManager::is_integer(cppfunc->_return_type)) + { + if(cppfunc->_parameters->_parameters.size() == 0) + { + return true; + } + } + } + + } + } + } + } + return false; +}; +//////////////////////////////////////////////////////////////////////////////////////////// +// Function : NeedsAStrFunction +// +// Can we generate a __str__ function for this class +////////////////////////////////////////////////////////////////////////////////////////// +bool InterfaceMakerPythonNative::NeedsAStrFunction(const InterrogateType &itype_class) +{ + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + + int num_methods = itype_class.number_of_methods(); + int mi; + for (mi = 0; mi < num_methods; mi++) + { + FunctionIndex func_index = itype_class.get_method(mi); + const InterrogateFunction &ifunc = idb->get_function(func_index); + if(ifunc.get_name() == "write") + { + if (ifunc._instances != (InterrogateFunction::Instances *)NULL) + { + InterrogateFunction::Instances::const_iterator ii; + for (ii = ifunc._instances->begin();ii != ifunc._instances->end();++ii) + { + CPPInstance *cppinst = (*ii).second; + CPPFunctionType *cppfunc = cppinst->_type->as_function_type(); + + if(cppfunc != NULL) + { + if(cppfunc->_parameters != NULL && cppfunc->_return_type != NULL && TypeManager::is_void(cppfunc->_return_type)) + { + if(cppfunc->_parameters->_parameters.size() == 1) + { + + CPPInstance *inst1 = cppfunc->_parameters->_parameters[0]; + if(TypeManager::is_pointer_to_ostream(inst1->_type)) + return true; + } + + if(cppfunc->_parameters->_parameters.size() == 2) + { + + CPPInstance *inst1 = cppfunc->_parameters->_parameters[0]; + if(TypeManager::is_pointer_to_ostream(inst1->_type)) + { + inst1 = cppfunc->_parameters->_parameters[0]; + if(inst1->_initializer != NULL) + return true; + } + } + + } + } + + } + } + } + } + return false; +}; + +//////////////////////////////////////////////////////////////////////////////////////////// +// Function : NeedsAReprFunction +// +// Can we generate a __repr__ function for this class +////////////////////////////////////////////////////////////////////////////////////////// +bool InterfaceMakerPythonNative::NeedsAReprFunction(const InterrogateType &itype_class) +{ + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + + int num_methods = itype_class.number_of_methods(); + int mi; + for (mi = 0; mi < num_methods; mi++) + { + FunctionIndex func_index = itype_class.get_method(mi); + const InterrogateFunction &ifunc = idb->get_function(func_index); + if(ifunc.get_name() == "output") + { + if (ifunc._instances != (InterrogateFunction::Instances *)NULL) + { + InterrogateFunction::Instances::const_iterator ii; + for (ii = ifunc._instances->begin();ii != ifunc._instances->end();++ii) + { + CPPInstance *cppinst = (*ii).second; + CPPFunctionType *cppfunc = cppinst->_type->as_function_type(); + + if(cppfunc != NULL) + { + if(cppfunc->_parameters != NULL && cppfunc->_return_type != NULL && TypeManager::is_void(cppfunc->_return_type)) + { + if(cppfunc->_parameters->_parameters.size() == 1) + { + + CPPInstance *inst1 = cppfunc->_parameters->_parameters[0]; + if(TypeManager::is_pointer_to_ostream(inst1->_type)) + return true; + } + + if(cppfunc->_parameters->_parameters.size() == 2) + { + + CPPInstance *inst1 = cppfunc->_parameters->_parameters[0]; + if(TypeManager::is_pointer_to_ostream(inst1->_type)) + { + inst1 = cppfunc->_parameters->_parameters[0]; + if(inst1->_initializer != NULL) + return true; + } + } + + } + } + + } + } + } + } + return false; +}; + diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.h b/dtool/src/interrogate/interfaceMakerPythonNative.h new file mode 100755 index 0000000000..be2b8738d6 --- /dev/null +++ b/dtool/src/interrogate/interfaceMakerPythonNative.h @@ -0,0 +1,119 @@ +// Filename: InterfaceMakerPythonNative.h +//////////////////////////////////////////////////////////////////// +// +// 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 . +// +//////////////////////////////////////////////////////////////////// + +#ifndef INTERFACEMAKERPYTHONNATIVE_H +#define INTERFACEMAKERPYTHONNATIVE_H +#include "map" +#include "set" +#include "dtoolbase.h" + +#include "interfaceMakerPython.h" +#include "interrogate_interface.h" +#include "cppStructType.h" + +class FunctionRemap; + +//////////////////////////////////////////////////////////////////// +// Class : InterfaceMakerPythonNative +// Description : An InterfaceMaker for generating complex Python +// function wrappers around C++ code. +//////////////////////////////////////////////////////////////////// +class InterfaceMakerPythonNative : public InterfaceMakerPython +{ +public: + InterfaceMakerPythonNative(InterrogateModuleDef *def); + virtual ~InterfaceMakerPythonNative(); + + + virtual void write_prototypes(ostream &out,ostream *out_h); + void write_prototypes_class(ostream &out,ostream *out_h, Object * obj) ; + void write_prototypes_class_external(ostream &out, Object * obj); + + virtual void write_functions(ostream &out); + + virtual void write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def); + virtual void write_module_support(ostream &out, ostream *out_h,InterrogateModuleDef *moduledefdef); + + void write_module_class(ostream &out, Object *cls); + virtual void write_sub_module(ostream &out, Object *obj); + + virtual bool synthesize_this_parameter(); + + virtual Object *record_object(TypeIndex type_index); + +protected: + virtual string get_wrapper_prefix(); + virtual string get_unique_prefix(); + virtual void record_function_wrapper(InterrogateFunction &ifunc, + FunctionWrapperIndex wrapper_index); + + virtual void generate_wrappers(); + +private: + void write_prototype_for_name(ostream &out, Function *func, const std::string &name); + void write_prototype_for(ostream &out, Function *func); + void write_function_for_name(ostream &out, Function *func, const std::string &name, const std::string &PreProcess, const std::string &ClassName); + void write_function_for_top(ostream &out, Function *func, const std::string &PreProcess); + void write_function_instance(ostream &out, Function *func, + FunctionRemap *remap , string &expected_params, int indent_level, bool errors_fatal, ostream &forwarddecl, const std::string &functionnamestr ) ; + + void write_function_forset(ostream &out, InterfaceMaker::Function *func, + std::set< FunctionRemap *> &remaps, string &expected_params, int indent_level , ostream &forwarddecl,const std::string &functionname) ; + + void pack_return_value(ostream &out, int indent_level, + FunctionRemap *remap, std::string return_expr , ostream &forwarddecl); + + void pack_return_value_tnit(ostream &out, int indent_level, + FunctionRemap *remap, string return_expr) ; + + void write_class_prototypes(ostream &out) ; + void write_ClasseDeclarations(ostream &out , ostream *out_h,Object * obj); + void write_ClasseDetails(ostream &out, Object * obj); + + void do_assert_init(ostream &out, int indent_level, bool constructor) const; +public: + bool isRemapLegal( FunctionRemap &remap); + bool isFunctionLegal( Function *func); + bool isCppTypeLegal(CPPType *ctype); + bool isExportThisRun(CPPType *ctype); + bool isExportThisRun(Function *func); + bool isFunctionWithThis( Function *func); + bool IsRunTimeTyped(const InterrogateType &itype); + + // comunicates the cast capabilites among methods.. + struct CastDetails + { + CPPStructType *_structType; + std::string _to_class_name; + std::string _up_cast_string; + bool _can_downcast; + bool _is_legal_py_class; + }; + + void InterfaceMakerPythonNative::GetValideChildClasses( std::map< std::string ,CastDetails > &answer, CPPStructType * inclass, const std::string &up_cast_seed = "", bool downcastposible = true); + bool DoesInheritFromIsClass( const CPPStructType * inclass, const std::string &name); + bool IsPandaTypedObject(CPPStructType * inclass) { return DoesInheritFromIsClass(inclass,"TypedObject"); }; + void WriteCreateInstance(ostream &out, int indent_level, std::string &return_expr, std::string &ows_memory_flag,const std::string &class_name, CPPType *ctype); + bool HasAGetKeyFunction(const InterrogateType &itype_class); + bool NeedsAStrFunction(const InterrogateType &itype_class); + bool NeedsAReprFunction(const InterrogateType &itype_class); + + // stash the forwad declarations for this compile pass.. + std::set< std::string > _external_imports; + +}; + +#endif diff --git a/dtool/src/interrogate/interfaceMakerPythonObj.cxx b/dtool/src/interrogate/interfaceMakerPythonObj.cxx index 1352207876..4b71941277 100644 --- a/dtool/src/interrogate/interfaceMakerPythonObj.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonObj.cxx @@ -15,7 +15,7 @@ // panda3d-general@lists.sourceforge.net . // //////////////////////////////////////////////////////////////////// - + #include "interfaceMakerPythonObj.h" #include "interrogateBuilder.h" #include "interrogate.h" @@ -58,7 +58,7 @@ InterfaceMakerPythonObj:: // write_functions(). //////////////////////////////////////////////////////////////////// void InterfaceMakerPythonObj:: -write_prototypes(ostream &out) { +write_prototypes(ostream &out,ostream *out_h) { Functions::iterator fi; for (fi = _functions.begin(); fi != _functions.end(); ++fi) { Function *func = (*fi); @@ -66,7 +66,7 @@ write_prototypes(ostream &out) { } out << "\n"; - InterfaceMakerPython::write_prototypes(out); + InterfaceMakerPython::write_prototypes(out,out_h); } //////////////////////////////////////////////////////////////////// @@ -102,8 +102,8 @@ write_functions(ostream &out) { // support a module file. //////////////////////////////////////////////////////////////////// void InterfaceMakerPythonObj:: -write_module(ostream &out, InterrogateModuleDef *def) { - InterfaceMakerPython::write_module(out, def); +write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) { + InterfaceMakerPython::write_module(out,out_h, def); out << "static PyMethodDef python_obj_funcs[] = {\n"; diff --git a/dtool/src/interrogate/interfaceMakerPythonObj.h b/dtool/src/interrogate/interfaceMakerPythonObj.h index df9b320e68..01cc9b0f22 100644 --- a/dtool/src/interrogate/interfaceMakerPythonObj.h +++ b/dtool/src/interrogate/interfaceMakerPythonObj.h @@ -44,10 +44,10 @@ public: InterfaceMakerPythonObj(InterrogateModuleDef *def); virtual ~InterfaceMakerPythonObj(); - virtual void write_prototypes(ostream &out); + virtual void write_prototypes(ostream &out,ostream *out_h); virtual void write_functions(ostream &out); - virtual void write_module(ostream &out, InterrogateModuleDef *def); + virtual void write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def); virtual bool synthesize_this_parameter(); diff --git a/dtool/src/interrogate/interfaceMakerPythonSimple.cxx b/dtool/src/interrogate/interfaceMakerPythonSimple.cxx index 88b1915e0b..40f683a585 100644 --- a/dtool/src/interrogate/interfaceMakerPythonSimple.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonSimple.cxx @@ -11,7 +11,7 @@ // 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 +// To contact the maintainers of this program write to // panda3d-general@lists.sourceforge.net . // //////////////////////////////////////////////////////////////////// @@ -56,7 +56,7 @@ InterfaceMakerPythonSimple:: // write_functions(). //////////////////////////////////////////////////////////////////// void InterfaceMakerPythonSimple:: -write_prototypes(ostream &out) { +write_prototypes(ostream &out,ostream *out_h) { Functions::iterator fi; for (fi = _functions.begin(); fi != _functions.end(); ++fi) { Function *func = (*fi); @@ -64,7 +64,7 @@ write_prototypes(ostream &out) { } out << "\n"; - InterfaceMakerPython::write_prototypes(out); + InterfaceMakerPython::write_prototypes(out,out_h); } //////////////////////////////////////////////////////////////////// @@ -92,8 +92,8 @@ write_functions(ostream &out) { // support a module file. //////////////////////////////////////////////////////////////////// void InterfaceMakerPythonSimple:: -write_module(ostream &out, InterrogateModuleDef *def) { - InterfaceMakerPython::write_module(out, def); +write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) { + InterfaceMakerPython::write_module(out,out_h, def); out << "static PyMethodDef python_simple_funcs[] = {\n"; @@ -215,8 +215,7 @@ write_function_for(ostream &out, InterfaceMaker::Function *func) { // 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, +void InterfaceMakerPythonSimple::write_function_instance(ostream &out, InterfaceMaker::Function *func, FunctionRemap *remap) { out << "/*\n" << " * Python simple wrapper for\n" @@ -435,7 +434,8 @@ pack_return_value(ostream &out, int indent_level, 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 (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"; @@ -446,11 +446,13 @@ pack_return_value(ostream &out, int indent_level, << return_expr << ".data(), " << return_expr << ".length());\n"; } - } else if (TypeManager::is_unsigned_longlong(type)) { + } else if (TypeManager::is_unsigned_longlong(type)) + { indent(out, indent_level) << "return PyLong_FromUnsignedLongLong(" << return_expr << ");\n"; - } else if (TypeManager::is_longlong(type)) { + } else if (TypeManager::is_longlong(type)) + { indent(out, indent_level) << "return PyLong_FromLongLong(" << return_expr << ");\n"; diff --git a/dtool/src/interrogate/interfaceMakerPythonSimple.h b/dtool/src/interrogate/interfaceMakerPythonSimple.h index 435cb35e36..c4bff79516 100644 --- a/dtool/src/interrogate/interfaceMakerPythonSimple.h +++ b/dtool/src/interrogate/interfaceMakerPythonSimple.h @@ -43,10 +43,10 @@ public: InterfaceMakerPythonSimple(InterrogateModuleDef *def); virtual ~InterfaceMakerPythonSimple(); - virtual void write_prototypes(ostream &out); + virtual void write_prototypes(ostream &out,ostream *out_h); virtual void write_functions(ostream &out); - virtual void write_module(ostream &out, InterrogateModuleDef *def); + virtual void write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def); virtual bool synthesize_this_parameter(); diff --git a/dtool/src/interrogate/interrogate.cxx b/dtool/src/interrogate/interrogate.cxx index b5b2f8516c..11167e662f 100644 --- a/dtool/src/interrogate/interrogate.cxx +++ b/dtool/src/interrogate/interrogate.cxx @@ -37,6 +37,7 @@ CPPParser parser; Filename output_code_filename; +Filename output_include_filename; Filename output_data_filename; string output_data_basename; bool output_module_specific = false; @@ -49,11 +50,12 @@ bool true_wrapper_names = false; bool build_c_wrappers = false; bool build_python_wrappers = false; bool build_python_obj_wrappers = false; +bool build_python_native = false; bool track_interpreter = false; bool save_unique_names = false; bool no_database = false; bool generate_spam = false; -bool left_inheritance_requires_upcast = false; +bool left_inheritance_requires_upcast = true; CPPVisibility min_vis = V_published; string library_name; string module_name; @@ -77,6 +79,7 @@ enum CommandOptions { CO_c, CO_python, CO_python_obj, + CO_python_native, CO_track_interpreter, CO_unique_names, CO_nodb, @@ -101,6 +104,7 @@ static struct option long_options[] = { { "c", no_argument, NULL, CO_c }, { "python", no_argument, NULL, CO_python }, { "python-obj", no_argument, NULL, CO_python_obj }, + { "python-native", no_argument, NULL, CO_python_native }, { "track-interpreter", no_argument, NULL, CO_track_interpreter }, { "unique-names", no_argument, NULL, CO_unique_names }, { "nodb", no_argument, NULL, CO_nodb }, @@ -241,6 +245,10 @@ void show_help() { << " Generate Python function wrappers that convert C++ objects to true\n" << " python objects, with all methods converted to Python methods. This\n" << " is currently experimental.\n\n" + << " -python-native\n" + << " Generate Python function wrappers that convert C++ objects to true\n" + << " python objects, with all methods converted to Python methods. This\n" + << " is currently experimental.\n\n" << " Any combination of -c, -python, or -python-obj may be specified. If all\n" << " are omitted, the default is -c.\n\n" @@ -278,15 +286,15 @@ void show_help() { // handle commandline -D options static void -predefine_macro(CPPParser& parser, const string& option) { +predefine_macro(CPPParser& parser, const string& inoption) { string macro_name, macro_def; - size_t eq = option.find('='); + size_t eq = inoption.find('='); if (eq != string::npos) { - macro_name = option.substr(0, eq); - macro_def = option.substr(eq + 1); + macro_name = inoption.substr(0, eq); + macro_def = inoption.substr(eq + 1); } else { - macro_name = option; + macro_name = inoption; } CPPManifest *macro = new CPPManifest(macro_name + " " + macro_def); @@ -384,6 +392,10 @@ main(int argc, char *argv[]) { build_python_obj_wrappers = true; break; + case CO_python_native: + build_python_native = true; + break; + case CO_track_interpreter: track_interpreter = true; break; @@ -427,8 +439,16 @@ main(int argc, char *argv[]) { exit(1); } + +// if(!output_code_filename.empty()) +// { +// output_include_filename = output_code_filename.get_fullpath_wo_extension() +".h"; +// printf(" Include File Will be Set to %s \n",output_include_filename.c_str()); +// } + output_code_filename.set_text(); output_data_filename.set_text(); +// output_include_filename.set_text(); output_data_basename = output_data_filename.get_basename(); if (output_function_names && true_wrapper_names) { @@ -440,14 +460,16 @@ main(int argc, char *argv[]) { } if (!build_c_wrappers && !build_python_wrappers && - !build_python_obj_wrappers) { + !build_python_obj_wrappers &&!build_python_native) { build_c_wrappers = true; } // Get all of the .h files. - for (i = 1; i < argc; ++i) { + for (i = 1; i < argc; ++i) + { Filename filename = Filename::from_os_specific(argv[i]); - if (!parser.parse_file(Filename::from_os_specific(filename))) { + if (!parser.parse_file(Filename::from_os_specific(filename))) + { cerr << "Error parsing file: '" << argv[i] << "'\n"; exit(1); } @@ -479,9 +501,37 @@ main(int argc, char *argv[]) { // database, so we can check synchronicity at load time. int file_identifier = time((time_t *)NULL); InterrogateModuleDef *def = builder.make_module_def(file_identifier); + + ofstream * the_output_include = NULL; + ofstream output_include; + + + if (1==2 && !output_include_filename.empty()) + { + output_include_filename.open_write(output_include); + + output_include << "#ifndef " << output_include_filename.get_basename_wo_extension() << "__HH__\n"; + output_include << "#define " << output_include_filename.get_basename_wo_extension() << "__HH__\n"; + + output_include + << "/*\n" + << " * This file generated by:\n" + << " * " << command_line << "\n" + << " *\n" + << " */\n\n"; + + + if (output_include.fail()) + { + nout << "Unable to write to " << output_include_filename << "\n"; + exit(-1); + } + the_output_include = &output_include; + } // Now output all of the wrapper functions. - if (!output_code_filename.empty()) { + if (!output_code_filename.empty()) + { ofstream output_code; output_code_filename.open_write(output_code); @@ -492,19 +542,30 @@ main(int argc, char *argv[]) { << " *\n" << " */\n\n"; + if(the_output_include != NULL) + { + output_code << "#include \""<write(output_data, def); diff --git a/dtool/src/interrogate/interrogate.h b/dtool/src/interrogate/interrogate.h index c40d4427d0..81ee128755 100644 --- a/dtool/src/interrogate/interrogate.h +++ b/dtool/src/interrogate/interrogate.h @@ -41,6 +41,7 @@ extern bool true_wrapper_names; extern bool build_c_wrappers; extern bool build_python_wrappers; extern bool build_python_obj_wrappers; +extern bool build_python_native; extern bool track_interpreter; extern bool save_unique_names; extern bool no_database; diff --git a/dtool/src/interrogate/interrogateBuilder.cxx b/dtool/src/interrogate/interrogateBuilder.cxx index 4c7a05cd77..9028d4c4c4 100644 --- a/dtool/src/interrogate/interrogateBuilder.cxx +++ b/dtool/src/interrogate/interrogateBuilder.cxx @@ -24,6 +24,7 @@ #include "interfaceMakerC.h" #include "interfaceMakerPythonObj.h" #include "interfaceMakerPythonSimple.h" +#include "interfaceMakerPythonNative.h" #include "functionRemap.h" #include "interrogateType.h" @@ -53,19 +54,8 @@ #include InterrogateBuilder builder; - -/* -static string -upcase_string(const string &str) { - string result; - for (string::const_iterator si = str.begin(); - si != str.end(); - ++si) { - result += toupper(*si); - } - return result; -} -*/ +std::string EXPORT_IMPORT_PREFEX; +bool inside_python_native = false; //////////////////////////////////////////////////////////////////// // Function: InterrogateBuilder::add_source_file @@ -238,18 +228,24 @@ build() { for (di = parser._declarations.begin(); di != parser._declarations.end(); ++di) { - if ((*di)->get_subtype() == CPPDeclaration::ST_instance) { + if ((*di)->get_subtype() == CPPDeclaration::ST_instance) + { CPPInstance *inst = (*di)->as_instance(); - if (inst->_type->get_subtype() == CPPDeclaration::ST_function) { + if (inst->_type->get_subtype() == CPPDeclaration::ST_function) + { // Here's a function declaration. scan_function(inst); - } else { + } + else + { // Here's a data element declaration. scan_element(inst, (CPPStructType *)NULL, &parser); } - } else if ((*di)->get_subtype() == CPPDeclaration::ST_typedef) { + } + else if ((*di)->get_subtype() == CPPDeclaration::ST_typedef) + { CPPTypedef *tdef = (*di)->as_typedef(); if (tdef->_type->get_subtype() == CPPDeclaration::ST_struct) { // A typedef counts as a declaration. This lets us pick up @@ -263,9 +259,9 @@ build() { CPPType *type = (*di)->as_type_declaration()->_type; type->_vis = (*di)->_vis; - if (type->get_subtype() == CPPDeclaration::ST_struct) { - CPPStructType *struct_type = - type->as_type()->resolve_type(&parser, &parser)->as_struct_type(); + if (type->get_subtype() == CPPDeclaration::ST_struct) + { + CPPStructType *struct_type =type->as_type()->resolve_type(&parser, &parser)->as_struct_type(); scan_struct_type(struct_type); } else if (type->get_subtype() == CPPDeclaration::ST_enum) { @@ -293,8 +289,7 @@ build() { // Description: Generates all the code necessary to the indicated // output stream. //////////////////////////////////////////////////////////////////// -void InterrogateBuilder:: -write_code(ostream &out, InterrogateModuleDef *def) { +void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, InterrogateModuleDef *def) { typedef vector InterfaceMakers; InterfaceMakers makers; @@ -313,8 +308,18 @@ write_code(ostream &out, InterrogateModuleDef *def) { makers.push_back(maker); } - InterfaceMakers::iterator mi; + if (build_python_native ) { + InterfaceMakerPythonNative *maker = new InterfaceMakerPythonNative(def); + makers.push_back(maker); + } + + EXPORT_IMPORT_PREFEX = std::string("EXPCL_") + def->module_name; + for (size_t i=0; igenerate_wrappers(); @@ -330,15 +335,25 @@ write_code(ostream &out, InterrogateModuleDef *def) { } // Now, begin the actual output. Start with the #include lines. - if (!no_database) { - out << "#include \"dtoolbase.h\"\n" + + if (!no_database) + { + out_code << "#include \"dtoolbase.h\"\n" << "#include \"interrogate_request.h\"\n" << "#include \"dconfig.h\"\n"; } + + + ostringstream declaration_bodies; + if (watch_asserts) { - out << "#include \"notify.h\"\n"; + declaration_bodies << "#include \"notify.h\"\n"; } - out << "\n"; + + declaration_bodies << "#include \n"; + + declaration_bodies << "#include \"py_panda.h\" \n"; + declaration_bodies << "\n"; IncludeFiles::const_iterator ifi; for (ifi = _include_files.begin(); @@ -348,41 +363,54 @@ write_code(ostream &out, InterrogateModuleDef *def) { char delimiter = (*ifi).second; if (should_include(filename)) { if (delimiter == '"') { - out << "#include \"" << filename << "\"\n"; + declaration_bodies << "#include \"" << filename << "\"\n"; } else { - out << "#include <" << filename << ">\n"; + declaration_bodies << "#include <" << filename << ">\n"; } } } - out << "\n"; + declaration_bodies << "\n"; + for (mi = makers.begin(); mi != makers.end(); ++mi) { - (*mi)->write_includes(out); + (*mi)->write_includes(declaration_bodies); } if (generate_spam) { - out << "#include \"config_interrogatedb.h\"\n" + declaration_bodies << "#include \"config_interrogatedb.h\"\n" << "#include \"notifyCategoryProxy.h\"\n\n" << "NotifyCategoryDeclNoExport(in_" << library_name << ");\n" << "NotifyCategoryDef(in_" << library_name << ", interrogatedb_cat);\n\n"; } - out << "\n"; + declaration_bodies << "\n"; + + // And now the prototypes. for (mi = makers.begin(); mi != makers.end(); ++mi) { - (*mi)->write_prototypes(out); + (*mi)->write_prototypes(declaration_bodies,out_include); } + declaration_bodies << "\n"; + +// if(out_include != NULL) +// (*out_include) << declaration_bodies.str(); +// else + out_code << declaration_bodies.str(); - out << "\n"; // Followed by the function bodies. - out << function_bodies.str() << "\n"; + out_code << function_bodies.str() << "\n"; + + for (mi = makers.begin(); mi != makers.end(); ++mi) { + (*mi)->write_module_support(out_code,out_include,def); + } + if (output_module_specific) { // Output whatever stuff we should output if this were a module. for (mi = makers.begin(); mi != makers.end(); ++mi) { - (*mi)->write_module(out, def); + (*mi)->write_module(out_code,out_include, def); } } @@ -410,7 +438,7 @@ write_code(ostream &out, InterrogateModuleDef *def) { if (output_function_pointers) { // Write out the table of function pointers. - out << "static void *_in_fptrs[" << num_wrappers << "] = {\n"; + out_code << "static void *_in_fptrs[" << num_wrappers << "] = {\n"; int next_index = 1; map::iterator ii; for (ii = wrappers_by_index.begin(); @@ -418,79 +446,84 @@ write_code(ostream &out, InterrogateModuleDef *def) { ++ii) { int this_index = (*ii).first; while (next_index < this_index) { - out << " (void *)0,\n"; + out_code << " (void *)0,\n"; next_index++; } assert(next_index == this_index); FunctionRemap *remap = (*ii).second; - out << " (void *)&" << remap->_wrapper_name << ",\n"; + out_code << " (void *)&" << remap->_wrapper_name << ",\n"; next_index++; } while (next_index < num_wrappers + 1) { - out << " (void *)0,\n"; + out_code << " (void *)0,\n"; next_index++; } - out << "};\n\n"; + out_code << "};\n\n"; } + if (save_unique_names) { // Write out the table of unique names, in no particular order. - out << "static InterrogateUniqueNameDef _in_unique_names[" + out_code << "static InterrogateUniqueNameDef _in_unique_names[" << num_wrappers << "] = {\n"; for (ri = remaps.begin(); ri != remaps.end(); ++ri) { FunctionRemap *remap = (*ri); - out << " { \"" + out_code << " { \"" << remap->_unique_name << "\", " << remap->_wrapper_index - 1 << " },\n"; } - out << "};\n\n"; + out_code << "};\n\n"; } +//if(1==2) +{ + if (!no_database) { // Now build the module definition structure to add ourselves to // the global interrogate database. - out << "static InterrogateModuleDef _in_module_def = {\n" + out_code << "static InterrogateModuleDef _in_module_def = {\n" << " " << def->file_identifier << ", /* file_identifier */\n" << " \"" << def->library_name << "\", /* library_name */\n" << " \"" << def->library_hash_name << "\", /* library_hash_name */\n" << " \"" << def->module_name << "\", /* module_name */\n"; if (def->database_filename != (const char *)NULL) { - out << " \"" << def->database_filename + out_code << " \"" << def->database_filename << "\", /* database_filename */\n"; } else { - out << " (const char *)0, /* database_filename */\n"; + out_code << " (const char *)0, /* database_filename */\n"; } if (save_unique_names) { - out << " _in_unique_names,\n" + out_code << " _in_unique_names,\n" << " " << num_wrappers << ", /* num_unique_names */\n"; } else { - out << " (InterrogateUniqueNameDef *)0, /* unique_names */\n" + out_code << " (InterrogateUniqueNameDef *)0, /* unique_names */\n" << " 0, /* num_unique_names */\n"; } - if (output_function_pointers) { - out << " _in_fptrs,\n" + if (output_function_pointers) { + out_code << " _in_fptrs,\n" << " " << num_wrappers << ", /* num_fptrs */\n"; } else { - out << " (void **)0, /* fptrs */\n" + out_code << " (void **)0, /* fptrs */\n" << " 0, /* num_fptrs */\n"; } - out << " 1, /* first_index */\n" + out_code << " 1, /* first_index */\n" << " " << InterrogateDatabase::get_ptr()->get_next_index() << " /* next_index */\n" << "};\n\n"; // And now write the static-init code that tells the interrogate // database to load up this module. - out << "Configure(_in_configure_" << library_name << ");\n" + out_code << "Configure(_in_configure_" << library_name << ");\n" << "ConfigureFn(_in_configure_" << library_name << ") {\n" << " interrogate_request_module(&_in_module_def);\n" << "}\n\n"; } } +} //////////////////////////////////////////////////////////////////// // Function: InterrogateBuilder::make_module_def @@ -938,10 +971,9 @@ scan_function(CPPFunctionGroup *fgroup) { void InterrogateBuilder:: scan_function(CPPInstance *function) { assert(function != (CPPInstance *)NULL); - assert(function->_type != (CPPType *)NULL && - function->_type->as_function_type() != (CPPFunctionType *)NULL); - CPPFunctionType *ftype = - function->_type->resolve_type(&parser, &parser)->as_function_type(); + assert(function->_type != (CPPType *)NULL && function->_type->as_function_type() != (CPPFunctionType *)NULL); + + CPPFunctionType *ftype = function->_type->resolve_type(&parser, &parser)->as_function_type(); assert(ftype != (CPPFunctionType *)NULL); CPPScope *scope = &parser; @@ -1040,7 +1072,8 @@ scan_struct_type(CPPStructType *type) { // Check if any of the members are exported. If none of them are, // and the type itself is not marked for export, then never mind. - if (type->_vis > min_vis) { + if (type->_vis > min_vis) + { CPPScope *scope = type->_scope; bool any_exported = false; @@ -1713,7 +1746,8 @@ get_type(CPPType *type, bool global) { // If it's an extension type of some kind, it might be scoped. if (ext_type->_ident != (CPPIdentifier *)NULL) { CPPScope *scope = ext_type->_ident->get_scope(&parser, &parser); - while (scope->as_template_scope() != (CPPTemplateScope *)NULL) { + while (scope->as_template_scope() != (CPPTemplateScope *)NULL) + { assert(scope->get_parent_scope() != scope); scope = scope->get_parent_scope(); assert(scope != (CPPScope *)NULL); @@ -1734,19 +1768,23 @@ get_type(CPPType *type, bool global) { } } - if (forced || !in_ignoretype(true_name)) { + if (forced || !in_ignoretype(true_name)) + { itype._flags |= InterrogateType::F_fully_defined; - if (type->as_simple_type() != (CPPSimpleType *)NULL) { + if (type->as_simple_type() != (CPPSimpleType *)NULL) + { define_atomic_type(itype, type->as_simple_type()); - } else if (type->as_pointer_type() != (CPPPointerType *)NULL) { + } else if (type->as_pointer_type() != (CPPPointerType *)NULL) + { define_wrapped_type(itype, type->as_pointer_type()); } else if (type->as_const_type() != (CPPConstType *)NULL) { define_wrapped_type(itype, type->as_const_type()); - } else if (type->as_struct_type() != (CPPStructType *)NULL) { + } else if (type->as_struct_type() != (CPPStructType *)NULL) + { define_struct_type(itype, type->as_struct_type(), index, forced); } else if (type->as_enum_type() != (CPPEnumType *)NULL) { @@ -1930,9 +1968,12 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype, bi != cpptype->_derivation.end(); ++bi) { const CPPStructType::Base &base = (*bi); - if (base._vis <= V_public) { + if (base._vis <= V_public) + { + CPPType *base_type = TypeManager::resolve_type(base._base, scope); TypeIndex base_index = get_type(base_type, true); + if (base_index == 0) { nout << *cpptype << " reports a derivation from an invalid type.\n"; @@ -1946,6 +1987,8 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype, // Do we need to synthesize upcast and downcast functions? bool generate_casts = false; + + // Function To Generate all castsss Posible.. if (base._is_virtual) { // We do in the presence of virtual inheritance. generate_casts = true; @@ -1972,6 +2015,8 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype, } if (generate_casts) { + + d._upcast = get_cast_function(base_type, cpptype, "upcast"); d._flags |= InterrogateType::DF_upcast; @@ -2008,12 +2053,15 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype, } } - } else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration) { + } else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration) + { CPPType *type = (*di)->as_type_declaration()->_type; - if ((*di)->_vis <= min_vis) { + if ((*di)->_vis <= min_vis || in_forcetype(type->get_local_name(&parser))) + { if (type->as_struct_type() != (CPPStructType *)NULL || - type->as_enum_type() != (CPPEnumType *)NULL) { + type->as_enum_type() != (CPPEnumType *)NULL) + { // Here's a nested class or enum definition. type->_vis = (*di)->_vis; @@ -2021,7 +2069,8 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype, assert(nested_type != (CPPExtensionType *)NULL); // Only try to export named types. - if (nested_type->_ident != (CPPIdentifier *)NULL) { + if (nested_type->_ident != (CPPIdentifier *)NULL) + { TypeIndex nested_index = get_type(nested_type, false); itype._nested_types.push_back(nested_index); } @@ -2129,7 +2178,8 @@ void InterrogateBuilder:: define_method(CPPFunctionGroup *fgroup, InterrogateType &itype, CPPStructType *struct_type, CPPScope *scope) { CPPFunctionGroup::Instances::const_iterator fi; - for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { + for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) + { CPPInstance *function = (*fi); define_method(function, itype, struct_type, scope); } diff --git a/dtool/src/interrogate/interrogateBuilder.h b/dtool/src/interrogate/interrogateBuilder.h index 3df0a74f3e..ee1b342bd4 100644 --- a/dtool/src/interrogate/interrogateBuilder.h +++ b/dtool/src/interrogate/interrogateBuilder.h @@ -59,7 +59,7 @@ public: void read_command_file(istream &in); void do_command(const string &command, const string ¶ms); void build(); - void write_code(ostream &out, InterrogateModuleDef *def); + void write_code(ostream &out_code,ostream *out_include, InterrogateModuleDef *def); InterrogateModuleDef *make_module_def(int file_identifier); static string clean_identifier(const string &name); @@ -68,8 +68,10 @@ public: string get_preferred_name(CPPType *type); static string hash_string(const string &name, int shift_offset); + TypeIndex get_type(CPPType *type, bool global); private: +public: typedef set Commands; typedef map CommandParams; void insert_param_list(InterrogateBuilder::Commands &commands, @@ -108,7 +110,7 @@ private: int flags, const string &expression = string()); TypeIndex get_atomic_string_type(); - TypeIndex get_type(CPPType *type, bool global); +// TypeIndex get_type(CPPType *type, bool global); void define_atomic_type(InterrogateType &itype, CPPSimpleType *cpptype); void define_wrapped_type(InterrogateType &itype, CPPPointerType *cpptype); diff --git a/dtool/src/interrogate/interrogate_composite1.cxx b/dtool/src/interrogate/interrogate_composite1.cxx index 76f5ca179a..39f08c9fe4 100644 --- a/dtool/src/interrogate/interrogate_composite1.cxx +++ b/dtool/src/interrogate/interrogate_composite1.cxx @@ -8,6 +8,7 @@ #include "interfaceMaker.cxx" #include "interfaceMakerC.cxx" #include "interfaceMakerPython.cxx" +#include "interfaceMakerPythonNative.cxx" #include "interfaceMakerPythonObj.cxx" #include "interfaceMakerPythonSimple.cxx" diff --git a/dtool/src/interrogate/interrogate_module.cxx b/dtool/src/interrogate/interrogate_module.cxx index 10b46780d1..355057cd02 100644 --- a/dtool/src/interrogate/interrogate_module.cxx +++ b/dtool/src/interrogate/interrogate_module.cxx @@ -27,6 +27,8 @@ #include "pystub.h" #include "notify.h" +#include "set" + // If our system getopt() doesn't come with getopt_long_only(), then use // the GNU flavor that we've got in tool for this purpose. #ifndef HAVE_GETOPT_LONG_ONLY @@ -40,6 +42,7 @@ string module_name; string library_name; bool build_c_wrappers = false; bool build_python_wrappers = false; +bool build_python_native_wrappers = false; bool track_interpreter = false; // Short command-line options. @@ -52,6 +55,7 @@ enum CommandOptions { CO_library, CO_c, CO_python, + CO_python_native, CO_track_interpreter, }; @@ -61,6 +65,7 @@ static struct option long_options[] = { { "library", required_argument, NULL, CO_library }, { "c", no_argument, NULL, CO_c }, { "python", no_argument, NULL, CO_python }, + { "python-native", no_argument, NULL, CO_python_native }, { "track-interpreter", no_argument, NULL, CO_track_interpreter }, { NULL } }; @@ -78,8 +83,88 @@ upcase_string(const string &str) { } */ -int -write_python_table(ostream &out) { +int write_python_table_native(ostream &out) +{ + out << "\n#include \"dtoolbase.h\"\n" + << "#include \"interrogate_request.h\"\n\n" + << "#undef _POSIX_C_SOURCE\n" + << "#include \"py_panda.h\"\n\n"; + + int count = 0; + + std::set Libraries; + + +// out << "extern \"C\" {\n"; + + // Walk through all of the Python functions. + int num_functions = interrogate_number_of_functions(); + int fi; + for (fi = 0; fi < num_functions; fi++) + { + FunctionIndex function_index = interrogate_get_function(fi); + + // Consider only those that belong in the module we asked for. + if (interrogate_function_has_module_name(function_index) && + module_name == interrogate_function_module_name(function_index)) + { + // if it has a library name add it to set of libraries + if(interrogate_function_has_library_name(function_index)) + Libraries.insert(interrogate_function_library_name(function_index)); + } + } + + for(int ti = 0; ti < interrogate_number_of_types(); ti++) + { + TypeIndex thetype = interrogate_get_type(ti); + if(interrogate_type_has_module_name(thetype) && module_name == interrogate_type_module_name(thetype)) + { + if(interrogate_type_has_library_name(thetype)) + Libraries.insert(interrogate_type_library_name(thetype)); + } + } + + + + std::set::iterator ii; + for(ii = Libraries.begin(); ii != Libraries.end(); ii++) + { + printf("Referencing Library %s\n",(*ii).c_str()); + out << "extern LibrayDef "<< *ii << "_moddef ;\n"; + } + + + + + out << "#ifdef _WIN32\n" + << "extern \"C\" __declspec(dllexport) void init" << library_name << "();\n" + << "#else\n" + << "extern \"C\" void init" << library_name << "();\n" + << "#endif\n\n" + + << "void init" << library_name << "() \n{\n"; + if (track_interpreter) { + out << " in_interpreter = 1;\n"; + } + + out << " LibrayDef *defs[] = {"; + for(ii = Libraries.begin(); ii != Libraries.end(); ii++) + out << "&"<< *ii << "_moddef,"; + + out << " NULL };\n "; + + + out << " Dtool_PyModuleInitHelper( defs, \"" << library_name << "\");\n"; + out << "\n\n\n}\n"; + + return count; +} + + + + +int write_python_table(ostream &out) +{ out << "\n#include \"dtoolbase.h\"\n" << "#include \"interrogate_request.h\"\n\n" << "#undef _POSIX_C_SOURCE\n" @@ -175,8 +260,8 @@ write_python_table(ostream &out) { return count; } -int -main(int argc, char *argv[]) { +int main(int argc, char *argv[]) +{ extern char *optarg; extern int optind; int flag; @@ -204,6 +289,10 @@ main(int argc, char *argv[]) { build_python_wrappers = true; break; + case CO_python_native: + build_python_native_wrappers = true; + break; + case CO_track_interpreter: track_interpreter = true; break; @@ -226,7 +315,7 @@ main(int argc, char *argv[]) { output_code_filename.set_text(); - if (!build_c_wrappers && !build_python_wrappers) { + if (!build_c_wrappers && !build_python_wrappers && !build_python_native_wrappers) { build_c_wrappers = true; } @@ -253,16 +342,24 @@ main(int argc, char *argv[]) { } // Now output the table. - if (!output_code_filename.empty()) { + if (!output_code_filename.empty()) + { ofstream output_code; - if (!output_code_filename.open_write(output_code)) { + if (!output_code_filename.open_write(output_code)) + { nout << "Unable to write to " << output_code_filename << "\n"; } else { + if (build_python_wrappers) { int count = write_python_table(output_code); nout << count << " python function wrappers exported.\n"; } + + if (build_python_native_wrappers) { + write_python_table_native(output_code); + } + } } diff --git a/dtool/src/interrogate/parameterRemapBasicStringToString.cxx b/dtool/src/interrogate/parameterRemapBasicStringToString.cxx index 50c5b90ab5..b5b0aac7c5 100644 --- a/dtool/src/interrogate/parameterRemapBasicStringToString.cxx +++ b/dtool/src/interrogate/parameterRemapBasicStringToString.cxx @@ -54,7 +54,7 @@ pass_parameter(ostream &out, const string &variable_name) { string ParameterRemapBasicStringToString:: prepare_return_expr(ostream &out, int indent_level, const string &expression) { InterfaceMaker::indent(out, indent_level) - << "static basic_string string_holder = " << expression << ";\n"; + << "static string string_holder = " << expression << ";\n"; return "string_holder"; } diff --git a/dtool/src/interrogate/typeManager.cxx b/dtool/src/interrogate/typeManager.cxx index 9d3ea2d649..286d687e0c 100644 --- a/dtool/src/interrogate/typeManager.cxx +++ b/dtool/src/interrogate/typeManager.cxx @@ -29,6 +29,9 @@ #include "cppStructType.h" #include "cppTypeDeclaration.h" #include "notify.h" +#include "cppTypedef.h" +#include "cppEnumType.h" + //////////////////////////////////////////////////////////////////// // Function: TypeManager::resolve_type @@ -818,6 +821,47 @@ is_PyObject(CPPType *type) { } } + +//////////////////////////////////////////////////////////////////// +// Function: TypeManager::is_ostream +// Access: Public, Static +// Description: Returns true if the indicated type is PyObject. +//////////////////////////////////////////////////////////////////// +bool TypeManager::is_ostream(CPPType *type) { + switch (type->get_subtype()) { + case CPPDeclaration::ST_const: + return is_ostream(type->as_const_type()->_wrapped_around); + + case CPPDeclaration::ST_struct: + return (type->get_local_name(&parser) == "ostream"); + + default: + return false; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TypeManager::is_pointer_to_PyObject +// Access: Public, Static +// Description: Returns true if the indicated type is PyObject *. +//////////////////////////////////////////////////////////////////// +bool TypeManager:: +is_pointer_to_ostream(CPPType *type) { + switch (type->get_subtype()) { + case CPPDeclaration::ST_const: + return is_pointer_to_ostream(type->as_const_type()->_wrapped_around); + + case CPPDeclaration::ST_reference: + return is_ostream(type->as_reference_type()->_pointing_at); + + case CPPDeclaration::ST_pointer: + return is_ostream(type->as_pointer_type()->_pointing_at); + + default: + return false; + } +} + //////////////////////////////////////////////////////////////////// // Function: TypeManager::involves_unpublished // Access: Public, Static @@ -1313,3 +1357,171 @@ has_protected_destructor(CPPType *type) { // No explicit destructor. return false; } +//////////////////////////////////////////////////////////////////// +// Function: TypeManager::has_protected_destructor +// Access: Public, Static +// Description: Returns true if the destructor for the given class or +// struct is protected or private, or false if the +// destructor is public or absent. +//////////////////////////////////////////////////////////////////// +bool TypeManager::IsExported(CPPType *in_type) +{ + + string name = in_type->get_local_name(&parser); + if (name.empty()) { + return false; + } + + //return true; + + // this question is about the base type + CPPType *base_type = resolve_type(unwrap(in_type)); + //CPPType *base_type = in_type; + // Ok export Rules.. + // Classes and Structs and Unions are exported only if they have a + // function that is exported.. + // function is the easiest case. + + if (base_type->_vis <= min_vis) + return true; + + if (in_type->_vis <= min_vis) + return true; + + + if (base_type->get_subtype() == CPPDeclaration::ST_struct) + { + CPPStructType *sstruct_type = base_type->as_struct_type(); + CPPStructType *struct_type =sstruct_type->resolve_type(&parser, &parser)->as_struct_type(); + CPPScope *scope = struct_type->_scope; + + CPPScope::Declarations::const_iterator di; + for (di = scope->_declarations.begin();di != scope->_declarations.end(); di++) + if ((*di)->_vis <= min_vis) + return true; + } + else if (base_type->get_subtype() == CPPDeclaration::ST_instance) + { + CPPInstance *inst = base_type->as_instance(); + if (inst->_type->get_subtype() == CPPDeclaration::ST_function) + { + CPPInstance *function = inst; + CPPFunctionType *ftype = function->_type->resolve_type(&parser, &parser)->as_function_type(); + if (ftype->_vis <= min_vis) + return true; + } + else + { + if (inst->_vis <= min_vis) + return true; + } + + } + else if (base_type->get_subtype() == CPPDeclaration::ST_typedef) + { + CPPTypedef *tdef = base_type->as_typedef(); + if (tdef->_type->get_subtype() == CPPDeclaration::ST_struct) + { + CPPStructType *struct_type =tdef->_type->resolve_type(&parser, &parser)->as_struct_type(); + return IsExported(struct_type); + } + + } + else if (base_type->get_subtype() == CPPDeclaration::ST_type_declaration) + { + CPPType *type = base_type->as_type_declaration()->_type; + if (type->get_subtype() == CPPDeclaration::ST_struct) + { + CPPStructType *struct_type =type->as_type()->resolve_type(&parser, &parser)->as_struct_type(); + CPPScope *scope = struct_type->_scope; + return IsExported(struct_type); + + } + else if (type->get_subtype() == CPPDeclaration::ST_enum) + { + CPPEnumType *enum_type = type->as_type()->resolve_type(&parser, &parser)->as_enum_type(); + if (type->_vis <= min_vis) + return true; + } + } + + +// printf("---------------------> Visibility Failed %s %d Vis=%d, Minvis=%d\n", +// base_type->get_fully_scoped_name().c_str(), +// base_type->get_subtype(), +// base_type->_vis, +// min_vis); + + return false; +}; + +bool TypeManager::IsLocal(CPPType *in_type) +{ + // A local means it was compiled in this scope of work.. + // IE a should actualy generate code for this objects.... + CPPType *base_type = resolve_type(unwrap(in_type)); + + + if(base_type->_file._source == CPPFile::S_local) + return true; + + return false; + + + if (base_type->get_subtype() == CPPDeclaration::ST_struct) + { + CPPStructType *struct_type = base_type->as_struct_type(); + if (struct_type->_file._source == CPPFile::S_local) + return true; + + } + else if (base_type->get_subtype() == CPPDeclaration::ST_instance) + { + CPPInstance *inst = base_type->as_instance(); + if (inst->_type->get_subtype() == CPPDeclaration::ST_function) + { + CPPInstance *function = inst; + CPPFunctionType *ftype = function->_type->resolve_type(&parser, &parser)->as_function_type(); + if (ftype->_file._source == CPPFile::S_local) + return true; + } + else + { + if (inst->_file._source == CPPFile::S_local) + return true; + } + } + else if (base_type->get_subtype() == CPPDeclaration::ST_typedef) + { + CPPTypedef *tdef = base_type->as_typedef(); + if (tdef->_type->get_subtype() == CPPDeclaration::ST_struct) + { + CPPStructType *struct_type =tdef->_type->resolve_type(&parser, &parser)->as_struct_type(); + return IsLocal(struct_type); + + + } + } + else if (base_type->get_subtype() == CPPDeclaration::ST_type_declaration) + { + CPPType *type = base_type->as_type_declaration()->_type; + if (type->get_subtype() == CPPDeclaration::ST_struct) + { + CPPStructType *struct_type =type->as_type()->resolve_type(&parser, &parser)->as_struct_type(); + if (struct_type->_file._source == CPPFile::S_local) + return true; + + } + else if (type->get_subtype() == CPPDeclaration::ST_enum) + { + CPPEnumType *enum_type = type->as_type()->resolve_type(&parser, &parser)->as_enum_type(); + if (enum_type->_file._source != CPPFile::S_local) + return true; + } + } + + if (base_type->_file._source == CPPFile::S_local) + return true; + + return false; +}; diff --git a/dtool/src/interrogate/typeManager.h b/dtool/src/interrogate/typeManager.h index ecdc303c41..d02023b120 100644 --- a/dtool/src/interrogate/typeManager.h +++ b/dtool/src/interrogate/typeManager.h @@ -84,6 +84,9 @@ public: static bool involves_unpublished(CPPType *type); static bool involves_protected(CPPType *type); + static bool is_ostream(CPPType *type); + static bool is_pointer_to_ostream(CPPType *type); + static CPPType *unwrap_pointer(CPPType *type); static CPPType *unwrap_reference(CPPType *type); static CPPType *unwrap_const(CPPType *type); @@ -107,6 +110,11 @@ public: static string get_function_name(CPPInstance *function); static bool has_protected_destructor(CPPType *type); + + + static bool IsExported(CPPType *type); + static bool IsLocal(CPPType *type); + }; #endif diff --git a/dtool/src/interrogatedb/Sources.pp b/dtool/src/interrogatedb/Sources.pp index bf3ecdeb8a..499dd9e0d7 100644 --- a/dtool/src/interrogatedb/Sources.pp +++ b/dtool/src/interrogatedb/Sources.pp @@ -27,6 +27,6 @@ #define INSTALL_HEADERS \ interrogate_interface.h interrogate_request.h vector_int.h \ - config_interrogatedb.h + config_interrogatedb.h py_panda.h #end lib_target diff --git a/dtool/src/interrogatedb/config_interrogatedb.h b/dtool/src/interrogatedb/config_interrogatedb.h index 02db51090e..e500951781 100644 --- a/dtool/src/interrogatedb/config_interrogatedb.h +++ b/dtool/src/interrogatedb/config_interrogatedb.h @@ -5,7 +5,7 @@ // // PANDA 3D SOFTWARE // Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// +//O // 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 diff --git a/dtool/src/interrogatedb/interrogateFunction.h b/dtool/src/interrogatedb/interrogateFunction.h index 3a86f4f58c..55fd07e281 100644 --- a/dtool/src/interrogatedb/interrogateFunction.h +++ b/dtool/src/interrogatedb/interrogateFunction.h @@ -101,6 +101,7 @@ public: friend class InterrogateBuilder; friend class InterfaceMakerC; friend class InterfaceMakerPythonSimple; + friend class InterfaceMakerPythonNative; friend class FunctionRemap; }; diff --git a/dtool/src/interrogatedb/interrogateType.cxx b/dtool/src/interrogatedb/interrogateType.cxx index e1138fc8a7..952f640f47 100644 --- a/dtool/src/interrogatedb/interrogateType.cxx +++ b/dtool/src/interrogatedb/interrogateType.cxx @@ -224,3 +224,17 @@ remap_indices(const IndexRemapper &remap) { } } + +EXPCL_DTOOLCONFIG RunTimeTypeDictionary & GetRunTimeDictionary() +{ + static RunTimeTypeDictionary dict; + return dict; +}; + + +EXPCL_DTOOLCONFIG RunTimeTypeList & GetRunTimeTypeList() +{ + static RunTimeTypeList list; + return list; +}; + diff --git a/dtool/src/interrogatedb/interrogateType.h b/dtool/src/interrogatedb/interrogateType.h index c1d34d897f..f964664966 100644 --- a/dtool/src/interrogatedb/interrogateType.h +++ b/dtool/src/interrogatedb/interrogateType.h @@ -135,7 +135,9 @@ private: F_unpublished = 0x100000, }; +public: int _flags; + string _scoped_name; string _true_name; string _comment; @@ -221,4 +223,14 @@ INLINE istream &operator >> (istream &in, InterrogateType::EnumValue &d); #include "interrogateType.I" +#include +#include +struct Dtool_PyTypedObject; +typedef std::map< int , Dtool_PyTypedObject *> RunTimeTypeDictionary; +typedef std::set RunTimeTypeList; + +extern "C" EXPCL_DTOOL RunTimeTypeDictionary & GetRunTimeDictionary(); +extern "C" EXPCL_DTOOL RunTimeTypeList & GetRunTimeTypeList(); + + #endif diff --git a/dtool/src/interrogatedb/interrogate_interface.cxx b/dtool/src/interrogatedb/interrogate_interface.cxx index 7b2c3f17da..ccd6064019 100644 --- a/dtool/src/interrogatedb/interrogate_interface.cxx +++ b/dtool/src/interrogatedb/interrogate_interface.cxx @@ -217,6 +217,18 @@ interrogate_function_module_name(FunctionIndex function) { return InterrogateDatabase::get_ptr()->get_function(function).get_module_name(); } +bool +interrogate_function_has_library_name(FunctionIndex function) { + return InterrogateDatabase::get_ptr()->get_function(function).has_library_name(); +} + +const char * +interrogate_function_library_name(FunctionIndex function) { + return InterrogateDatabase::get_ptr()->get_function(function).get_library_name(); +} + + + bool interrogate_function_is_virtual(FunctionIndex function) { return InterrogateDatabase::get_ptr()->get_function(function).is_virtual(); @@ -401,6 +413,17 @@ interrogate_type_module_name(TypeIndex type) { return InterrogateDatabase::get_ptr()->get_type(type).get_module_name(); } +bool +interrogate_type_has_library_name(TypeIndex type) { + return InterrogateDatabase::get_ptr()->get_type(type).has_library_name(); +} + +const char * +interrogate_type_library_name(TypeIndex type) { + return InterrogateDatabase::get_ptr()->get_type(type).get_library_name(); +} + + bool interrogate_type_is_atomic(TypeIndex type) { return InterrogateDatabase::get_ptr()->get_type(type).is_atomic(); diff --git a/dtool/src/interrogatedb/interrogate_interface.h b/dtool/src/interrogatedb/interrogate_interface.h index 8bd78d977d..7ea6c43361 100644 --- a/dtool/src/interrogatedb/interrogate_interface.h +++ b/dtool/src/interrogatedb/interrogate_interface.h @@ -229,6 +229,11 @@ EXPCL_DTOOLCONFIG TypeIndex interrogate_function_class(FunctionIndex function); EXPCL_DTOOLCONFIG bool interrogate_function_has_module_name(FunctionIndex function); EXPCL_DTOOLCONFIG const char *interrogate_function_module_name(FunctionIndex function); +// This returns the library name reported for the function, if +// available. +EXPCL_DTOOLCONFIG bool interrogate_function_has_library_name(FunctionIndex function); +EXPCL_DTOOLCONFIG const char *interrogate_function_library_name(FunctionIndex function); + // This is true for virtual member functions. It's not likely that // this will be important to the scripting language. EXPCL_DTOOLCONFIG bool interrogate_function_is_virtual(FunctionIndex function); @@ -388,6 +393,11 @@ EXPCL_DTOOLCONFIG const char *interrogate_type_comment(TypeIndex type); EXPCL_DTOOLCONFIG bool interrogate_type_has_module_name(TypeIndex type); EXPCL_DTOOLCONFIG const char *interrogate_type_module_name(TypeIndex type); +// This returns the library name reported for the type, if available. +EXPCL_DTOOLCONFIG bool interrogate_type_has_library_name(TypeIndex type); +EXPCL_DTOOLCONFIG const char *interrogate_type_library_name(TypeIndex type); + + // If interrogate_type_is_atomic() returns true, the type is one of // the basic C types enumerated in AtomicToken, above. The type may // then be further modified by one or more of unsigned, signed, long, diff --git a/panda/metalibs/panda/Sources.pp b/panda/metalibs/panda/Sources.pp index a246914ae5..3f229761df 100644 --- a/panda/metalibs/panda/Sources.pp +++ b/panda/metalibs/panda/Sources.pp @@ -22,6 +22,7 @@ #define LOCAL_LIBS \ downloader express pandabase #define OTHER_LIBS \ + pandaexpress:m \ interrogatedb:c dconfig:c dtoolconfig:m \ dtoolutil:c dtoolbase:c dtool:m diff --git a/panda/src/express/buffer.h b/panda/src/express/buffer.h index 615b5fe5aa..96cb9a6a97 100644 --- a/panda/src/express/buffer.h +++ b/panda/src/express/buffer.h @@ -32,6 +32,7 @@ public: Buffer(int size); ~Buffer(); +PUBLISHED: INLINE int get_length(void) const; #ifndef CPPPARSER diff --git a/panda/src/express/config_express.N b/panda/src/express/config_express.N index c40d9cae39..9521bab077 100644 --- a/panda/src/express/config_express.N +++ b/panda/src/express/config_express.N @@ -1,5 +1,6 @@ forcetype PandaSystem forcetype DSearchPath +forcetype DSearchPath::Results forcetype Filename forcetype GlobPattern forcetype Notify diff --git a/panda/src/express/patchfile.h b/panda/src/express/patchfile.h index 5f32e3f0eb..9b0576a3be 100644 --- a/panda/src/express/patchfile.h +++ b/panda/src/express/patchfile.h @@ -34,6 +34,7 @@ #include + //////////////////////////////////////////////////////////////////// // Class : Patchfile // Description : diff --git a/panda/src/express/pointerToArray.h b/panda/src/express/pointerToArray.h index d977c3cc99..929a79f60a 100644 --- a/panda/src/express/pointerToArray.h +++ b/panda/src/express/pointerToArray.h @@ -51,7 +51,7 @@ // Note that in the above example, unlike an STL vector (but like a // C-style array), assigning a PointerToArray object from another // simply copies the pointer, and does not copy individual elements. -// (Of course, reference counts are adjusted appropriately.) If you +// (Of course, reference counts are adjusted appropriately7.) If you // actually wanted an element-by-element copy of the array, you would // do this: // diff --git a/panda/src/express/typeHandle.I b/panda/src/express/typeHandle.I index 8484a09b78..d28687d877 100644 --- a/panda/src/express/typeHandle.I +++ b/panda/src/express/typeHandle.I @@ -284,3 +284,23 @@ none() { return _none; } +//////////////////////////////////////////////////////////////////// +// Function: get_best_parent_from_Set +// Access: Published +// Description: Return the Index of the BEst fit Classs from a set +//////////////////////////////////////////////////////////////////// +INLINE int TypeHandle::get_best_parent_from_Set(const std::set< int > &legal_vals) const +{ + if(legal_vals.find(_index) != legal_vals.end()) + return _index; + + for(int pi = 0; pi < get_num_parent_classes() ; pi++) + { + TypeHandle ph = get_parent_class(pi); + int val = ph.get_best_parent_from_Set(legal_vals); + if(val > 0) + return val; + + } + return -1; +} \ No newline at end of file diff --git a/panda/src/express/typeHandle.h b/panda/src/express/typeHandle.h index 9ba440212a..750a29a5e4 100644 --- a/panda/src/express/typeHandle.h +++ b/panda/src/express/typeHandle.h @@ -25,6 +25,8 @@ #include "config_express.h" +#include "set" + // The following illustrates the convention for declaring a type that // uses TypeHandle. In this example, ThisThingie inherits from // TypedObject, which automatically supplies some type-differentiation @@ -114,6 +116,8 @@ PUBLISHED: INLINE TypeHandle get_parent_towards(TypeHandle ancestor, TypedObject *object = (TypedObject *)NULL) const; + + INLINE int get_best_parent_from_Set(const std::set< int > &legal_vals) const; INLINE int get_index() const; INLINE void output(ostream &out) const; diff --git a/panda/src/express/typeRegistry.cxx b/panda/src/express/typeRegistry.cxx index 0216fcdf2d..6dc254abe7 100644 --- a/panda/src/express/typeRegistry.cxx +++ b/panda/src/express/typeRegistry.cxx @@ -615,5 +615,42 @@ look_up(TypeHandle handle, TypedObject *object) const { return _handle_registry[handle._index]; } + +//////////////////////////////////////////////////////////////////// +// Function: find_type_by_id +// Access: Private +/////////////////////////////////////////////////////////////////// +TypeHandle TypeRegistry::find_type_by_id(int id) const +{ + if (id < 0 ||id >= (int)_handle_registry.size()) + { + express_cat->fatal() + << "Invalid TypeHandle index " << id + << "! Is memory corrupt?\n"; + //nassertr(false, NULL); + return TypeHandle::none(); + } + + return _handle_registry[id]->_handle; +}; + +//////////////////////////////////////////////////////////////////// +// Function: get_best_parent_from_Set +// Access: Private +/////////////////////////////////////////////////////////////////// +extern "C" int get_best_parent_from_Set(int id, const std::set &set) +{ + // most common case.. + if(set.find(id) != set.end()) + return id; + + TypeHandle th = TypeRegistry::ptr()->find_type_by_id(id); + if(th == TypeHandle::none()) + return -1; + + return th.get_best_parent_from_Set(set); +} + + #endif // NDEBUG diff --git a/panda/src/express/typeRegistry.h b/panda/src/express/typeRegistry.h index 1cc6ca71a1..a763dca08e 100644 --- a/panda/src/express/typeRegistry.h +++ b/panda/src/express/typeRegistry.h @@ -48,10 +48,12 @@ public: void record_derivation(TypeHandle child, TypeHandle parent); void record_alternate_name(TypeHandle type, const string &name); + TypeHandle find_type_by_id(int id) const; PUBLISHED: TypeHandle find_type(const string &name) const; + string get_name(TypeHandle type, TypedObject *object) const; INLINE bool is_derived_from(TypeHandle child, TypeHandle base, TypedObject *child_object); @@ -111,6 +113,10 @@ private: static TypeRegistry *_global_pointer; }; +/////////////////////////////////////////// +// Helper function to allow for "C" interaction into the type system +extern "C" EXPCL_PANDAEXPRESS int get_best_parent_from_Set(int id, const std::set &set); + #include "typeRegistry.I" #endif diff --git a/panda/src/express/typedObject.I b/panda/src/express/typedObject.I index b88679287c..8b8ae08adc 100644 --- a/panda/src/express/typedObject.I +++ b/panda/src/express/typedObject.I @@ -82,3 +82,15 @@ is_exact_type(TypeHandle handle) const { #endif return get_type() == handle; } + +//////////////////////////////////////////////////////////////////// +// Function: TypedObject::is_exact_type +// Access: Public +// Description: Returns true if the current object is the indicated +// type exactly. +//////////////////////////////////////////////////////////////////// +INLINE int TypedObject:: +get_best_parent_from_Set(const std::set &inset) const +{ + return get_type().get_best_parent_from_Set(inset); +} diff --git a/panda/src/express/typedObject.h b/panda/src/express/typedObject.h index f5ed7731ac..08630da28f 100644 --- a/panda/src/express/typedObject.h +++ b/panda/src/express/typedObject.h @@ -24,6 +24,7 @@ #include "typeHandle.h" #include "register_type.h" +#include "set" //////////////////////////////////////////////////////////////////// // Class : TypedObject @@ -120,6 +121,7 @@ PUBLISHED: INLINE int get_type_index() const; INLINE bool is_of_type(TypeHandle handle) const; INLINE bool is_exact_type(TypeHandle handle) const; + INLINE int get_best_parent_from_Set(const std::set &) const; public: // Derived classes should override this function to call diff --git a/panda/src/express/virtualFile.h b/panda/src/express/virtualFile.h index 972f399629..83c47140f5 100644 --- a/panda/src/express/virtualFile.h +++ b/panda/src/express/virtualFile.h @@ -30,6 +30,7 @@ class VirtualFileMount; class VirtualFileList; class VirtualFileSystem; + //////////////////////////////////////////////////////////////////// // Class : VirtualFile // Description : The abstract base class for a file or directory @@ -93,6 +94,7 @@ private: INLINE ostream &operator << (ostream &out, const VirtualFile &file); + #include "virtualFile.I" #endif diff --git a/panda/src/express/virtualFileList.h b/panda/src/express/virtualFileList.h index b87f5fa9e5..2c53365517 100644 --- a/panda/src/express/virtualFileList.h +++ b/panda/src/express/virtualFileList.h @@ -48,6 +48,7 @@ private: Files _files; }; + #include "virtualFileList.I" #endif diff --git a/panda/src/linmath/luse.N b/panda/src/linmath/luse.N index f51d30262f..9e1f4a10b3 100644 --- a/panda/src/linmath/luse.N +++ b/panda/src/linmath/luse.N @@ -1,4 +1,11 @@ +forcetype PointerToBase< RefCountObj< pvector>> +forcetype PointerToBase< RefCountObj< pvector>> + +forcetype PointerToBase< RefCountObj< pvector>> + +forcetype PointerToBase< RefCountObj< pvector>> + renametype LPoint2f LPoint2f renametype LPoint3f LPoint3f renametype LPoint4f LPoint4f diff --git a/panda/src/net/connectionManager.N b/panda/src/net/connectionManager.N index 6842b1753f..0ae2ba471b 100644 --- a/panda/src/net/connectionManager.N +++ b/panda/src/net/connectionManager.N @@ -1 +1,2 @@ forcetype PointerTo +forcetype PointerToBase diff --git a/panda/src/physics/angularIntegrator.h b/panda/src/physics/angularIntegrator.h index cb8f4c27f6..d9dc0918b3 100644 --- a/panda/src/physics/angularIntegrator.h +++ b/panda/src/physics/angularIntegrator.h @@ -30,8 +30,9 @@ // forces to them. //////////////////////////////////////////////////////////////////// class EXPCL_PANDAPHYSICS AngularIntegrator : public BaseIntegrator { -public: +PUBLISHED: virtual ~AngularIntegrator(); +public: void integrate(Physical *physical, AngularForceVector &forces, float dt); diff --git a/panda/src/physics/linearIntegrator.h b/panda/src/physics/linearIntegrator.h index 09c371fdd3..315e9463bb 100644 --- a/panda/src/physics/linearIntegrator.h +++ b/panda/src/physics/linearIntegrator.h @@ -31,8 +31,9 @@ // forces to them. //////////////////////////////////////////////////////////////////// class EXPCL_PANDAPHYSICS LinearIntegrator : public BaseIntegrator { -public: +PUBLISHED: virtual ~LinearIntegrator(); +public: void integrate(Physical *physical, LinearForceVector &forces, float dt); diff --git a/panda/src/putil/pta_int.h b/panda/src/putil/pta_int.h index 3cf018b0fe..adc11683b4 100644 --- a/panda/src/putil/pta_int.h +++ b/panda/src/putil/pta_int.h @@ -38,8 +38,10 @@ EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToBase) EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, ConstPointerToArray) +BEGIN_PUBLISH typedef PointerToArray PTA_int; typedef ConstPointerToArray CPTA_int; +END_PUBLISH // Tell GCC that we'll take care of the instantiation explicitly here. #ifdef __GNUC__