diff --git a/doc/man/interrogate_module.1 b/doc/man/interrogate_module.1 index 289c65d691..039266094d 100644 --- a/doc/man/interrogate_module.1 +++ b/doc/man/interrogate_module.1 @@ -1,4 +1,4 @@ -.TH INTERROGATE_MODULE 1 "26 December 2014" "" Panda3D +.TH INTERROGATE_MODULE 1 "02 June 2015" "" Panda3D .SH NAME interrogate_module \- generate module-level code for interrogate .SH SYNOPSIS @@ -64,6 +64,9 @@ may be specified. If all are omitted, the default is \fB\-c\fP. Generate code within each wrapper function to adjust the global variable "in_interpreter" to indicated whether code is running within the Panda C++ environment or within the high-level language. +.TP +.BI "\-import " module_name +Used to import an external dependency module. .SH "SEE ALSO" .BR interrogate (1), .BR test_interrogate (1) diff --git a/dtool/src/cppparser/cppArrayType.cxx b/dtool/src/cppparser/cppArrayType.cxx index 44714cc9bd..4b044fb766 100644 --- a/dtool/src/cppparser/cppArrayType.cxx +++ b/dtool/src/cppparser/cppArrayType.cxx @@ -76,6 +76,17 @@ is_tbd() const { return _element_type->is_tbd(); } +//////////////////////////////////////////////////////////////////// +// Function: CPPArrayType::is_trivial +// Access: Public, Virtual +// Description: Returns true if the type is considered a Plain Old +// Data (POD) type. +//////////////////////////////////////////////////////////////////// +bool CPPArrayType:: +is_trivial() const { + return _element_type->is_trivial(); +} + //////////////////////////////////////////////////////////////////// // Function: CPPArrayType::is_equivalent // Access: Public, Virtual diff --git a/dtool/src/cppparser/cppArrayType.h b/dtool/src/cppparser/cppArrayType.h index 335759c105..82a369a90e 100644 --- a/dtool/src/cppparser/cppArrayType.h +++ b/dtool/src/cppparser/cppArrayType.h @@ -40,6 +40,7 @@ public: virtual CPPType *resolve_type(CPPScope *current_scope, CPPScope *global_scope); virtual bool is_tbd() const; + virtual bool is_trivial() const; virtual bool is_equivalent(const CPPType &other) const; virtual void output(ostream &out, int indent_level, CPPScope *scope, diff --git a/dtool/src/cppparser/cppConstType.cxx b/dtool/src/cppparser/cppConstType.cxx index bf663b436c..503f1c0871 100644 --- a/dtool/src/cppparser/cppConstType.cxx +++ b/dtool/src/cppparser/cppConstType.cxx @@ -101,6 +101,17 @@ is_tbd() const { return _wrapped_around->is_tbd(); } +//////////////////////////////////////////////////////////////////// +// Function: CPPConstType::is_trivial +// Access: Public, Virtual +// Description: Returns true if the type is considered a Plain Old +// Data (POD) type. +//////////////////////////////////////////////////////////////////// +bool CPPConstType:: +is_trivial() const { + return _wrapped_around->is_trivial(); +} + //////////////////////////////////////////////////////////////////// // Function: CPPConstType::is_equivalent // Access: Public, Virtual diff --git a/dtool/src/cppparser/cppConstType.h b/dtool/src/cppparser/cppConstType.h index 2d6c552e1d..499b403a6e 100644 --- a/dtool/src/cppparser/cppConstType.h +++ b/dtool/src/cppparser/cppConstType.h @@ -38,6 +38,7 @@ public: CPPScope *global_scope); virtual bool is_tbd() const; + virtual bool is_trivial() const; virtual bool is_equivalent(const CPPType &other) const; virtual void output(ostream &out, int indent_level, CPPScope *scope, diff --git a/dtool/src/cppparser/cppExtensionType.cxx b/dtool/src/cppparser/cppExtensionType.cxx index 26022cf8bf..3056b8b6d4 100644 --- a/dtool/src/cppparser/cppExtensionType.cxx +++ b/dtool/src/cppparser/cppExtensionType.cxx @@ -102,6 +102,17 @@ is_tbd() const { return false; } +//////////////////////////////////////////////////////////////////// +// Function: CPPExtensionType::is_trivial +// Access: Public, Virtual +// Description: Returns true if the type is considered a Plain Old +// Data (POD) type. +//////////////////////////////////////////////////////////////////// +bool CPPExtensionType:: +is_trivial() const { + return (_type == T_enum); +} + //////////////////////////////////////////////////////////////////// // Function: CPPExtensionType::substitute_decl // Access: Public, Virtual diff --git a/dtool/src/cppparser/cppExtensionType.h b/dtool/src/cppparser/cppExtensionType.h index d1d810209c..d4201dc4e2 100644 --- a/dtool/src/cppparser/cppExtensionType.h +++ b/dtool/src/cppparser/cppExtensionType.h @@ -47,6 +47,7 @@ public: virtual bool is_incomplete() const; virtual bool is_tbd() const; + virtual bool is_trivial() const; virtual CPPDeclaration *substitute_decl(SubstDecl &subst, CPPScope *current_scope, diff --git a/dtool/src/cppparser/cppFunctionType.cxx b/dtool/src/cppparser/cppFunctionType.cxx index 515729cf39..fa8cf3f291 100644 --- a/dtool/src/cppparser/cppFunctionType.cxx +++ b/dtool/src/cppparser/cppFunctionType.cxx @@ -159,6 +159,17 @@ is_tbd() const { return _parameters->is_tbd(); } +//////////////////////////////////////////////////////////////////// +// Function: CPPFunctionType::is_trivial +// Access: Public, Virtual +// Description: Returns true if the type is considered a Plain Old +// Data (POD) type. +//////////////////////////////////////////////////////////////////// +bool CPPFunctionType:: +is_trivial() const { + return false; +} + //////////////////////////////////////////////////////////////////// // Function: CPPFunctionType::output // Access: Public, Virtual diff --git a/dtool/src/cppparser/cppFunctionType.h b/dtool/src/cppparser/cppFunctionType.h index b728fa7b22..37360a80a7 100644 --- a/dtool/src/cppparser/cppFunctionType.h +++ b/dtool/src/cppparser/cppFunctionType.h @@ -29,14 +29,16 @@ class CPPIdentifier; class CPPFunctionType : public CPPType { public: enum Flags { - F_const_method = 0x01, - F_operator_typecast = 0x02, - F_constructor = 0x04, - F_destructor = 0x08, - F_method_pointer = 0x10, - F_unary_op = 0x20, - F_operator = 0x40, - F_noexcept = 0x80, + F_const_method = 0x001, + F_operator_typecast = 0x002, + F_constructor = 0x004, + F_destructor = 0x008, + F_method_pointer = 0x010, + F_unary_op = 0x020, + F_operator = 0x040, + F_noexcept = 0x080, + F_copy_constructor = 0x200, + F_move_constructor = 0x400, }; CPPFunctionType(CPPType *return_type, CPPParameterList *parameters, @@ -57,6 +59,7 @@ public: CPPScope *global_scope); virtual bool is_tbd() const; + virtual bool is_trivial() const; virtual void output(ostream &out, int indent_level, CPPScope *scope, bool complete) const; diff --git a/dtool/src/cppparser/cppInstance.cxx b/dtool/src/cppparser/cppInstance.cxx index 94b0924460..32790e0cde 100644 --- a/dtool/src/cppparser/cppInstance.cxx +++ b/dtool/src/cppparser/cppInstance.cxx @@ -347,9 +347,33 @@ check_for_constructor(CPPScope *current_scope, CPPScope *global_scope) { CPPType *void_type = CPPType::new_type (new CPPSimpleType(CPPSimpleType::T_void)); + int flags = func->_flags | CPPFunctionType::F_constructor; + + // Check if it might be a copy or move constructor. + CPPParameterList *params = func->_parameters; + if (params->_parameters.size() == 1 && !params->_includes_ellipsis) { + CPPType *param_type = params->_parameters[0]->_type; + CPPReferenceType *ref_type = param_type->as_reference_type(); + + if (ref_type != NULL) { + param_type = ref_type->_pointing_at; + + if (param_type->get_subtype() == CPPDeclaration::ST_const) { + param_type = param_type->as_const_type()->_wrapped_around; + } + + if (class_name == param_type->get_simple_name()) { + if (ref_type->_value_category == CPPReferenceType::VC_rvalue) { + flags |= CPPFunctionType::F_move_constructor; + } else { + flags |= CPPFunctionType::F_copy_constructor; + } + } + } + } + _type = CPPType::new_type - (new CPPFunctionType(void_type, func->_parameters, - func->_flags | CPPFunctionType::F_constructor)); + (new CPPFunctionType(void_type, func->_parameters, flags)); } else if (method_name == "~" + class_name) { CPPType *void_type = CPPType::new_type diff --git a/dtool/src/cppparser/cppInstanceIdentifier.cxx b/dtool/src/cppparser/cppInstanceIdentifier.cxx index 7cd3c67283..45379e5f70 100644 --- a/dtool/src/cppparser/cppInstanceIdentifier.cxx +++ b/dtool/src/cppparser/cppInstanceIdentifier.cxx @@ -166,7 +166,16 @@ add_scoped_pointer_modifier(CPPIdentifier *scoping) { //////////////////////////////////////////////////////////////////// void CPPInstanceIdentifier:: add_array_modifier(CPPExpression *expr) { - _modifiers.push_back(Modifier::array_type(expr)); + // Special case for operator new[] and delete[]. We're not really + // adding an array modifier to them, but appending [] to the + // identifier. This is to work around a parser ambiguity. + if (_ident != NULL && (_ident->get_simple_name() == "operator delete" || + _ident->get_simple_name() == "operator new")) { + + _ident->_names.back().append_name("[]"); + } else { + _modifiers.push_back(Modifier::array_type(expr)); + } } //////////////////////////////////////////////////////////////////// diff --git a/dtool/src/cppparser/cppPointerType.cxx b/dtool/src/cppparser/cppPointerType.cxx index 22dd91b268..baa8a62ff8 100644 --- a/dtool/src/cppparser/cppPointerType.cxx +++ b/dtool/src/cppparser/cppPointerType.cxx @@ -103,6 +103,17 @@ is_tbd() const { return _pointing_at->is_tbd(); } +//////////////////////////////////////////////////////////////////// +// Function: CPPPointerType::is_trivial +// Access: Public, Virtual +// Description: Returns true if the type is considered a Plain Old +// Data (POD) type. +//////////////////////////////////////////////////////////////////// +bool CPPPointerType:: +is_trivial() const { + return true; +} + //////////////////////////////////////////////////////////////////// // Function: CPPPointerType::is_equivalent // Access: Public, Virtual diff --git a/dtool/src/cppparser/cppPointerType.h b/dtool/src/cppparser/cppPointerType.h index 6a7349343f..6f9c2b1b75 100644 --- a/dtool/src/cppparser/cppPointerType.h +++ b/dtool/src/cppparser/cppPointerType.h @@ -38,6 +38,7 @@ public: CPPScope *global_scope); virtual bool is_tbd() const; + virtual bool is_trivial() const; virtual bool is_equivalent(const CPPType &other) const; virtual void output(ostream &out, int indent_level, CPPScope *scope, diff --git a/dtool/src/cppparser/cppReferenceType.cxx b/dtool/src/cppparser/cppReferenceType.cxx index 40d6e987da..5b5d85fd3b 100644 --- a/dtool/src/cppparser/cppReferenceType.cxx +++ b/dtool/src/cppparser/cppReferenceType.cxx @@ -102,6 +102,17 @@ is_tbd() const { return _pointing_at->is_tbd(); } +//////////////////////////////////////////////////////////////////// +// Function: CPPReferenceType::is_trivial +// Access: Public, Virtual +// Description: Returns true if the type is considered a Plain Old +// Data (POD) type. +//////////////////////////////////////////////////////////////////// +bool CPPReferenceType:: +is_trivial() const { + return false; +} + //////////////////////////////////////////////////////////////////// // Function: CPPReferenceType::is_equivalent // Access: Public, Virtual diff --git a/dtool/src/cppparser/cppReferenceType.h b/dtool/src/cppparser/cppReferenceType.h index 3bf292841e..713a6abd6c 100644 --- a/dtool/src/cppparser/cppReferenceType.h +++ b/dtool/src/cppparser/cppReferenceType.h @@ -35,9 +35,6 @@ public: CPPType *_pointing_at; ValueCategory _value_category; - inline bool is_lvalue() const; - inline bool is_rvalue() const; - virtual bool is_fully_specified() const; virtual CPPDeclaration *substitute_decl(SubstDecl &subst, CPPScope *current_scope, @@ -47,6 +44,7 @@ public: CPPScope *global_scope); virtual bool is_tbd() const; + virtual bool is_trivial() const; virtual bool is_equivalent(const CPPType &other) const; virtual void output(ostream &out, int indent_level, CPPScope *scope, diff --git a/dtool/src/cppparser/cppSimpleType.cxx b/dtool/src/cppparser/cppSimpleType.cxx index 7ce7048848..ac4e633d6d 100644 --- a/dtool/src/cppparser/cppSimpleType.cxx +++ b/dtool/src/cppparser/cppSimpleType.cxx @@ -40,6 +40,17 @@ is_tbd() const { return (_type == T_unknown); } +//////////////////////////////////////////////////////////////////// +// Function: CPPSimpleType::is_trivial +// Access: Public, Virtual +// Description: Returns true if the type is considered a Plain Old +// Data (POD) type. +//////////////////////////////////////////////////////////////////// +bool CPPSimpleType:: +is_trivial() const { + return true; +} + //////////////////////////////////////////////////////////////////// // Function: CPPSimpleType::is_parameter_expr // Access: Public, Virtual diff --git a/dtool/src/cppparser/cppSimpleType.h b/dtool/src/cppparser/cppSimpleType.h index 6ac032456b..27a1b89206 100644 --- a/dtool/src/cppparser/cppSimpleType.h +++ b/dtool/src/cppparser/cppSimpleType.h @@ -66,6 +66,7 @@ public: int _flags; virtual bool is_tbd() const; + virtual bool is_trivial() const; virtual bool is_parameter_expr() const; virtual string get_preferred_name() const; diff --git a/dtool/src/cppparser/cppStructType.cxx b/dtool/src/cppparser/cppStructType.cxx index 0c138f586d..42dfed1d7b 100644 --- a/dtool/src/cppparser/cppStructType.cxx +++ b/dtool/src/cppparser/cppStructType.cxx @@ -131,6 +131,97 @@ is_abstract() const { return !funcs.empty(); } +//////////////////////////////////////////////////////////////////// +// Function: CPPStructType::is_trivial +// Access: Public, Virtual +// Description: Returns true if the type is considered a Plain Old +// Data (POD) type. +//////////////////////////////////////////////////////////////////// +bool CPPStructType:: +is_trivial() const { + // Make sure all base classes are trivial. + Derivation::const_iterator di; + for (di = _derivation.begin(); di != _derivation.end(); ++di) { + CPPStructType *base = (*di)._base->as_struct_type(); + if (base != NULL && !base->is_trivial()) { + return false; + } + } + + assert(_scope != NULL); + + // Make sure all members are trivial. + CPPScope::Variables::const_iterator vi; + for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) { + CPPInstance *instance = (*vi).second; + assert(instance != NULL); + + if (instance->_storage_class & CPPInstance::SC_static) { + // Static members don't count. + continue; + } + + if (instance->_initializer != NULL) { + // A member with an initializer means the default constructor would + // assign a value. This means the type can't be trivial. + return false; + } + + // Finally, check if the data member itself is non-trivial. + assert(instance->_type != NULL); + if (!instance->_type->is_trivial()) { + return false; + } + } + + // Now look for functions that are virtual or con/destructors. + bool is_default_constructible = true; + CPPScope::Functions::const_iterator fi; + for (fi = _scope->_functions.begin(); fi != _scope->_functions.end(); ++fi) { + CPPFunctionGroup *fgroup = (*fi).second; + + CPPFunctionGroup::Instances::const_iterator ii; + for (ii = fgroup->_instances.begin(); ii != fgroup->_instances.end(); ++ii) { + CPPInstance *inst = (*ii); + + if (inst->_storage_class & CPPInstance::SC_virtual) { + // Virtual functions are banned right off the bat. + return false; + } + + assert(inst->_type != (CPPType *)NULL); + CPPFunctionType *ftype = inst->_type->as_function_type(); + assert(ftype != (CPPFunctionType *)NULL); + + if (ftype->_flags & (CPPFunctionType::F_destructor | + CPPFunctionType::F_move_constructor | + CPPFunctionType::F_copy_constructor)) { + // User-provided destructors and copy/move constructors are not trivial. + return false; + } + + if ((ftype->_flags & CPPFunctionType::F_constructor) != 0) { + if (ftype->_parameters->_parameters.size() == 0 && + !ftype->_parameters->_includes_ellipsis) { + // Same for the default constructor. + return false; + } + // The presence of a non-default constructor makes the class not + // default-constructible. + is_default_constructible = false; + } + + if (fgroup->_name == "operator =") { + // Or assignment operators. + return false; + } + } + } + + // Finally, the class must be default-constructible. + return is_default_constructible; +} + //////////////////////////////////////////////////////////////////// // Function: CPPStructType::check_virtual // Access: Public diff --git a/dtool/src/cppparser/cppStructType.h b/dtool/src/cppparser/cppStructType.h index 1e0c74a02f..9a650320d2 100644 --- a/dtool/src/cppparser/cppStructType.h +++ b/dtool/src/cppparser/cppStructType.h @@ -47,6 +47,7 @@ public: bool check_virtual(); virtual bool is_fully_specified() const; virtual bool is_incomplete() const; + virtual bool is_trivial() const; CPPInstance *get_destructor() const; diff --git a/dtool/src/cppparser/cppType.cxx b/dtool/src/cppparser/cppType.cxx index bad935dba6..daceeb1d26 100644 --- a/dtool/src/cppparser/cppType.cxx +++ b/dtool/src/cppparser/cppType.cxx @@ -68,6 +68,17 @@ is_tbd() const { return false; } +//////////////////////////////////////////////////////////////////// +// Function: CPPType::is_trivial +// Access: Public, Virtual +// Description: Returns true if the type is considered a Plain Old +// Data (POD) type. +//////////////////////////////////////////////////////////////////// +bool CPPType:: +is_trivial() const { + return false; +} + //////////////////////////////////////////////////////////////////// // Function: CPPType::is_parameter_expr // Access: Public, Virtual diff --git a/dtool/src/cppparser/cppType.h b/dtool/src/cppparser/cppType.h index 1d962e8d69..824a71e3c4 100644 --- a/dtool/src/cppparser/cppType.h +++ b/dtool/src/cppparser/cppType.h @@ -48,6 +48,7 @@ public: CPPScope *global_scope); virtual bool is_tbd() const; + virtual bool is_trivial() const; virtual bool is_parameter_expr() const; bool has_typedef_name() const; diff --git a/dtool/src/cppparser/cppTypedefType.cxx b/dtool/src/cppparser/cppTypedefType.cxx index ceedd35f33..89924b3cc1 100644 --- a/dtool/src/cppparser/cppTypedefType.cxx +++ b/dtool/src/cppparser/cppTypedefType.cxx @@ -178,6 +178,17 @@ is_tbd() const { return _type->is_tbd(); } +//////////////////////////////////////////////////////////////////// +// Function: CPPTypedefType::is_trivial +// Access: Public, Virtual +// Description: Returns true if the type is considered a Plain Old +// Data (POD) type. +//////////////////////////////////////////////////////////////////// +bool CPPTypedefType:: +is_trivial() const { + return _type->is_trivial(); +} + //////////////////////////////////////////////////////////////////// // Function: CPPTypedefType::is_fully_specified // Access: Public, Virtual diff --git a/dtool/src/cppparser/cppTypedefType.h b/dtool/src/cppparser/cppTypedefType.h index ad6c33ffa2..030da91c18 100644 --- a/dtool/src/cppparser/cppTypedefType.h +++ b/dtool/src/cppparser/cppTypedefType.h @@ -42,6 +42,7 @@ public: virtual bool is_incomplete() const; virtual bool is_tbd() const; + virtual bool is_trivial() const; virtual bool is_fully_specified() const; diff --git a/dtool/src/dtoolbase/typeHandle.I b/dtool/src/dtoolbase/typeHandle.I index 482d0996db..e489fd4099 100644 --- a/dtool/src/dtoolbase/typeHandle.I +++ b/dtool/src/dtoolbase/typeHandle.I @@ -13,28 +13,6 @@ //////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////// -// Function: TypeHandle::Constructor -// Access: Published -// Description: The default constructor must do nothing, because we -// can't guarantee ordering of static initializers. If -// the constructor tried to initialize its value, it -// might happen after the value had already been set -// previously by another static initializer! -//////////////////////////////////////////////////////////////////// -INLINE TypeHandle:: -TypeHandle() { -} - -//////////////////////////////////////////////////////////////////// -// Function: TypeHandle::Copy Constructor -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -INLINE TypeHandle:: -TypeHandle(const TypeHandle ©) : _index(copy._index) { -} - //////////////////////////////////////////////////////////////////// // Function: TypeHandle::Equality Operator // Access: Published diff --git a/dtool/src/dtoolbase/typeHandle.h b/dtool/src/dtoolbase/typeHandle.h index 9573cb2ffb..c669fa8084 100644 --- a/dtool/src/dtoolbase/typeHandle.h +++ b/dtool/src/dtoolbase/typeHandle.h @@ -94,8 +94,10 @@ PUBLISHED: // enum value. }; - INLINE TypeHandle(); - INLINE TypeHandle(const TypeHandle ©); + // The default constructor must do nothing, because we can't + // guarantee ordering of static initializers. If the constructor + // tried to initialize its value, it might happen after the value + // had already been set previously by another static initializer! EXTENSION(static TypeHandle make(PyTypeObject *classobj)); diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index b2f703c926..25a2848112 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/dtool/src/interrogate/functionRemap.cxx @@ -30,8 +30,6 @@ #include "interrogateType.h" #include "pnotify.h" -extern bool inside_python_native; - //////////////////////////////////////////////////////////////////// // Function: FunctionRemap::Constructor // Access: Public @@ -120,11 +118,7 @@ call_function(ostream &out, int indent_level, bool convert_result, InterfaceMaker::indent(out, indent_level) << "unref_delete(" << container << ");\n"; } else { - if (inside_python_native) { - InterfaceMaker::indent(out, indent_level) << "Dtool_Py_Delete(self);\n"; - } else { - InterfaceMaker::indent(out, indent_level) << "delete " << container << ";\n"; - } + InterfaceMaker::indent(out, indent_level) << "delete " << container << ";\n"; } } else if (_type == T_typecast_method) { @@ -866,13 +860,12 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak break; case T_constructor: - if (!_has_this && _parameters.size() == 1 && - TypeManager::unwrap(_parameters[0]._remap->get_orig_type()) == - TypeManager::unwrap(_return_type->get_orig_type())) { - // If this is the only parameter, and it's the same as the - // "this" type, this is a copy constructor. + if (_ftype->_flags & CPPFunctionType::F_copy_constructor) { + // It's a copy constructor. _flags |= F_copy_constructor; + } else if (_ftype->_flags & CPPFunctionType::F_move_constructor) { + } else if (!_has_this && _parameters.size() > 0 && (_cppfunc->_storage_class & CPPInstance::SC_explicit) == 0) { // A non-explicit non-copy constructor might be eligible for coercion. diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index db8a3e8e03..eda69928ff 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -40,7 +40,6 @@ #include #include -extern bool inside_python_native; extern InterrogateType dummy_type; extern std::string EXPORT_IMPORT_PREFIX; @@ -724,7 +723,7 @@ write_python_instance(ostream &out, int indent_level, const string &return_expr, out << boolalpha; if (!isExportThisRun(itype._cpptype)) { - _external_imports.insert(itype._cpptype); + _external_imports.insert(TypeManager::resolve_type(itype._cpptype)); } string class_name = itype.get_scoped_name(); @@ -743,7 +742,7 @@ write_python_instance(ostream &out, int indent_level, const string &return_expr, << "} else {\n"; indent(out, indent_level) << " return DTool_CreatePyInstanceTyped((void *)" << return_expr - << ", " << CLASS_PREFIX << make_safe_name(class_name) << ", " + << ", *Dtool_Ptr_" << make_safe_name(class_name) << ", " << owns_memory << ", " << is_const << ", " << return_expr << "->as_typed_object()->get_type_index());\n"; indent(out, indent_level) @@ -753,7 +752,7 @@ write_python_instance(ostream &out, int indent_level, const string &return_expr, indent(out, indent_level) << "return " << "DTool_CreatePyInstance((void *)" << return_expr << ", " - << CLASS_PREFIX << make_safe_name(class_name) << ", " + << "*Dtool_Ptr_" << make_safe_name(class_name) << ", " << owns_memory << ", " << is_const << ");\n"; } } @@ -787,8 +786,6 @@ InterfaceMakerPythonNative:: //////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative:: write_prototypes(ostream &out_code, ostream *out_h) { - inside_python_native = true; - Functions::iterator fi; if (out_h != NULL) { @@ -817,7 +814,7 @@ write_prototypes(ostream &out_code, ostream *out_h) { write_prototypes_class(out_code, out_h, object); } else { //write_prototypes_class_external(out_code, object); - _external_imports.insert(object->_itype._cpptype); + //_external_imports.insert(object->_itype._cpptype); } } } @@ -832,28 +829,62 @@ write_prototypes(ostream &out_code, ostream *out_h) { string class_name = type->get_local_name(&parser); string safe_name = make_safe_name(class_name); - out_code << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << safe_name << ";\n"; - out_code << "IMPORT_THIS void Dtool_PyModuleClassInit_" << safe_name << "(PyObject *module);\n"; + out_code << "// " << class_name << "\n"; + //out_code << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << safe_name << ";\n"; + out_code << "static struct Dtool_PyTypedObject *Dtool_Ptr_" << safe_name << ";\n"; + //out_code << "#define Dtool_Ptr_" << safe_name << " &Dtool_" << safe_name << "\n"; + //out_code << "IMPORT_THIS void Dtool_PyModuleClassInit_" << safe_name << "(PyObject *module);\n"; + + // This is some really ugly code, because we have to store a pointer with a + // function of a signature that differs from class to class. If someone can + // think of an elegant way to do this without sacrificing perf, let me know. int has_coerce = has_coerce_constructor(type->as_struct_type()); - if (TypeManager::is_reference_count(type)) { - if (has_coerce > 0) { - out_code << "IMPORT_THIS bool Dtool_Coerce_" << safe_name << "(PyObject *args, CPT(" << class_name << ") &coerced);\n"; + if (has_coerce > 0) { + if (TypeManager::is_reference_count(type)) { + out_code + << "inline static bool Dtool_ConstCoerce_" << safe_name << "(PyObject *args, CPT(" << class_name << ") &coerced) {\n" + << " nassertr(Dtool_Ptr_" << safe_name << " != NULL, false);\n" + << " nassertr(Dtool_Ptr_" << safe_name << "->_Dtool_ConstCoerce != NULL, false);\n" + << " return ((bool (*)(PyObject *, CPT(" << class_name << ") &))Dtool_Ptr_" << safe_name << "->_Dtool_ConstCoerce)(args, coerced);\n" + << "}\n"; + if (has_coerce > 1) { - out_code << "IMPORT_THIS bool Dtool_Coerce_" << safe_name << "(PyObject *args, PT(" << class_name << ") &coerced);\n"; + out_code + << "inline static bool Dtool_Coerce_" << safe_name << "(PyObject *args, PT(" << class_name << ") &coerced) {\n" + << " nassertr(Dtool_Ptr_" << safe_name << " != NULL, false);\n" + << " nassertr(Dtool_Ptr_" << safe_name << "->_Dtool_Coerce != NULL, false);\n" + << " return ((bool (*)(PyObject *, PT(" << class_name << ") &))Dtool_Ptr_" << safe_name << "->_Dtool_Coerce)(args, coerced);\n" + << "}\n"; } - } - } else { - if (has_coerce > 0) { - out_code << "IMPORT_THIS bool Dtool_Coerce_" << safe_name << "(PyObject *args, " << class_name << " const *&coerced, bool &manage);\n"; + + } else if (TypeManager::is_trivial(type)) { + out_code + << "inline static " << class_name << " *Dtool_Coerce_" << safe_name << "(PyObject *args, " << class_name << " &coerced) {\n" + << " nassertr(Dtool_Ptr_" << safe_name << " != NULL, NULL);\n" + << " nassertr(Dtool_Ptr_" << safe_name << "->_Dtool_Coerce != NULL, NULL);\n" + << " return ((" << class_name << " *(*)(PyObject *, " << class_name << " &))Dtool_Ptr_" << safe_name << "->_Dtool_Coerce)(args, coerced);\n" + << "}\n"; + + } else { + out_code + << "inline static bool Dtool_ConstCoerce_" << safe_name << "(PyObject *args, " << class_name << " const *&coerced, bool &manage) {\n" + << " nassertr(Dtool_Ptr_" << safe_name << " != NULL, false);\n" + << " nassertr(Dtool_Ptr_" << safe_name << "->_Dtool_ConstCoerce != NULL, false);\n" + << " return ((bool (*)(PyObject *, " << class_name << " const *&, bool&))Dtool_Ptr_" << safe_name << "->_Dtool_ConstCoerce)(args, coerced, manage);\n" + << "}\n"; + if (has_coerce > 1) { - out_code << "IMPORT_THIS bool Dtool_Coerce_" << safe_name << "(PyObject *args, " << class_name << " *&coerced, bool &manage);\n"; + out_code + << "inline static bool Dtool_Coerce_" << safe_name << "(PyObject *args, " << class_name << " *&coerced, bool &manage) {\n" + << " nassertr(Dtool_Ptr_" << safe_name << " != NULL, false);\n" + << " nassertr(Dtool_Ptr_" << safe_name << "->_Dtool_Coerce != NULL, false);\n" + << " return ((bool (*)(PyObject *, " << class_name << " *&, bool&))Dtool_Ptr_" << safe_name << "->_Dtool_Coerce)(args, coerced, manage);\n" + << "}\n"; } } } } - - inside_python_native = false; } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -919,8 +950,6 @@ write_prototypes_class(ostream &out_code, ostream *out_h, Object *obj) { //////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative:: write_functions(ostream &out) { - inside_python_native = true; - out << "//********************************************************************\n"; out << "//*** Functions for .. Global\n" ; out << "//********************************************************************\n"; @@ -957,8 +986,6 @@ write_functions(ostream &out) { } } } - - inside_python_native = true; } //////////////////////////////////////////////////////////////////// @@ -1015,7 +1042,7 @@ write_class_details(ostream &out, Object *obj) { // Write the constructors. if (obj->_constructors.size() == 0) { // There is no constructor - write one that simply outputs an error. - out << "int Dtool_Init_" + ClassName + "(PyObject *, PyObject *, PyObject *) {\n" + out << "static int Dtool_Init_" + ClassName + "(PyObject *, PyObject *, PyObject *) {\n" << "#ifdef NDEBUG\n" << " Dtool_Raise_TypeError(\"cannot init constant class\");\n" << "#else\n" @@ -1027,7 +1054,7 @@ write_class_details(ostream &out, Object *obj) { } 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)"; + std::string fname = "static int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)"; string expected_params; write_function_for_name(out, obj, func->_remaps, fname, expected_params, true, AT_keyword_args, RF_int); @@ -1040,7 +1067,7 @@ write_class_details(ostream &out, Object *obj) { int has_coerce = has_coerce_constructor(cpptype->as_struct_type()); if (has_coerce > 0) { write_coerce_constructor(out, obj, true); - if (has_coerce > 1) { + if (has_coerce > 1 && !TypeManager::is_trivial(obj->_itype._cpptype)) { write_coerce_constructor(out, obj, false); } } @@ -1059,28 +1086,28 @@ write_class_details(ostream &out, Object *obj) { 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(di->second._structType); + _external_imports.insert(TypeManager::resolve_type(di->second._structType)); } //out << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(di->second._to_class_name) << ";\n"; } // Write support methods to cast from and to pointers of this type. { - out << "inline void *Dtool_UpcastInterface_" << ClassName << "(PyObject *self, Dtool_PyTypedObject *requested_type) {\n"; + out << "static void *Dtool_UpcastInterface_" << ClassName << "(PyObject *self, Dtool_PyTypedObject *requested_type) {\n"; out << " Dtool_PyTypedObject *SelfType = ((Dtool_PyInstDef *)self)->_My_Type;\n"; - out << " if (SelfType != &Dtool_" << ClassName << ") {\n"; + out << " if (SelfType != Dtool_Ptr_" << ClassName << ") {\n"; out << " printf(\"" << ClassName << " ** Bad Source Type-- Requesting Conversion from %s to %s\\n\", Py_TYPE(self)->tp_name, requested_type->_PyType.tp_name); fflush(NULL);\n";; out << " return NULL;\n"; out << " }\n"; out << "\n"; out << " " << cClassName << " *local_this = (" << cClassName << " *)((Dtool_PyInstDef *)self)->_ptr_to_object;\n"; - out << " if (requested_type == &Dtool_" << ClassName << ") {\n"; + out << " if (requested_type == Dtool_Ptr_" << ClassName << ") {\n"; out << " return local_this;\n"; out << " }\n"; for (di = details.begin(); di != details.end(); di++) { if (di->second._is_legal_py_class) { - out << " if (requested_type == &Dtool_" << make_safe_name(di->second._to_class_name) << ") {\n"; + out << " if (requested_type == Dtool_Ptr_" << make_safe_name(di->second._to_class_name) << ") {\n"; out << " return " << di->second._up_cast_string << " local_this;\n"; out << " }\n"; } @@ -1089,16 +1116,16 @@ write_class_details(ostream &out, Object *obj) { out << " return NULL;\n"; out << "}\n\n"; - out << "inline void *Dtool_DowncastInterface_" << ClassName << "(void *from_this, Dtool_PyTypedObject *from_type) {\n"; + out << "static void *Dtool_DowncastInterface_" << ClassName << "(void *from_this, Dtool_PyTypedObject *from_type) {\n"; out << " if (from_this == NULL || from_type == NULL) {\n"; out << " return NULL;\n"; out << " }\n"; - out << " if (from_type == &Dtool_" << ClassName << ") {\n"; + out << " if (from_type == Dtool_Ptr_" << ClassName << ") {\n"; out << " return from_this;\n"; out << " }\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_" << make_safe_name(di->second._to_class_name) << ") {\n"; + out << " if (from_type == Dtool_Ptr_" << make_safe_name(di->second._to_class_name) << ") {\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"; @@ -1144,21 +1171,25 @@ write_class_declarations(ostream &out, ostream *out_h, Object *obj) { } out << "(" << _def->module_name << ", " << class_name << ", " << class_name << "_localtype, " << classNameFromCppName(preferred_name, false) << ");\n"; - out << "EXPORT_THIS void Dtool_PyModuleClassInit_" << class_name << "(PyObject *module);\n"; + out << "static struct Dtool_PyTypedObject *const Dtool_Ptr_" << class_name << " = &Dtool_" << class_name << ";\n"; + out << "static void Dtool_PyModuleClassInit_" << class_name << "(PyObject *module);\n"; int has_coerce = has_coerce_constructor(type->as_struct_type()); - if (TypeManager::is_reference_count(type)) { - if (has_coerce > 0) { - out << "EXPORT_THIS bool Dtool_Coerce_" << class_name << "(PyObject *args, CPT(" << c_class_name << ") &coerced);\n"; + if (has_coerce > 0) { + if (TypeManager::is_reference_count(type)) { + assert(!type->is_trivial()); + out << "bool Dtool_ConstCoerce_" << class_name << "(PyObject *args, CPT(" << c_class_name << ") &coerced);\n"; if (has_coerce > 1) { - out << "EXPORT_THIS bool Dtool_Coerce_" << class_name << "(PyObject *args, PT(" << c_class_name << ") &coerced);\n"; + out << "bool Dtool_Coerce_" << class_name << "(PyObject *args, PT(" << c_class_name << ") &coerced);\n"; } - } - } else { - if (has_coerce > 0) { - out << "EXPORT_THIS bool Dtool_Coerce_" << class_name << "(PyObject *args, " << c_class_name << " const *&coerced, bool &manage);\n"; + + } else if (TypeManager::is_trivial(type)) { + out << "" << c_class_name << " *Dtool_Coerce_" << class_name << "(PyObject *args, " << c_class_name << " &coerced);\n"; + + } else { + out << "bool Dtool_ConstCoerce_" << class_name << "(PyObject *args, " << c_class_name << " const *&coerced, bool &manage);\n"; if (has_coerce > 1) { - out << "EXPORT_THIS bool Dtool_Coerce_" << class_name << "(PyObject *args, " << c_class_name << " *&coerced, bool &manage);\n"; + out << "bool Dtool_Coerce_" << class_name << "(PyObject *args, " << c_class_name << " *&coerced, bool &manage);\n"; } } } @@ -1202,7 +1233,7 @@ write_sub_module(ostream &out, Object *obj) { << " " << *(obj->_itype._cpptype) << "\n"; if (!isExportThisRun(wrapped_itype._cpptype)) { - _external_imports.insert(wrapped_itype._cpptype); + _external_imports.insert(TypeManager::resolve_type(wrapped_itype._cpptype)); } } @@ -1210,9 +1241,9 @@ write_sub_module(ostream &out, Object *obj) { std::string export_class_name2 = classNameFromCppName(obj->_itype.get_name(), true); // out << " Py_INCREF(&Dtool_" << class_name << ".As_PyTypeObject());\n"; - out << " PyModule_AddObject(module, \"" << export_class_name << "\", (PyObject *)&Dtool_" << class_name << ".As_PyTypeObject());\n"; + out << " PyModule_AddObject(module, \"" << export_class_name << "\", (PyObject *)&Dtool_" << class_name << ");\n"; if (export_class_name != export_class_name2) { - out << " PyModule_AddObject(module, \"" << export_class_name2 << "\", (PyObject *)&Dtool_" << class_name << ".As_PyTypeObject());\n"; + out << " PyModule_AddObject(module, \"" << export_class_name2 << "\", (PyObject *)&Dtool_" << class_name << ");\n"; } } @@ -1225,19 +1256,62 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) { out << "//*** Module Object Linker ..\n"; out << "//********************************************************************\n"; - out << "static void BuildInstants(PyObject *module) {\n"; - out << " (void) module; // Unused\n"; - Objects::iterator oi; + + out << "void Dtool_" << def->library_name << "_RegisterTypes() {\n"; + for (oi = _objects.begin(); oi != _objects.end(); ++oi) { Object *object = (*oi).second; - if (object->_itype.is_enum() && !object->_itype.is_nested()) { - 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"; + if (object->_itype.is_class() || + object->_itype.is_struct()) { + if (is_cpp_type_legal(object->_itype._cpptype) && + isExportThisRun(object->_itype._cpptype)) { + string class_name = make_safe_name(object->_itype.get_scoped_name()); + bool is_typed = HasAGetClassTypeFunction(object->_itype._cpptype); + + if (is_typed) { + out << " Dtool_" << class_name << "._type = " + << object->_itype._cpptype->get_local_name(&parser) + << "::get_class_type();\n" + << " RegisterRuntimeTypedClass(Dtool_" << class_name << ");\n"; + + } else { + out << " RegisterNamedClass(\"" << object->_itype.get_scoped_name() + << "\", Dtool_" << class_name << ");\n"; + + if (IsPandaTypedObject(object->_itype._cpptype->as_struct_type())) { + nout << object->_itype.get_scoped_name() << " derives from TypedObject, " + << "but does not define a get_class_type() function.\n"; + } + } } + } + } + out << "}\n\n"; + + out << "void Dtool_" << def->library_name << "_ResolveExternals() {\n"; + out << " // Resolve externally imported types.\n"; + + for (std::set::iterator ii = _external_imports.begin(); ii != _external_imports.end(); ++ii) { + string class_name = (*ii)->get_local_name(&parser); + string safe_name = make_safe_name(class_name); + + if (HasAGetClassTypeFunction(*ii)) { + out << " Dtool_Ptr_" << safe_name << " = LookupRuntimeTypedClass(" << class_name << "::get_class_type());\n"; + } else { + out << " Dtool_Ptr_" << safe_name << " = LookupNamedClass(\"" << class_name << "\");\n"; + } + } + out << "}\n\n"; + + out << "void Dtool_" << def->library_name << "_BuildInstants(PyObject *module) {\n"; + out << " (void) module;\n"; + + for (oi = _objects.begin(); oi != _objects.end(); ++oi) { + Object *object = (*oi).second; + if (object->_itype.is_enum() && !object->_itype.is_nested() && + isExportThisRun(object->_itype._cpptype)) { + int enum_count = object->_itype.number_of_enum_values(); for (int xx = 0; xx < enum_count; xx++) { string name1 = classNameFromCppName(object->_itype.get_enum_value_name(xx), false); string name2 = classNameFromCppName(object->_itype.get_enum_value_name(xx), true); @@ -1334,10 +1408,10 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) { // Note: we shouldn't add METH_STATIC here, since both METH_STATIC // and METH_CLASS are illegal for module-level functions. - out << " { \"" << name1 << "\", (PyCFunction) &" + out << " {\"" << name1 << "\", (PyCFunction) &" << func->_name << ", " << flags << ", (const char *)" << func->_name << "_comment},\n"; if (name1 != name2) { - out << " { \"" << name2 << "\", (PyCFunction) &" + out << " {\"" << name2 << "\", (PyCFunction) &" << func->_name << ", " << flags << ", (const char *)" << func->_name << "_comment},\n"; } } @@ -1351,7 +1425,7 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) { out << " {NULL, NULL, 0, NULL}\n" << "};\n\n"; - out << "EXPORT_THIS struct LibraryDef " << def->library_name << "_moddef = {python_simple_funcs, BuildInstants};\n"; + out << "struct LibraryDef " << def->library_name << "_moddef = {python_simple_funcs};\n"; if (out_h != NULL) { *out_h << "extern struct LibraryDef " << def->library_name << "_moddef;\n"; } @@ -1440,6 +1514,11 @@ write_module_class(ostream &out, Object *obj) { std::string cClassName = obj->_itype.get_true_name(); std::string export_class_name = classNameFromCppName(obj->_itype.get_name(), false); + bool is_runtime_typed = IsPandaTypedObject(obj->_itype._cpptype->as_struct_type()); + if (!is_runtime_typed && HasAGetClassTypeFunction(obj->_itype._cpptype)) { + is_runtime_typed = true; + } + Functions::iterator fi; out << "//********************************************************************\n"; out << "//*** Py Init Code For .. " << ClassName << " | " << export_class_name << "\n" ; @@ -1555,10 +1634,10 @@ write_module_class(ostream &out, Object *obj) { } // This method has non-slotted remaps, so write it out into the function table. - out << " { \"" << name1 << "\", (PyCFunction) &" + out << " {\"" << name1 << "\", (PyCFunction) &" << func->_name << ", " << flags << ", (char *) " << func->_name << "_comment},\n"; if (name1 != name2) { - out << " { \"" << name2 << "\", (PyCFunction) &" + out << " {\"" << name2 << "\", (PyCFunction) &" << func->_name << ", " << flags << ", (char *) " << func->_name << "_comment},\n"; } } @@ -1566,37 +1645,43 @@ write_module_class(ostream &out, Object *obj) { if (obj->_protocol_types & Object::PT_make_copy) { if (!got_copy) { - out << " { \"__copy__\", (PyCFunction) ©_from_make_copy, METH_NOARGS, NULL},\n"; + out << " {\"__copy__\", (PyCFunction) ©_from_make_copy, METH_NOARGS, NULL},\n"; got_copy = true; } } else if (obj->_protocol_types & Object::PT_copy_constructor) { if (!got_copy) { - out << " { \"__copy__\", (PyCFunction) ©_from_copy_constructor, METH_NOARGS, NULL},\n"; + out << " {\"__copy__\", (PyCFunction) ©_from_copy_constructor, METH_NOARGS, NULL},\n"; got_copy = true; } } if (got_copy && !got_deepcopy) { - out << " { \"__deepcopy__\", (PyCFunction) &map_deepcopy_to_copy, METH_VARARGS, NULL},\n"; + out << " {\"__deepcopy__\", (PyCFunction) &map_deepcopy_to_copy, METH_VARARGS, NULL},\n"; } MakeSeqs::iterator msi; for (msi = obj->_make_seqs.begin(); msi != obj->_make_seqs.end(); ++msi) { - string flags = "METH_NOARGS"; - if (obj->is_static_method((*msi)->_element_name)) { - flags += " | METH_CLASS"; - } - string name1 = methodNameFromCppName((*msi)->_seq_name, export_class_name, false); - string name2 = methodNameFromCppName((*msi)->_seq_name, export_class_name, true); - out << " { \"" << name1 - << "\", (PyCFunction) &" << (*msi)->_name << ", " << flags << ", NULL},\n"; - if (name1 != name2) { - out << " { \"" << name2 + const string &seq_name = (*msi)->_seq_name; + + if ((seq_name.size() > 4 && seq_name.substr(0, 4) == "get_") || + (seq_name.size() > 7 && seq_name.substr(0, 7) == "modify_")) { + + string flags = "METH_NOARGS"; + if (obj->is_static_method((*msi)->_element_name)) { + flags += " | METH_CLASS"; + } + string name1 = methodNameFromCppName((*msi)->_seq_name, export_class_name, false); + string name2 = methodNameFromCppName((*msi)->_seq_name, export_class_name, true); + out << " {\"" << name1 << "\", (PyCFunction) &" << (*msi)->_name << ", " << flags << ", NULL},\n"; + if (name1 != name2) { + out << " { \"" << name2 + << "\", (PyCFunction) &" << (*msi)->_name << ", " << flags << ", NULL},\n"; + } } } - out << " { NULL, NULL, 0, NULL }\n" + out << " {NULL, NULL, 0, NULL}\n" << "};\n\n"; int num_derivations = obj->_itype.number_of_derivations(); @@ -1607,7 +1692,7 @@ write_module_class(ostream &out, Object *obj) { const InterrogateType &d_itype = idb->get_type(d_type_Index); if (is_cpp_type_legal(d_itype._cpptype)) { if (!isExportThisRun(d_itype._cpptype)) { - _external_imports.insert(d_itype._cpptype); + _external_imports.insert(TypeManager::resolve_type(d_itype._cpptype)); //out << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(d_itype.get_scoped_name().c_str()) << ";\n"; } @@ -2649,7 +2734,7 @@ write_module_class(ostream &out, Object *obj) { } // Output the actual PyTypeObject definition. - out << "EXPORT_THIS Dtool_PyTypedObject Dtool_" << ClassName << " = {\n"; + out << "struct Dtool_PyTypedObject Dtool_" << ClassName << " = {\n"; out << " {\n"; out << " PyVarObject_HEAD_INIT(NULL, 0)\n"; // const char *tp_name; @@ -2848,12 +2933,36 @@ write_module_class(ostream &out, Object *obj) { out << " 0, // tp_version_tag\n"; out << "#endif\n"; out << " },\n"; + + // It's tempting to initialize the type handle here, but this causes static + // init ordering issues; this may run before init_type is called. + out << " TypeHandle::none(),\n"; + out << " Dtool_PyModuleClassInit_" << ClassName << ",\n"; out << " Dtool_UpcastInterface_" << ClassName << ",\n"; out << " Dtool_DowncastInterface_" << ClassName << ",\n"; - out << " TypeHandle::none(),\n"; + + int has_coerce = has_coerce_constructor(obj->_itype._cpptype->as_struct_type()); + if (has_coerce > 0) { + if (TypeManager::is_reference_count(obj->_itype._cpptype) || + !TypeManager::is_trivial(obj->_itype._cpptype)) { + out << " (CoerceFunction)Dtool_ConstCoerce_" << ClassName << ",\n"; + if (has_coerce > 1) { + out << " (CoerceFunction)Dtool_Coerce_" << ClassName << ",\n"; + } else { + out << " (CoerceFunction)0,\n"; + } + } else { + out << " (CoerceFunction)0,\n"; + out << " (CoerceFunction)Dtool_Coerce_" << ClassName << ",\n"; + } + } else { + out << " (CoerceFunction)0,\n"; + out << " (CoerceFunction)0,\n"; + } + out << "};\n\n"; - out << "void Dtool_PyModuleClassInit_" << ClassName << "(PyObject *module) {\n"; + out << "static void Dtool_PyModuleClassInit_" << ClassName << "(PyObject *module) {\n"; out << " (void) module; // Unused\n"; out << " static bool initdone = false;\n"; out << " if (!initdone) {\n"; @@ -2864,11 +2973,14 @@ write_module_class(ostream &out, Object *obj) { out << " // Dependent objects\n"; string baseargs; for (vector::iterator bi = bases.begin(); bi != bases.end(); ++bi) { - baseargs += ", &Dtool_" + *bi + ".As_PyTypeObject()"; - out << " Dtool_PyModuleClassInit_" << make_safe_name(*bi) << "(NULL);\n"; + baseargs += ", (PyTypeObject *)Dtool_Ptr_" + *bi; + string safe_name = make_safe_name(*bi); + + out << " assert(Dtool_Ptr_" << safe_name << " != NULL);\n" + << " Dtool_Ptr_" << safe_name << "->_Dtool_ModuleClassInit(NULL);\n"; } - out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_bases = PyTuple_Pack(" << bases.size() << baseargs << ");\n"; + out << " Dtool_" << ClassName << "._PyType.tp_bases = PyTuple_Pack(" << bases.size() << baseargs << ");\n"; } int num_nested = obj->_itype.number_of_nested_types(); @@ -2901,7 +3013,7 @@ write_module_class(ostream &out, Object *obj) { } else { out << " PyObject *dict = PyDict_New();\n"; } - out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_dict = dict;\n"; + out << " Dtool_" << ClassName << "._PyType.tp_dict = dict;\n"; out << " PyDict_SetItemString(dict, \"DtoolClassDict\", dict);\n"; // Now go through the nested types again to actually add the dict items. @@ -2922,9 +3034,9 @@ write_module_class(ostream &out, Object *obj) { out << " Dtool_PyModuleClassInit_" << ClassName1 << "(NULL);\n"; string name1 = classNameFromCppName(ClassName2, false); string name2 = classNameFromCppName(ClassName2, true); - out << " PyDict_SetItemString(dict, \"" << name1 << "\", (PyObject *)&Dtool_" << ClassName1 << ".As_PyTypeObject());\n"; + out << " PyDict_SetItemString(dict, \"" << name1 << "\", (PyObject *)&Dtool_" << ClassName1 << ");\n"; if (name1 != name2) { - out << " PyDict_SetItemString(dict, \"" << name2 << "\", (PyObject *)&Dtool_" << ClassName1 << ".As_PyTypeObject());\n"; + out << " PyDict_SetItemString(dict, \"" << name2 << "\", (PyObject *)&Dtool_" << ClassName1 << ");\n"; } } else if (nested_obj->_itype.is_typedef()) { @@ -2943,7 +3055,7 @@ write_module_class(ostream &out, Object *obj) { string ClassName2 = make_safe_name(interrogate_type_name(wrapped)); string name1 = classNameFromCppName(ClassName2, false); - out << " PyDict_SetItemString(dict, \"" << name1 << "\", (PyObject *)&Dtool_" << ClassName1 << ".As_PyTypeObject());\n"; + out << " PyDict_SetItemString(dict, \"" << name1 << "\", (PyObject *)&Dtool_" << ClassName1 << ");\n"; // No need to support mangled names for nested typedefs; we only added support recently. } else if (nested_obj->_itype.is_enum()) { @@ -2969,28 +3081,12 @@ write_module_class(ostream &out, Object *obj) { } } - out << " if (PyType_Ready(&Dtool_" << ClassName << ".As_PyTypeObject()) < 0) {\n"; - out << " Dtool_Raise_TypeError(\"PyType_Ready(" << ClassName << ")\");\n"; - out << " return;\n"; - out << " }\n"; - - out << " Py_INCREF(&Dtool_" << ClassName << ".As_PyTypeObject());\n"; - - // Why make the class a member of itself? - //out << " PyDict_SetItemString(Dtool_" <_itype._cpptype->as_struct_type()); - if (HasAGetClassTypeFunction(obj->_itype)) { - is_runtime_typed = true; - } - - if (is_runtime_typed) { - out << " RegisterRuntimeClass(&Dtool_" << ClassName << ", " << cClassName << "::get_class_type().get_index());\n"; - } else { - out << " RegisterRuntimeClass(&Dtool_" << ClassName << ", -1);\n"; - } - - out << " }\n"; + out << " if (PyType_Ready((PyTypeObject *)&Dtool_" << ClassName << ") < 0) {\n" + " Dtool_Raise_TypeError(\"PyType_Ready(" << ClassName << ")\");\n" + " return;\n" + " }\n" + " Py_INCREF((PyTypeObject *)&Dtool_" << ClassName << ");\n" + " }\n"; // Also write out the explicit alternate names. //int num_alt_names = obj->_itype.get_num_alt_names(); @@ -3625,12 +3721,14 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) { std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); std::string cClassName = obj->_itype.get_true_name(); + int return_flags = RF_coerced; + if (TypeManager::is_reference_count(obj->_itype._cpptype)) { // The coercion works slightly different for reference counted types, since // we can handle those a bit more nicely by taking advantage of the refcount // instead of having to use a boolean to indicate that it should be managed. if (is_const) { - out << "bool Dtool_Coerce_" << ClassName << "(PyObject *args, CPT(" << cClassName << ") &coerced) {\n"; + out << "bool Dtool_ConstCoerce_" << ClassName << "(PyObject *args, CPT(" << cClassName << ") &coerced) {\n"; } else { out << "bool Dtool_Coerce_" << ClassName << "(PyObject *args, PT(" << cClassName << ") &coerced) {\n"; } @@ -3650,9 +3748,26 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) { out << " coerced->ref();\n"; out << " return true;\n"; } + return_flags |= RF_err_false; + + } else if (TypeManager::is_trivial(obj->_itype._cpptype)) { + out << cClassName << " *Dtool_Coerce_" << ClassName << "(PyObject *args, " << cClassName << " &coerced) {\n"; + + out << " " << cClassName << " *local_this;\n"; + out << " DTOOL_Call_ExtractThisPointerForType(args, &Dtool_" << ClassName << ", (void**)&local_this);\n"; + out << " if (local_this != NULL) {\n"; + out << " if (((Dtool_PyInstDef *)args)->_is_const) {\n"; + out << " // This is a const object. Make a copy.\n"; + out << " coerced = *(const " << cClassName << " *)local_this;\n"; + out << " return &coerced;\n"; + out << " }\n"; + out << " return local_this;\n"; + + return_flags |= RF_err_null; + } else { if (is_const) { - out << "bool Dtool_Coerce_" << ClassName << "(PyObject *args, " << cClassName << " const *&coerced, bool &manage) {\n"; + out << "bool Dtool_ConstCoerce_" << ClassName << "(PyObject *args, " << cClassName << " const *&coerced, bool &manage) {\n"; } else { out << "bool Dtool_Coerce_" << ClassName << "(PyObject *args, " << cClassName << " *&coerced, bool &manage) {\n"; } @@ -3667,12 +3782,14 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) { } else { out << " return true;\n"; } + + return_flags |= RF_err_false; } out << " }\n\n"; if (map_sets.empty()) { - error_return(out, 2, RF_coerced | RF_err_false); + error_return(out, 2, return_flags); out << "}\n\n"; return; } @@ -3687,12 +3804,12 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) { out << " PyObject *arg = args;\n"; write_function_forset(out, mii->second, mii->first, mii->first, expected_params, 4, false, false, - AT_single_arg, RF_coerced | RF_err_false, true, false); + AT_single_arg, return_flags, true, false); if (map_sets.size() == 1) { out << " }\n"; //out << " PyErr_Clear();\n"; - error_return(out, 2, RF_coerced | RF_err_false); + error_return(out, 2, return_flags); out << "}\n\n"; return; } @@ -3730,7 +3847,7 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) { indent(out, 6) << "case " << max_args << ": {\n"; write_function_forset(out, mii->second, min_args, max_args, expected_params, 8, false, false, - AT_varargs, RF_coerced | RF_err_false, true, false); + AT_varargs, return_flags, true, false); indent(out, 8) << "break;\n"; indent(out, 6) << "}\n"; @@ -3760,13 +3877,13 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) { } write_function_forset(out, mii->second, min_args, max_args, expected_params, 6, false, false, - AT_varargs, RF_coerced | RF_err_false, true, false); + AT_varargs, return_flags, true, false); indent(out, 4) << "}\n"; } out << " }\n\n"; //out << " PyErr_Clear();\n"; - error_return(out, 2, RF_coerced | RF_err_false); + error_return(out, 2, return_flags); out << "}\n\n"; } @@ -5163,7 +5280,7 @@ write_function_instance(ostream &out, FunctionRemap *remap, // need to a forward scope for this class.. if (!isExportThisRun(obj_type)) { - _external_imports.insert(obj_type); + _external_imports.insert(TypeManager::resolve_type(obj_type)); } string this_class_name; @@ -5183,19 +5300,50 @@ write_function_instance(ostream &out, FunctionRemap *remap, // We use a PointerTo to handle the management here. It's cleaner // that way. if (TypeManager::is_const_pointer_to_anything(type)) { - extra_convert << 'C'; - } - extra_convert - << "PT(" << class_name << ") " << param_name << "_this" - << default_expr << ";\n"; + extra_convert + << "CPT(" << class_name << ") " << param_name << "_this" + << default_expr << ";\n"; - coerce_call = "Dtool_Coerce_" + make_safe_name(class_name) + - "(" + param_name + ", " + param_name + "_this)"; + coerce_call = "Dtool_ConstCoerce_" + make_safe_name(class_name) + + "(" + param_name + ", " + param_name + "_this)"; + } else { + extra_convert + << "PT(" << class_name << ") " << param_name << "_this" + << default_expr << ";\n"; + + coerce_call = "Dtool_Coerce_" + make_safe_name(class_name) + + "(" + param_name + ", " + param_name + "_this)"; + } // Use move constructor when available for functions that take // an actual PointerTo. This eliminates an unref()/ref() pair. pexpr_string = "MOVE(" + param_name + "_this)"; + } else if (TypeManager::is_trivial(obj_type)) { + // This is a trivial type, such as TypeHandle or LVecBase4. + obj_type->output_instance(extra_convert, param_name + "_local", &parser); + extra_convert << ";\n"; + + type->output_instance(extra_convert, param_name + "_this", &parser); + + if (is_optional) { + extra_convert + << default_expr << ";\n" + << "if (" << param_name << " != NULL) {\n" + << " " << param_name << "_this"; + } + + extra_convert << " = Dtool_Coerce_" + make_safe_name(class_name) + + "(" + param_name + ", " + param_name + "_local);\n"; + + if (is_optional) { + extra_convert << "}\n"; + } + + coerce_call = "(" + param_name + "_this != NULL)"; + + pexpr_string = param_name + "_this"; + } else { // This is a bit less elegant: we use a bool to store whether // we're supposed to clean up the reference afterward. @@ -5204,8 +5352,13 @@ write_function_instance(ostream &out, FunctionRemap *remap, << default_expr << ";\n" << "bool " << param_name << "_manage = false;\n"; - coerce_call = "Dtool_Coerce_" + make_safe_name(class_name) + - "(" + param_name + ", " + param_name + "_this, " + param_name + "_manage)"; + if (TypeManager::is_const_pointer_or_ref(orig_type)) { + coerce_call = "Dtool_ConstCoerce_" + make_safe_name(class_name) + + "(" + param_name + ", " + param_name + "_this, " + param_name + "_manage)"; + } else { + coerce_call = "Dtool_Coerce_" + make_safe_name(class_name) + + "(" + param_name + ", " + param_name + "_this, " + param_name + "_manage)"; + } extra_cleanup << "if (" << param_name << "_manage) {\n" @@ -5266,13 +5419,13 @@ write_function_instance(ostream &out, FunctionRemap *remap, } extra_convert << "DTOOL_Call_ExtractThisPointerForType(" << param_name - << ", &Dtool_" << make_safe_name(class_name) + << ", Dtool_Ptr_" << make_safe_name(class_name) << ", (void **)&" << param_name << "_this);\n"; } else { extra_convert << boolalpha << " = (" << class_name << " *)" << "DTOOL_Call_GetPointerThisClass(" << param_name - << ", &Dtool_" << make_safe_name(class_name) + << ", Dtool_Ptr_" << make_safe_name(class_name) << ", " << pn << ", \"" << method_prefix << methodNameFromCppName(remap, this_class_name, false) << "\", " << const_ok << ", " << report_errors << ");\n"; @@ -5462,6 +5615,20 @@ write_function_instance(ostream &out, FunctionRemap *remap, manage_return = remap->_return_value_needs_management; return_expr = "return_value"; + } else if ((return_flags & RF_coerced) != 0 && TypeManager::is_trivial(remap->_cpptype)) { + // Another special case is the coerce constructor for a trivial type. + // We don't want to invoke "operator new" unnecessarily. + if (is_constructor && remap->_extension) { + // Extension constructors are a special case, as usual. + indent(out, indent_level) + << remap->get_call_str("&coerced", pexprs) << ";\n"; + + } else { + indent(out, indent_level) + << "coerced = " << remap->get_call_str(container, pexprs) << ";\n"; + } + return_expr = "&coerced"; + } else { // The general case; an ordinary constructor or function. return_expr = remap->call_function(out, indent_level, true, container, pexprs); @@ -5626,7 +5793,10 @@ write_function_instance(ostream &out, FunctionRemap *remap, // the C++ code was executing, and report this failure back to Python. // Don't do this for coercion constructors since they are called by // other wrapper functions which already check this on their own. - if (watch_asserts && (return_flags & RF_coerced) == 0) { + // Generated getters obviously can't raise asserts. + if (watch_asserts && (return_flags & RF_coerced) == 0 && + remap->_type != FunctionRemap::T_getter && + remap->_type != FunctionRemap::T_setter) { out << "#ifndef NDEBUG\n"; indent(out, indent_level) << "Notify *notify = Notify::ptr();\n"; @@ -5663,7 +5833,7 @@ write_function_instance(ostream &out, FunctionRemap *remap, TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)), false); const InterrogateType &itype = idb->get_type(type_index); indent(out, indent_level) - << "return DTool_PyInit_Finalize(self, " << return_expr << ", &" << CLASS_PREFIX << make_safe_name(itype.get_scoped_name()) << ", true, false);\n"; + << "return DTool_PyInit_Finalize(self, (void *)" << return_expr << ", &" << CLASS_PREFIX << make_safe_name(itype.get_scoped_name()) << ", true, false);\n"; } else if (TypeManager::is_integer(orig_type)) { if (return_flags & RF_compare) { @@ -5678,7 +5848,7 @@ write_function_instance(ostream &out, FunctionRemap *remap, indent(out, indent_level) << "return 0;\n"; } else { - cerr << "Warning: function has return type " << *orig_type + nout << "Warning: function has return type " << *orig_type << ", expected int or void:\n" << expected_params << "\n"; indent(out, indent_level) << "// Don't know what to do with return type " << *orig_type << ".\n"; @@ -5728,16 +5898,20 @@ write_function_instance(ostream &out, FunctionRemap *remap, if (return_expr == "coerced") { // We already did this earlier... + indent(out, indent_level) << "return true;\n"; } else if (TypeManager::is_reference_count(remap->_cpptype)) { indent(out, indent_level) << "coerced = MOVE(" << return_expr << ");\n"; + indent(out, indent_level) << "return true;\n"; + + } else if (TypeManager::is_trivial(remap->_cpptype)) { + indent(out, indent_level) << "return &coerced;\n"; } else { indent(out, indent_level) << "coerced = " << return_expr << ";\n"; indent(out, indent_level) << "manage = true;\n"; + indent(out, indent_level) << "return true;\n"; } - - indent(out, indent_level) << "return true;\n"; } // Close the extra braces opened earlier. @@ -5827,7 +6001,8 @@ error_raise_return(ostream &out, int indent_level, int return_flags, out << ");\n"; } - } else if ((return_flags & RF_err_null) != 0) { + } else if ((return_flags & RF_err_null) != 0 && + (return_flags & RF_pyobject) != 0) { // PyErr_Format always returns NULL. Passing it on directly allows // the compiler to make a tiny optimization, so why not. indent(out, indent_level) << "return PyErr_Format(PyExc_" << exc_type << ",\n"; @@ -6265,7 +6440,6 @@ record_object(TypeIndex type_index) { //////////////////////////////////////////////////////////////////// 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 @@ -6314,7 +6488,6 @@ generate_wrappers() { record_function(dummy_type, func_index); } } - inside_python_native = false; } ////////////////////////////////////////////// @@ -6490,9 +6663,9 @@ has_coerce_constructor(CPPStructType *type) { } if (ftype->_flags & CPPFunctionType::F_constructor) { - if (params.size() == 1 && - TypeManager::unwrap(params[0]->_type) == type) { - // Skip a copy constructor. + if (ftype->_flags & (CPPFunctionType::F_copy_constructor | + CPPFunctionType::F_move_constructor)) { + // Skip a copy and move constructor. continue; } else { return 2; @@ -6626,37 +6799,19 @@ DoesInheritFromIsClass(const CPPStructType *inclass, const std::string &name) { // does the class have a supportable GetClassType which returns a TypeHandle. ////////////////////////////////////////////////////////////////////////////////////////// bool InterfaceMakerPythonNative:: -HasAGetClassTypeFunction(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() == "get_class_type") { - 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 && cppfunc->_return_type != NULL && - cppfunc->_parameters != NULL) { - CPPType *ret_type = TypeManager::unwrap(cppfunc->_return_type); - if (TypeManager::is_struct(ret_type) && - ret_type->get_simple_name() == "TypeHandle") { - if (cppfunc->_parameters->_parameters.size() == 0) { - return true; - } - } - } - } - } - } +HasAGetClassTypeFunction(CPPType *type) { + while (type->get_subtype() == CPPDeclaration::ST_typedef) { + type = type->as_typedef_type()->_type; } - return false; + + CPPStructType *struct_type = type->as_struct_type(); + if (struct_type == NULL) { + return false; + } + + CPPScope *scope = struct_type->get_scope(); + + return scope->_functions.find("get_class_type") != scope->_functions.end(); } //////////////////////////////////////////////////////////////////// diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.h b/dtool/src/interrogate/interfaceMakerPythonNative.h index 2eb7e64b5e..ae62cfc72b 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.h +++ b/dtool/src/interrogate/interfaceMakerPythonNative.h @@ -199,7 +199,7 @@ public: bool DoesInheritFromIsClass(const CPPStructType * inclass, const std::string &name); bool IsPandaTypedObject(CPPStructType * inclass) { return DoesInheritFromIsClass(inclass,"TypedObject"); }; void write_python_instance(ostream &out, int indent_level, const std::string &return_expr, bool owns_memory, const InterrogateType &itype, bool is_const); - bool HasAGetClassTypeFunction(const InterrogateType &itype_class); + bool HasAGetClassTypeFunction(CPPType *type); int NeedsAStrFunction(const InterrogateType &itype_class); int NeedsAReprFunction(const InterrogateType &itype_class); bool NeedsARichCompareFunction(const InterrogateType &itype_class); diff --git a/dtool/src/interrogate/interrogateBuilder.cxx b/dtool/src/interrogate/interrogateBuilder.cxx index 6e874462f8..6563132bf4 100644 --- a/dtool/src/interrogate/interrogateBuilder.cxx +++ b/dtool/src/interrogate/interrogateBuilder.cxx @@ -53,7 +53,6 @@ InterrogateBuilder builder; std::string EXPORT_IMPORT_PREFIX; -bool inside_python_native = false; //////////////////////////////////////////////////////////////////// // Function: InterrogateBuilder::add_source_file @@ -1912,27 +1911,29 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type) { CPPType *return_type = NULL; CPPFunctionGroup *fgroup = make_property->_getter; - CPPFunctionGroup::Instances::const_iterator fi; - for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { - CPPInstance *function = (*fi); - CPPFunctionType *ftype = - function->_type->as_function_type(); - if (ftype != NULL && ftype->_parameters->_parameters.size() == 0) { - getter = function; - return_type = ftype->_return_type; + if (fgroup != NULL) { + CPPFunctionGroup::Instances::const_iterator fi; + for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { + CPPInstance *function = (*fi); + CPPFunctionType *ftype = + function->_type->as_function_type(); + if (ftype != NULL && ftype->_parameters->_parameters.size() == 0) { + getter = function; + return_type = ftype->_return_type; - // The return type of the non-const method probably better represents - // the type of the property we are creating. - if ((ftype->_flags & CPPFunctionType::F_const_method) == 0) { - break; + // The return type of the non-const method probably better represents + // the type of the property we are creating. + if ((ftype->_flags & CPPFunctionType::F_const_method) == 0) { + break; + } } } - } - if (getter == NULL || return_type == NULL) { - cerr << "No instance of getter '" - << make_property->_getter->_name << "' is suitable!\n"; - return 0; + if (getter == NULL || return_type == NULL) { + cerr << "No instance of getter '" + << fgroup->_name << "' is suitable!\n"; + return 0; + } } InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); @@ -1944,11 +1945,17 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type) { iproperty._name = make_property->get_simple_name(); iproperty._scoped_name = descope(make_property->get_local_name(&parser)); - iproperty._type = get_type(return_type, false); + if (return_type != NULL) { + iproperty._type = get_type(return_type, false); + } else { + iproperty._type = 0; + } - iproperty._flags |= InterrogateElement::F_has_getter; - iproperty._getter = get_function(getter, "", struct_type, - struct_type->get_scope(), 0); + if (getter != NULL) { + iproperty._flags |= InterrogateElement::F_has_getter; + iproperty._getter = get_function(getter, "", struct_type, + struct_type->get_scope(), 0); + } // See if there happens to be a comment before the MAKE_PROPERTY macro. if (make_property->_leading_comment != (CPPCommentBlock *)NULL) { @@ -1958,6 +1965,7 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type) { // Now look for setters. fgroup = make_property->_setter; if (fgroup != NULL) { + CPPFunctionGroup::Instances::const_iterator fi; for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { CPPInstance *function = (*fi); iproperty._flags |= InterrogateElement::F_has_setter; diff --git a/dtool/src/interrogate/interrogate_module.cxx b/dtool/src/interrogate/interrogate_module.cxx index 9292f04b02..9653654629 100644 --- a/dtool/src/interrogate/interrogate_module.cxx +++ b/dtool/src/interrogate/interrogate_module.cxx @@ -25,6 +25,7 @@ #include "panda_getopt_long.h" #include "preprocess_argv.h" #include "pset.h" +#include "vector_string.h" Filename output_code_filename; string module_name; @@ -33,6 +34,7 @@ bool build_c_wrappers = false; bool build_python_wrappers = false; bool build_python_native_wrappers = false; bool track_interpreter = false; +vector_string imports; // Short command-line options. static const char *short_options = ""; @@ -46,6 +48,7 @@ enum CommandOptions { CO_python, CO_python_native, CO_track_interpreter, + CO_import, }; static struct option long_options[] = { @@ -56,6 +59,7 @@ static struct option long_options[] = { { "python", no_argument, NULL, CO_python }, { "python-native", no_argument, NULL, CO_python_native }, { "track-interpreter", no_argument, NULL, CO_track_interpreter }, + { "import", required_argument, NULL, CO_import }, { NULL } }; @@ -113,6 +117,9 @@ int write_python_table_native(ostream &out) { for(ii = libraries.begin(); ii != libraries.end(); ii++) { printf("Referencing Library %s\n", (*ii).c_str()); out << "extern LibraryDef " << *ii << "_moddef;\n"; + out << "extern void Dtool_" << *ii << "_RegisterTypes();\n"; + out << "extern void Dtool_" << *ii << "_ResolveExternals();\n"; + out << "extern void Dtool_" << *ii << "_BuildInstants(PyObject *module);\n"; } out << "\n" @@ -138,6 +145,19 @@ int write_python_table_native(ostream &out) { out << " in_interpreter = 1;\n"; } + vector_string::const_iterator si; + for (si = imports.begin(); si != imports.end(); ++si) { + out << " PyImport_Import(PyUnicode_FromString(\"" << *si << "\"));\n"; + } + + for (ii = libraries.begin(); ii != libraries.end(); ii++) { + out << " Dtool_" << *ii << "_RegisterTypes();\n"; + } + for (ii = libraries.begin(); ii != libraries.end(); ii++) { + out << " Dtool_" << *ii << "_ResolveExternals();\n"; + } + out << "\n"; + out << " LibraryDef *defs[] = {"; for(ii = libraries.begin(); ii != libraries.end(); ii++) { out << "&" << *ii << "_moddef, "; @@ -145,7 +165,15 @@ int write_python_table_native(ostream &out) { out << "NULL};\n" << "\n" - << " return Dtool_PyModuleInitHelper(defs, &py_" << library_name << "_module);\n" + << " PyObject *module = Dtool_PyModuleInitHelper(defs, &py_" << library_name << "_module);\n" + << " if (module != NULL) {\n"; + + for (ii = libraries.begin(); ii != libraries.end(); ii++) { + out << " Dtool_" << *ii << "_BuildInstants(module);\n"; + } + + out << " }\n" + << " return module;\n" << "}\n" << "\n" << "#else // Python 2 case\n" @@ -162,6 +190,18 @@ int write_python_table_native(ostream &out) { out << " in_interpreter = 1;\n"; } + for (si = imports.begin(); si != imports.end(); ++si) { + out << " PyImport_Import(PyUnicode_FromString(\"" << *si << "\"));\n"; + } + + for (ii = libraries.begin(); ii != libraries.end(); ii++) { + out << " Dtool_" << *ii << "_RegisterTypes();\n"; + } + for (ii = libraries.begin(); ii != libraries.end(); ii++) { + out << " Dtool_" << *ii << "_ResolveExternals();\n"; + } + out << "\n"; + out << " LibraryDef *defs[] = {"; for(ii = libraries.begin(); ii != libraries.end(); ii++) { out << "&" << *ii << "_moddef, "; @@ -169,7 +209,14 @@ int write_python_table_native(ostream &out) { out << "NULL};\n" << "\n" - << " Dtool_PyModuleInitHelper(defs, \"" << library_name << "\");\n" + << " PyObject *module = Dtool_PyModuleInitHelper(defs, \"" << library_name << "\");\n" + << " if (module != NULL) {\n"; + + for (ii = libraries.begin(); ii != libraries.end(); ii++) { + out << " Dtool_" << *ii << "_BuildInstants(module);\n"; + } + + out << " }\n" << "}\n" << "#endif\n" << "\n"; @@ -335,6 +382,10 @@ int main(int argc, char *argv[]) { track_interpreter = true; break; + case CO_import: + imports.push_back(optarg); + break; + default: exit(1); } diff --git a/dtool/src/interrogate/typeManager.cxx b/dtool/src/interrogate/typeManager.cxx index fa78d89664..05372ab30c 100644 --- a/dtool/src/interrogate/typeManager.cxx +++ b/dtool/src/interrogate/typeManager.cxx @@ -2570,4 +2570,59 @@ is_local(CPPType *source_type) { return false; */ -}; +} + +//////////////////////////////////////////////////////////////////// +// Function: TypeManager::is_trivial +// Access: Public, Static +// Description: Returns true if the type is trivial (or trivial +// enough for our purposes). +//////////////////////////////////////////////////////////////////// +bool TypeManager:: +is_trivial(CPPType *source_type) { + switch (source_type->get_subtype()) { + case CPPDeclaration::ST_const: + return is_trivial(source_type->as_const_type()->_wrapped_around); + + case CPPDeclaration::ST_reference: + return false; + + case CPPDeclaration::ST_pointer: + return true; + + case CPPDeclaration::ST_simple: + return true; + + case CPPDeclaration::ST_typedef: + return is_trivial(source_type->as_typedef_type()->_type); + + default: + if (source_type->is_trivial()) { + return true; + } else { + // This is a bit of a hack. is_trivial() returns false for types that + // have an empty constructor (since we can't use =default yet). + // For the other classes, it's just convenient to consider them trivial + // even if they aren't, since they are simple enough. + string name = source_type->get_simple_name(); + return (name == "ButtonHandle" || name == "DatagramIterator" || + name == "BitMask" || name == "Filename" || name == "pixel" || + name == "NodePath" || name == "LoaderOptions" || + name == "PointerToArray" || name == "ConstPointerToArray" || + name == "PStatThread" || + (name.size() >= 6 && name.substr(0, 6) == "LPlane") || + (name.size() > 6 && name.substr(0, 6) == "LPoint") || + (name.size() > 7 && name.substr(0, 7) == "LVector") || + (name.size() > 7 && name.substr(0, 7) == "LMatrix") || + (name.size() > 8 && name.substr(0, 8) == "LVecBase") || + (name.size() >= 9 && name.substr(0, 9) == "LParabola") || + (name.size() >= 9 && name.substr(0, 9) == "LRotation") || + (name.size() >= 11 && name.substr(0, 11) == "LQuaternion") || + (name.size() >= 12 && name.substr(0, 12) == "LOrientation") || + (name.size() > 16 && name.substr(0, 16) == "UnalignedLMatrix") || + (name.size() > 17 && name.substr(0, 17) == "UnalignedLVecBase")); + } + } + + return false; +} diff --git a/dtool/src/interrogate/typeManager.h b/dtool/src/interrogate/typeManager.h index 16b9dfda22..848f3907ca 100644 --- a/dtool/src/interrogate/typeManager.h +++ b/dtool/src/interrogate/typeManager.h @@ -146,7 +146,7 @@ public: static bool is_exported(CPPType *type); static bool is_local(CPPType *type); - + static bool is_trivial(CPPType *type); }; #endif diff --git a/dtool/src/interrogatedb/dtool_super_base.cxx b/dtool/src/interrogatedb/dtool_super_base.cxx index d695fb5ef5..84334cf4c8 100644 --- a/dtool/src/interrogatedb/dtool_super_base.cxx +++ b/dtool/src/interrogatedb/dtool_super_base.cxx @@ -21,7 +21,7 @@ class EmptyClass { Define_Module_Class_Private(dtoolconfig, DTOOL_SUPER_BASE, EmptyClass, DTOOL_SUPER_BASE111); static PyObject *GetSuperBase(PyObject *self) { - Py_INCREF(&(Dtool_DTOOL_SUPER_BASE.As_PyTypeObject())); // order is important .. this is used for static functions + Py_INCREF((PyTypeObject *)&Dtool_DTOOL_SUPER_BASE); // order is important .. this is used for static functions return (PyObject *) &Dtool_DTOOL_SUPER_BASE; }; @@ -35,21 +35,21 @@ EXPCL_DTOOLCONFIG void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module if (!initdone) { initdone = true; - Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_dict = PyDict_New(); - PyDict_SetItemString(Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_dict, "DtoolClassDict", Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_dict); + Dtool_DTOOL_SUPER_BASE._PyType.tp_dict = PyDict_New(); + PyDict_SetItemString(Dtool_DTOOL_SUPER_BASE._PyType.tp_dict, "DtoolClassDict", Dtool_DTOOL_SUPER_BASE._PyType.tp_dict); - if (PyType_Ready(&Dtool_DTOOL_SUPER_BASE.As_PyTypeObject()) < 0) { + if (PyType_Ready((PyTypeObject *)&Dtool_DTOOL_SUPER_BASE) < 0) { PyErr_SetString(PyExc_TypeError, "PyType_Ready(Dtool_DTOOL_SUPER_BASE)"); return; } - Py_INCREF(&Dtool_DTOOL_SUPER_BASE.As_PyTypeObject()); + Py_INCREF((PyTypeObject *)&Dtool_DTOOL_SUPER_BASE); - PyDict_SetItemString(Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_dict, "DtoolGetSuperBase", PyCFunction_New(&Dtool_Methods_DTOOL_SUPER_BASE[0], &Dtool_DTOOL_SUPER_BASE.As_PyObject())); + PyDict_SetItemString(Dtool_DTOOL_SUPER_BASE._PyType.tp_dict, "DtoolGetSuperBase", PyCFunction_New(&Dtool_Methods_DTOOL_SUPER_BASE[0], (PyObject *)&Dtool_DTOOL_SUPER_BASE)); } if (module != NULL) { - Py_INCREF(&Dtool_DTOOL_SUPER_BASE.As_PyTypeObject()); - PyModule_AddObject(module, "DTOOL_SUPER_BASE", (PyObject *)&Dtool_DTOOL_SUPER_BASE.As_PyTypeObject()); + Py_INCREF((PyTypeObject *)&Dtool_DTOOL_SUPER_BASE); + PyModule_AddObject(module, "DTOOL_SUPER_BASE", (PyObject *)&Dtool_DTOOL_SUPER_BASE); } } @@ -123,9 +123,12 @@ EXPORT_THIS Dtool_PyTypedObject Dtool_DTOOL_SUPER_BASE = { 0, 0, }, + TypeHandle::none(), + Dtool_PyModuleClassInit_DTOOL_SUPER_BASE, Dtool_UpcastInterface_DTOOL_SUPER_BASE, Dtool_DowncastInterface_DTOOL_SUPER_BASE, - TypeHandle::none(), + NULL, + NULL, }; #endif // HAVE_PYTHON diff --git a/dtool/src/interrogatedb/interrogateType.cxx b/dtool/src/interrogatedb/interrogateType.cxx index 3c69995c99..d0ce756fa4 100644 --- a/dtool/src/interrogatedb/interrogateType.cxx +++ b/dtool/src/interrogatedb/interrogateType.cxx @@ -269,23 +269,3 @@ remap_indices(const IndexRemapper &remap) { } } - - -//////////////////////////////////////////////////////////////////// -// Function: GetRunTimeDictionary -//////////////////////////////////////////////////////////////////// -EXPCL_DTOOLCONFIG RunTimeTypeDictionary & GetRunTimeDictionary() -{ - static RunTimeTypeDictionary dict; - return dict; -}; - -//////////////////////////////////////////////////////////////////// -// Function: GetRunTimeTypeList -//////////////////////////////////////////////////////////////////// -EXPCL_DTOOLCONFIG RunTimeTypeList & GetRunTimeTypeList() -{ - static RunTimeTypeList list; - return list; -}; - diff --git a/dtool/src/interrogatedb/interrogateType.h b/dtool/src/interrogatedb/interrogateType.h index 8abf807f02..365c2a2d40 100644 --- a/dtool/src/interrogatedb/interrogateType.h +++ b/dtool/src/interrogatedb/interrogateType.h @@ -231,14 +231,4 @@ 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; - -EXPCL_DTOOLCONFIG RunTimeTypeDictionary & GetRunTimeDictionary(); -EXPCL_DTOOLCONFIG RunTimeTypeList & GetRunTimeTypeList(); - - #endif diff --git a/dtool/src/interrogatedb/py_panda.cxx b/dtool/src/interrogatedb/py_panda.cxx index 11af0c1ace..91b0dd9f1a 100644 --- a/dtool/src/interrogatedb/py_panda.cxx +++ b/dtool/src/interrogatedb/py_panda.cxx @@ -26,6 +26,10 @@ PyMemberDef standard_type_members[] = { {NULL} /* Sentinel */ }; +static RuntimeTypeMap runtime_type_map; +static RuntimeTypeSet runtime_type_set; +static NamedTypeMap named_type_map; + //////////////////////////////////////////////////////////////////// // Function: DtoolCanThisBeAPandaInstance // Description: Given a valid (non-NULL) PyObject, does a simple @@ -360,7 +364,7 @@ PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject & ///////////////////////////////////////////// // ask class to allocate an instance.. ///////////////////////////////////////////// - Dtool_PyInstDef *self = (Dtool_PyInstDef *) target_class->As_PyTypeObject().tp_new(&target_class->As_PyTypeObject(), NULL, NULL); + Dtool_PyInstDef *self = (Dtool_PyInstDef *) target_class->_PyType.tp_new(&target_class->_PyType, NULL, NULL); if (self != NULL) { self->_ptr_to_object = new_local_this; self->_memory_rules = memory_rules; @@ -377,7 +381,7 @@ PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject & // if we get this far .. just wrap the thing in the known type ?? // better than aborting...I guess.... ///////////////////////////////////////////////////// - Dtool_PyInstDef *self = (Dtool_PyInstDef *) known_class_type.As_PyTypeObject().tp_new(&known_class_type.As_PyTypeObject(), NULL, NULL); + Dtool_PyInstDef *self = (Dtool_PyInstDef *) known_class_type._PyType.tp_new(&known_class_type._PyType, NULL, NULL); if (self != NULL) { self->_ptr_to_object = local_this_in; self->_memory_rules = memory_rules; @@ -401,7 +405,7 @@ PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTypedObject &in_class } Dtool_PyTypedObject *classdef = &in_classdef; - Dtool_PyInstDef *self = (Dtool_PyInstDef *) classdef->As_PyTypeObject().tp_new(&classdef->As_PyTypeObject(), NULL, NULL); + Dtool_PyInstDef *self = (Dtool_PyInstDef *) classdef->_PyType.tp_new(&classdef->_PyType, NULL, NULL); if (self != NULL) { self->_ptr_to_object = local_this; self->_memory_rules = memory_rules; @@ -446,42 +450,97 @@ void Dtool_Accum_MethDefs(PyMethodDef in[], MethodDefmap &themap) { // /////////////////////////////////////////////////////////////////////////////// void -RegisterRuntimeClass(Dtool_PyTypedObject *otype, int class_id) { - if (class_id == 0) { +RegisterNamedClass(const string &name, Dtool_PyTypedObject &otype) { + pair result = + named_type_map.insert(NamedTypeMap::value_type(name, &otype)); + + if (!result.second) { + // There was already a class with this name in the dictionary. interrogatedb_cat.warning() - << "Class " << otype->_PyType.tp_name + << "Double definition for class " << name << "\n"; + } +} + +void +RegisterRuntimeTypedClass(Dtool_PyTypedObject &otype) { + int type_index = otype._type.get_index(); + + if (type_index == 0) { + interrogatedb_cat.warning() + << "Class " << otype._PyType.tp_name << " has a zero TypeHandle value; check that init_type() is called.\n"; - } else if (class_id > 0) { - RunTimeTypeDictionary &dict = GetRunTimeDictionary(); - pair result = - dict.insert(RunTimeTypeDictionary::value_type(class_id, otype)); + } else if (type_index < 0 || type_index >= TypeRegistry::ptr()->get_num_typehandles()) { + interrogatedb_cat.warning() + << "Class " << otype._PyType.tp_name + << " has an illegal TypeHandle value; check that init_type() is called.\n"; + + } else { + pair result = + runtime_type_map.insert(RuntimeTypeMap::value_type(type_index, &otype)); if (!result.second) { - // There was already an entry in the dictionary for class_id. + // There was already an entry in the dictionary for type_index. Dtool_PyTypedObject *other_type = (*result.first).second; interrogatedb_cat.warning() - << "Classes " << otype->_PyType.tp_name + << "Classes " << otype._PyType.tp_name << " and " << other_type->_PyType.tp_name - << " share the same TypeHandle value (" << class_id + << " share the same TypeHandle value (" << type_index << "); check class definitions.\n"; } else { - GetRunTimeTypeList().insert(class_id); - otype->_type = TypeRegistry::ptr()->find_type_by_id(class_id); + runtime_type_set.insert(type_index); } } } +Dtool_PyTypedObject * +LookupNamedClass(const string &name) { + NamedTypeMap::const_iterator it; + it = named_type_map.find(name); + + if (it == named_type_map.end()) { + // Find a type named like this in the type registry. + TypeHandle handle = TypeRegistry::ptr()->find_type(name); + if (handle.get_index() > 0) { + RuntimeTypeMap::const_iterator it2; + it2 = runtime_type_map.find(handle.get_index()); + if (it2 != runtime_type_map.end()) { + return it2->second; + } + } + + interrogatedb_cat.error() + << "Attempt to use type " << name << " which has not yet been defined!\n"; + return NULL; + } else { + return it->second; + } +} + +Dtool_PyTypedObject * +LookupRuntimeTypedClass(TypeHandle handle) { + RuntimeTypeMap::const_iterator it; + it = runtime_type_map.find(handle.get_index()); + + if (it == runtime_type_map.end()) { + interrogatedb_cat.error() + << "Attempt to use type " << handle << " which has not yet been defined!\n"; + return NULL; + } else { + return it->second; + } +} + /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// Dtool_PyTypedObject *Dtool_RuntimeTypeDtoolType(int type) { - RunTimeTypeDictionary::iterator di = GetRunTimeDictionary().find(type); - if (di != GetRunTimeDictionary().end()) { + RuntimeTypeMap::iterator di = runtime_type_map.find(type); + if (di != runtime_type_map.end()) { return di->second; } else { - int type2 = get_best_parent_from_Set(type, GetRunTimeTypeList()); - di = GetRunTimeDictionary().find(type2); - if (di != GetRunTimeDictionary().end()) { + int type2 = get_best_parent_from_Set(type, runtime_type_set); + di = runtime_type_map.find(type2); + if (di != runtime_type_map.end()) { return di->second; } } @@ -526,11 +585,6 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) { #endif } - // the constant inits... enums, classes ... - for (int y = 0; defs[y] != NULL; y++) { - defs[y]->_constants(module); - } - PyModule_AddIntConstant(module, "Dtool_PyNativeInterface", 1); return module; } @@ -710,33 +764,6 @@ PyObject *DTOOL_PyObject_RichCompare(PyObject *v1, PyObject *v2, int op) { return PyBool_FromLong(result); } -PyObject *make_list_for_item(PyObject *self, const char *num_name, - const char *element_name) { - PyObject *num_result = PyObject_CallMethod(self, (char *)num_name, (char *)"()"); - if (num_result == NULL) { - return NULL; - } - - Py_ssize_t num_elements; -#if PY_MAJOR_VERSION >= 3 - num_elements = PyLong_AsSsize_t(num_result); -#else - num_elements = PyInt_AsSsize_t(num_result); -#endif - Py_DECREF(num_result); - - PyObject *list = PyList_New(num_elements); - for (int i = 0; i < num_elements; ++i) { - PyObject *element = PyObject_CallMethod(self, (char *)element_name, (char *)"(i)", i); - if (element == NULL) { - Py_DECREF(list); - return NULL; - } - PyList_SET_ITEM(list, i, element); - } - return list; -} - //////////////////////////////////////////////////////////////////// // Function: copy_from_make_copy // Description: This is a support function for a synthesized diff --git a/dtool/src/interrogatedb/py_panda.h b/dtool/src/interrogatedb/py_panda.h index e6847359c3..ad58b775b5 100644 --- a/dtool/src/interrogatedb/py_panda.h +++ b/dtool/src/interrogatedb/py_panda.h @@ -143,17 +143,17 @@ using namespace std; /////////////////////////////////////////////////////////////////////////////////// struct Dtool_PyTypedObject; -typedef std::map RunTimeTypeDictionary; -typedef std::set RunTimeTypeList; - -EXPCL_DTOOLCONFIG RunTimeTypeDictionary &GetRunTimeDictionary(); -EXPCL_DTOOLCONFIG RunTimeTypeList &GetRunTimeTypeList(); +typedef std::map RuntimeTypeMap; +typedef std::set RuntimeTypeSet; +typedef std::map NamedTypeMap; ////////////////////////////////////////////////////////// // used to stamp dtool instance.. #define PY_PANDA_SIGNATURE 0xbeaf typedef void *(*UpcastFunction)(PyObject *,Dtool_PyTypedObject *); typedef void *(*DowncastFunction)(void *, Dtool_PyTypedObject *); +typedef void *(*CoerceFunction)(PyObject *, void *); +typedef void (*ModuleClassInitFunction)(PyObject *module); //inline Dtool_PyTypedObject * Dtool_RuntimeTypeDtoolType(int type); //inline void Dtool_Deallocate_General(PyObject * self); @@ -196,16 +196,16 @@ struct Dtool_PyTypedObject { // Standard Python Features.. PyTypeObject _PyType; - // My Class Level Features.. - UpcastFunction _Dtool_UpcastInterface; // The Upcast Function By Slot - DowncastFunction _Dtool_DowncastInterface; // The Downcast Function By Slot - // May be TypeHandle::none() to indicate a non-TypedObject class. TypeHandle _type; - // some convenience functions.. - inline PyTypeObject &As_PyTypeObject() { return _PyType; }; - inline PyObject &As_PyObject() { return (PyObject &)_PyType; }; + ModuleClassInitFunction _Dtool_ModuleClassInit; + + UpcastFunction _Dtool_UpcastInterface; // The Upcast Function By Slot + DowncastFunction _Dtool_DowncastInterface; // The Downcast Function By Slot + + CoerceFunction _Dtool_ConstCoerce; + CoerceFunction _Dtool_Coerce; }; // This is now simply a forward declaration. The actual definition is created @@ -217,7 +217,7 @@ struct Dtool_PyTypedObject { // More Macro(s) to Implement class functions.. Usually used if C++ needs type information //////////////////////////////////////////////////////////////////////// #define Define_Dtool_new(CLASS_NAME,CNAME)\ -PyObject *Dtool_new_##CLASS_NAME(PyTypeObject *type, PyObject *args, PyObject *kwds) {\ +static PyObject *Dtool_new_##CLASS_NAME(PyTypeObject *type, PyObject *args, PyObject *kwds) {\ (void) args; (void) kwds;\ PyObject *self = type->tp_alloc(type, 0);\ ((Dtool_PyInstDef *)self)->_signature = PY_PANDA_SIGNATURE;\ @@ -291,7 +291,11 @@ EXPCL_DTOOLCONFIG bool DtoolCanThisBeAPandaInstance(PyObject *self); // /////////////////////////////////////////////////////////////////////////////// -EXPCL_DTOOLCONFIG void RegisterRuntimeClass(Dtool_PyTypedObject *otype, int class_id); +EXPCL_DTOOLCONFIG void RegisterNamedClass(const string &name, Dtool_PyTypedObject &otype); +EXPCL_DTOOLCONFIG void RegisterRuntimeTypedClass(Dtool_PyTypedObject &otype); + +EXPCL_DTOOLCONFIG Dtool_PyTypedObject *LookupNamedClass(const string &name); +EXPCL_DTOOLCONFIG Dtool_PyTypedObject *LookupRuntimeTypedClass(TypeHandle handle); /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// @@ -305,7 +309,7 @@ EXPCL_DTOOLCONFIG Dtool_PyTypedObject *Dtool_RuntimeTypeDtoolType(int type); // with these as the generated code depends on how this is set // up.. //////////////////////////////////////////////////////////////////////// -EXPCL_DTOOLCONFIG void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject * classdef, void ** answer); +EXPCL_DTOOLCONFIG void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *classdef, void **answer); EXPCL_DTOOLCONFIG void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const string &function_name, bool const_ok, bool report_errors); @@ -407,11 +411,9 @@ template INLINE PyObject *DTool_CreatePyInstanceTyped(T *obj, bool memo //struct Dtool_PyTypedObject Dtool_##CLASS_NAME; #define Define_Module_Class_Internal(MODULE_NAME,CLASS_NAME,CNAME)\ -extern EXPORT_THIS Dtool_PyTypedObject Dtool_##CLASS_NAME;\ -int Dtool_Init_##CLASS_NAME(PyObject *self, PyObject *args, PyObject *kwds);\ -PyObject * Dtool_new_##CLASS_NAME(PyTypeObject *type, PyObject *args, PyObject *kwds);\ -void * Dtool_UpcastInterface_##CLASS_NAME(PyObject *self, Dtool_PyTypedObject *requested_type);\ -void * Dtool_DowncastInterface_##CLASS_NAME(void *self, Dtool_PyTypedObject *requested_type); +extern struct Dtool_PyTypedObject Dtool_##CLASS_NAME;\ +static int Dtool_Init_##CLASS_NAME(PyObject *self, PyObject *args, PyObject *kwds);\ +static PyObject *Dtool_new_##CLASS_NAME(PyTypeObject *type, PyObject *args, PyObject *kwds); /////////////////////////////////////////////////////////////////////////////// #define Define_Module_Class(MODULE_NAME,CLASS_NAME,CNAME,PUBLIC_NAME)\ @@ -460,10 +462,7 @@ EXPCL_DTOOLCONFIG void Dtool_Accum_MethDefs(PyMethodDef in[], MethodDefmap &them /// fallowing structors and code.. along with the support of interigate_module /////////////////////////////////////////////////////////////////////////////// struct LibraryDef { - typedef void (*ConstantFunction)(PyObject *); - PyMethodDef *_methods; - ConstantFunction _constants; }; /////////////////////////////////////////////////////////////////////////////// @@ -505,10 +504,6 @@ EXPCL_DTOOLCONFIG int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2); EXPCL_DTOOLCONFIG PyObject *DTOOL_PyObject_RichCompare(PyObject *v1, PyObject *v2, int op); -EXPCL_DTOOLCONFIG PyObject * -make_list_for_item(PyObject *self, const char *num_name, - const char *element_name); - EXPCL_DTOOLCONFIG PyObject * copy_from_make_copy(PyObject *self); @@ -527,6 +522,8 @@ PyLongOrInt_FromUnsignedLong(unsigned long value); EXPCL_DTOOLCONFIG extern struct Dtool_PyTypedObject Dtool_DTOOL_SUPER_BASE; EXPCL_DTOOLCONFIG extern void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module); +#define Dtool_Ptr_DTOOL_SUPER_BASE (&Dtool_DTOOL_SUPER_BASE) + #endif // HAVE_PYTHON && !CPPPARSER #endif // PY_PANDA_H_ diff --git a/dtool/src/parser-inc/iostream b/dtool/src/parser-inc/iostream index 87fd92ebcd..5cd485d04d 100644 --- a/dtool/src/parser-inc/iostream +++ b/dtool/src/parser-inc/iostream @@ -43,6 +43,9 @@ __published: static const openmode in; static const openmode out; static const openmode trunc; +protected: + // Force this to be a non-trivial type. + ios_base() {}; }; class ios : public ios_base { __published: diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 5aff172e2a..8d081ebf5f 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -1411,7 +1411,10 @@ def CompileImod(wobj, wsrc, opts): # Assume that interrogate_module is on the PATH somewhere. cmd = 'interrogate_module' - cmd += ' -oc ' + woutc + ' -module ' + module + ' -library ' + library + ' -python-native ' + cmd += ' -oc ' + woutc + ' -module ' + module + ' -library ' + library + ' -python-native' + importmod = GetValueOption(opts, "IMPORT:") + if importmod: + cmd += ' -import ' + importmod for x in wsrc: cmd += ' ' + BracketNameWithQuotes(x) oscmd(cmd) CompileCxx(wobj,woutc,opts) @@ -1592,20 +1595,13 @@ def CompileLink(dll, obj, opts): cmd = cxx + ' -undefined dynamic_lookup' if ("BUNDLE" in opts): cmd += ' -bundle ' else: - if GetOrigExt(dll) == ".pyd": - install_name = '@loader_path/../panda3d/' + os.path.basename(dll) - else: - install_name = os.path.basename(dll) + install_name = os.path.basename(dll) cmd += ' -dynamiclib -install_name ' + install_name cmd += ' -compatibility_version ' + MAJOR_VERSION + ' -current_version ' + VERSION cmd += ' -o ' + dll + ' -L' + GetOutputDir() + '/lib -L' + GetOutputDir() + '/tmp' else: cmd = cxx + ' -shared' if ("MODULE" not in opts): cmd += " -Wl,-soname=" + os.path.basename(dll) - if GetOrigExt(dll) == ".pyd" and not os.path.basename(dll).startswith('core'): - # Tell the other libraries where to find core.so. - # Not sure if this is the best way to do that, but it works. - cmd += " -Wl,-rpath '-Wl,$ORIGIN'" cmd += ' -o ' + dll + ' -L' + GetOutputDir() + '/lib -L' + GetOutputDir() + '/tmp' for x in obj: @@ -3856,12 +3852,11 @@ if (PkgSkip("VISION") == 0) and (not RUNTIME): TargetAdd('vision_module.obj', input='libp3vision.in') TargetAdd('vision_module.obj', opts=OPTS) - TargetAdd('vision_module.obj', opts=['IMOD:panda3d.vision', 'ILIB:vision']) + TargetAdd('vision_module.obj', opts=['IMOD:panda3d.vision', 'ILIB:vision', 'IMPORT:panda3d.core']) TargetAdd('vision.pyd', input='vision_module.obj') TargetAdd('vision.pyd', input='libp3vision_igate.obj') TargetAdd('vision.pyd', input='libp3vision.dll') - TargetAdd('vision.pyd', input='core.pyd') TargetAdd('vision.pyd', input=COMMON_PANDA_LIBS) TargetAdd('vision.pyd', opts=['PYTHON']) @@ -3887,13 +3882,12 @@ if (PkgSkip("ROCKET") == 0) and (not RUNTIME): TargetAdd('rocket_module.obj', input='libp3rocket.in') TargetAdd('rocket_module.obj', opts=OPTS) - TargetAdd('rocket_module.obj', opts=['IMOD:panda3d.rocket', 'ILIB:rocket']) + TargetAdd('rocket_module.obj', opts=['IMOD:panda3d.rocket', 'ILIB:rocket', 'IMPORT:panda3d.core']) TargetAdd('rocket.pyd', input='rocket_module.obj') TargetAdd('rocket.pyd', input='libp3rocket_igate.obj') TargetAdd('rocket.pyd', input='p3rocket_rocketRegion_ext.obj') TargetAdd('rocket.pyd', input='libp3rocket.dll') - TargetAdd('rocket.pyd', input='core.pyd') TargetAdd('rocket.pyd', input=COMMON_PANDA_LIBS) TargetAdd('rocket.pyd', opts=['PYTHON', 'ROCKET']) @@ -3915,12 +3909,11 @@ if PkgSkip("AWESOMIUM") == 0 and not RUNTIME: TargetAdd('awesomium_module.obj', input='libp3awesomium.in') TargetAdd('awesomium_module.obj', opts=OPTS) - TargetAdd('awesomium_module.obj', opts=['IMOD:panda3d.awesomium', 'ILIB:awesomium']) + TargetAdd('awesomium_module.obj', opts=['IMOD:panda3d.awesomium', 'ILIB:awesomium', 'IMPORT:panda3d.core']) TargetAdd('awesomium.pyd', input='awesomium_module.obj') TargetAdd('awesomium.pyd', input='libp3awesomium_igate.obj') TargetAdd('awesomium.pyd', input='libp3awesomium.dll') - TargetAdd('awesomium.pyd', input='core.pyd') TargetAdd('awesomium.pyd', input=COMMON_PANDA_LIBS) TargetAdd('awesomium.pyd', opts=['PYTHON']) @@ -3949,12 +3942,11 @@ if (PkgSkip('SKEL')==0) and (not RUNTIME): TargetAdd('libpandaskel.dll', opts=OPTS) TargetAdd('skel_module.obj', input='libp3skel.in') - TargetAdd('skel_module.obj', opts=['IMOD:panda3d.skel', 'ILIB:skel']) + TargetAdd('skel_module.obj', opts=['IMOD:panda3d.skel', 'ILIB:skel', 'IMPORT:panda3d.core']) TargetAdd('skel.pyd', input='skel_module.obj') TargetAdd('skel.pyd', input='libp3skel_igate.obj') TargetAdd('skel.pyd', input='libpandaskel.dll') - TargetAdd('skel.pyd', input='core.pyd') TargetAdd('skel.pyd', input=COMMON_PANDA_LIBS) TargetAdd('skel.pyd', opts=['PYTHON']) @@ -3988,12 +3980,11 @@ if (PkgSkip('PANDAFX')==0) and (not RUNTIME): OPTS=['DIR:panda/metalibs/pandafx', 'DIR:panda/src/distort', 'NVIDIACG'] TargetAdd('fx_module.obj', input='libp3distort.in') TargetAdd('fx_module.obj', opts=OPTS) - TargetAdd('fx_module.obj', opts=['IMOD:panda3d.fx', 'ILIB:fx']) + TargetAdd('fx_module.obj', opts=['IMOD:panda3d.fx', 'ILIB:fx', 'IMPORT:panda3d.core']) TargetAdd('fx.pyd', input='fx_module.obj') TargetAdd('fx.pyd', input='libp3distort_igate.obj') TargetAdd('fx.pyd', input='libpandafx.dll') - TargetAdd('fx.pyd', input='core.pyd') TargetAdd('fx.pyd', input=COMMON_PANDA_LIBS) TargetAdd('fx.pyd', opts=['PYTHON']) @@ -4016,12 +4007,11 @@ if (PkgSkip("VRPN")==0 and not RUNTIME): TargetAdd('vrpn_module.obj', input='libp3vrpn.in') TargetAdd('vrpn_module.obj', opts=OPTS) - TargetAdd('vrpn_module.obj', opts=['IMOD:panda3d.vrpn', 'ILIB:vrpn']) + TargetAdd('vrpn_module.obj', opts=['IMOD:panda3d.vrpn', 'ILIB:vrpn', 'IMPORT:panda3d.core']) TargetAdd('vrpn.pyd', input='vrpn_module.obj') TargetAdd('vrpn.pyd', input='libp3vrpn_igate.obj') TargetAdd('vrpn.pyd', input='libp3vrpn.dll') - TargetAdd('vrpn.pyd', input='core.pyd') TargetAdd('vrpn.pyd', input=COMMON_PANDA_LIBS) TargetAdd('vrpn.pyd', opts=['PYTHON']) @@ -4249,14 +4239,13 @@ if (not RUNTIME): TargetAdd('egg_module.obj', input='libp3egg2pg.in') TargetAdd('egg_module.obj', input='libp3egg.in') TargetAdd('egg_module.obj', opts=OPTS) - TargetAdd('egg_module.obj', opts=['IMOD:panda3d.egg', 'ILIB:egg']) + TargetAdd('egg_module.obj', opts=['IMOD:panda3d.egg', 'ILIB:egg', 'IMPORT:panda3d.core']) TargetAdd('egg.pyd', input='egg_module.obj') TargetAdd('egg.pyd', input='p3egg_eggGroupNode_ext.obj') TargetAdd('egg.pyd', input='libp3egg_igate.obj') TargetAdd('egg.pyd', input='libp3egg2pg_igate.obj') TargetAdd('egg.pyd', input='libpandaegg.dll') - TargetAdd('egg.pyd', input='core.pyd') TargetAdd('egg.pyd', input=COMMON_PANDA_LIBS) TargetAdd('egg.pyd', opts=['PYTHON']) @@ -4416,13 +4405,12 @@ if (PkgSkip("ODE")==0 and not RUNTIME): OPTS=['DIR:panda/metalibs/pandaode', 'ODE'] TargetAdd('ode_module.obj', input='libpandaode.in') TargetAdd('ode_module.obj', opts=OPTS) - TargetAdd('ode_module.obj', opts=['IMOD:panda3d.ode', 'ILIB:ode']) + TargetAdd('ode_module.obj', opts=['IMOD:panda3d.ode', 'ILIB:ode', 'IMPORT:panda3d.core']) TargetAdd('ode.pyd', input='ode_module.obj') TargetAdd('ode.pyd', input='libpandaode_igate.obj') TargetAdd('ode.pyd', input='p3ode_ext_composite.obj') TargetAdd('ode.pyd', input='libpandaode.dll') - TargetAdd('ode.pyd', input='core.pyd') TargetAdd('ode.pyd', input=COMMON_PANDA_LIBS) TargetAdd('ode.pyd', opts=['PYTHON', 'WINUSER', 'ODE']) @@ -4454,12 +4442,11 @@ if (PkgSkip("BULLET")==0 and not RUNTIME): OPTS=['DIR:panda/metalibs/pandabullet', 'BULLET'] TargetAdd('bullet_module.obj', input='libpandabullet.in') TargetAdd('bullet_module.obj', opts=OPTS) - TargetAdd('bullet_module.obj', opts=['IMOD:panda3d.bullet', 'ILIB:bullet']) + TargetAdd('bullet_module.obj', opts=['IMOD:panda3d.bullet', 'ILIB:bullet', 'IMPORT:panda3d.core']) TargetAdd('bullet.pyd', input='bullet_module.obj') TargetAdd('bullet.pyd', input='libpandabullet_igate.obj') TargetAdd('bullet.pyd', input='libpandabullet.dll') - TargetAdd('bullet.pyd', input='core.pyd') TargetAdd('bullet.pyd', input=COMMON_PANDA_LIBS) TargetAdd('bullet.pyd', opts=['PYTHON', 'WINUSER', 'BULLET']) @@ -4493,12 +4480,11 @@ if (PkgSkip("PHYSX")==0): OPTS=['DIR:panda/metalibs/pandaphysx', 'PHYSX', 'NOARCH:PPC'] TargetAdd('physx_module.obj', input='libpandaphysx.in') TargetAdd('physx_module.obj', opts=OPTS) - TargetAdd('physx_module.obj', opts=['IMOD:panda3d.physx', 'ILIB:physx']) + TargetAdd('physx_module.obj', opts=['IMOD:panda3d.physx', 'ILIB:physx', 'IMPORT:panda3d.core']) TargetAdd('physx.pyd', input='physx_module.obj') TargetAdd('physx.pyd', input='libpandaphysx_igate.obj') TargetAdd('physx.pyd', input='libpandaphysx.dll') - TargetAdd('physx.pyd', input='core.pyd') TargetAdd('physx.pyd', input=COMMON_PANDA_LIBS) TargetAdd('physx.pyd', opts=['PYTHON', 'WINUSER', 'PHYSX', 'NOARCH:PPC']) @@ -4559,14 +4545,13 @@ if (PkgSkip("PANDAPHYSICS")==0) and (not RUNTIME): if (PkgSkip("PANDAPARTICLESYSTEM")==0): TargetAdd('physics_module.obj', input='libp3particlesystem.in') TargetAdd('physics_module.obj', opts=OPTS) - TargetAdd('physics_module.obj', opts=['IMOD:panda3d.physics', 'ILIB:physics']) + TargetAdd('physics_module.obj', opts=['IMOD:panda3d.physics', 'ILIB:physics', 'IMPORT:panda3d.core']) TargetAdd('physics.pyd', input='physics_module.obj') TargetAdd('physics.pyd', input='libp3physics_igate.obj') if (PkgSkip("PANDAPARTICLESYSTEM")==0): TargetAdd('physics.pyd', input='libp3particlesystem_igate.obj') TargetAdd('physics.pyd', input='libpandaphysics.dll') - TargetAdd('physics.pyd', input='core.pyd') TargetAdd('physics.pyd', input=COMMON_PANDA_LIBS) TargetAdd('physics.pyd', opts=['PYTHON']) @@ -4816,7 +4801,7 @@ if (PkgSkip("DIRECT")==0): TargetAdd('direct_module.obj', input='libp3interval.in') TargetAdd('direct_module.obj', input='libp3distributed.in') TargetAdd('direct_module.obj', opts=OPTS) - TargetAdd('direct_module.obj', opts=['IMOD:panda3d.direct', 'ILIB:direct']) + TargetAdd('direct_module.obj', opts=['IMOD:panda3d.direct', 'ILIB:direct', 'IMPORT:panda3d.core']) TargetAdd('direct.pyd', input='libp3dcparser_igate.obj') TargetAdd('direct.pyd', input='libp3showbase_igate.obj') @@ -4826,7 +4811,6 @@ if (PkgSkip("DIRECT")==0): TargetAdd('direct.pyd', input='direct_module.obj') TargetAdd('direct.pyd', input='libp3direct.dll') - TargetAdd('direct.pyd', input='core.pyd') TargetAdd('direct.pyd', input=COMMON_PANDA_LIBS) TargetAdd('direct.pyd', opts=['PYTHON', 'OPENSSL', 'WINUSER', 'WINGDI']) @@ -6026,12 +6010,11 @@ if (PkgSkip("CONTRIB")==0 and not RUNTIME): TargetAdd('ai_module.obj', input='libpandaai.in') TargetAdd('ai_module.obj', opts=OPTS) - TargetAdd('ai_module.obj', opts=['IMOD:panda3d.ai', 'ILIB:ai']) + TargetAdd('ai_module.obj', opts=['IMOD:panda3d.ai', 'ILIB:ai', 'IMPORT:panda3d.core']) TargetAdd('ai.pyd', input='ai_module.obj') TargetAdd('ai.pyd', input='libpandaai_igate.obj') TargetAdd('ai.pyd', input='libpandaai.dll') - TargetAdd('ai.pyd', input='core.pyd') TargetAdd('ai.pyd', input=COMMON_PANDA_LIBS) TargetAdd('ai.pyd', opts=['PYTHON']) diff --git a/panda/src/bullet/bulletRigidBodyNode.h b/panda/src/bullet/bulletRigidBodyNode.h index 73ba5568a3..309e2386a1 100644 --- a/panda/src/bullet/bulletRigidBodyNode.h +++ b/panda/src/bullet/bulletRigidBodyNode.h @@ -33,7 +33,7 @@ class BulletShape; class EXPCL_PANDABULLET BulletRigidBodyNode : public BulletBodyNode { PUBLISHED: - BulletRigidBodyNode(const char *name="rigid"); + explicit BulletRigidBodyNode(const char *name="rigid"); INLINE ~BulletRigidBodyNode(); // Mass & inertia diff --git a/panda/src/egg/eggGroupNode.h b/panda/src/egg/eggGroupNode.h index ffdfcb304c..b7c318941b 100644 --- a/panda/src/egg/eggGroupNode.h +++ b/panda/src/egg/eggGroupNode.h @@ -26,6 +26,7 @@ #include "luse.h" #include "globPattern.h" #include "plist.h" +#include "bamCacheRecord.h" class EggTextureCollection; class EggMaterialCollection; @@ -33,7 +34,6 @@ class EggPolygon; class EggVertex; class EggVertexPool; class DSearchPath; -class BamCacheRecord; //////////////////////////////////////////////////////////////////// // Class : EggGroupNode diff --git a/panda/src/express/memoryUsagePointers_ext.cxx b/panda/src/express/memoryUsagePointers_ext.cxx index eee3b5d0e6..63713cc907 100644 --- a/panda/src/express/memoryUsagePointers_ext.cxx +++ b/panda/src/express/memoryUsagePointers_ext.cxx @@ -17,9 +17,9 @@ #if defined(HAVE_PYTHON) && defined(DO_MEMORY_USAGE) #ifndef CPPPARSER -extern EXPCL_PANDAEXPRESS Dtool_PyTypedObject Dtool_TypedObject; -extern EXPCL_PANDAEXPRESS Dtool_PyTypedObject Dtool_TypedReferenceCount; -extern EXPCL_PANDAEXPRESS Dtool_PyTypedObject Dtool_ReferenceCount; +extern Dtool_PyTypedObject Dtool_TypedObject; +extern Dtool_PyTypedObject Dtool_TypedReferenceCount; +extern Dtool_PyTypedObject Dtool_ReferenceCount; #endif // CPPPARSER //////////////////////////////////////////////////////////////////// diff --git a/panda/src/express/namable.I b/panda/src/express/namable.I index adad9ec1e9..8d3e0b438d 100644 --- a/panda/src/express/namable.I +++ b/panda/src/express/namable.I @@ -45,6 +45,19 @@ operator = (const Namable &other) { return *this; } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: Namable::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Namable &Namable:: +operator = (Namable &&other) NOEXCEPT { + _name = MOVE(other._name); + return *this; +} +#endif + //////////////////////////////////////////////////////////////////// // Function: Namable::set_name // Access: Public diff --git a/panda/src/express/namable.h b/panda/src/express/namable.h index 9c756827d2..84e01b0919 100644 --- a/panda/src/express/namable.h +++ b/panda/src/express/namable.h @@ -28,10 +28,14 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDAEXPRESS Namable : public MemoryBase { PUBLISHED: - INLINE Namable(const string &initial_name = ""); + INLINE explicit Namable(const string &initial_name = ""); INLINE Namable(const Namable ©); INLINE Namable &operator = (const Namable &other); +#ifdef USE_MOVE_SEMANTICS + INLINE Namable &operator = (Namable &&other) NOEXCEPT; +#endif + INLINE void set_name(const string &name); INLINE void clear_name(); INLINE bool has_name() const; diff --git a/panda/src/gobj/geom.h b/panda/src/gobj/geom.h index 35337bbfcc..5e5b269f10 100644 --- a/panda/src/gobj/geom.h +++ b/panda/src/gobj/geom.h @@ -60,7 +60,7 @@ protected: virtual PT(CopyOnWriteObject) make_cow_copy(); PUBLISHED: - Geom(const GeomVertexData *data); + explicit Geom(const GeomVertexData *data); protected: Geom(const Geom ©); diff --git a/panda/src/gobj/geomVertexArrayData.h b/panda/src/gobj/geomVertexArrayData.h index e0aebb95e5..58ffbb6b46 100644 --- a/panda/src/gobj/geomVertexArrayData.h +++ b/panda/src/gobj/geomVertexArrayData.h @@ -68,8 +68,8 @@ protected: virtual PT(CopyOnWriteObject) make_cow_copy(); PUBLISHED: - GeomVertexArrayData(const GeomVertexArrayFormat *array_format, - UsageHint usage_hint); + explicit GeomVertexArrayData(const GeomVertexArrayFormat *array_format, + UsageHint usage_hint); GeomVertexArrayData(const GeomVertexArrayData ©); void operator = (const GeomVertexArrayData ©); virtual ~GeomVertexArrayData(); diff --git a/panda/src/gobj/geomVertexData.h b/panda/src/gobj/geomVertexData.h index 034018430a..4c91761d52 100644 --- a/panda/src/gobj/geomVertexData.h +++ b/panda/src/gobj/geomVertexData.h @@ -80,12 +80,12 @@ protected: virtual PT(CopyOnWriteObject) make_cow_copy(); PUBLISHED: - GeomVertexData(const string &name, - const GeomVertexFormat *format, - UsageHint usage_hint); + explicit GeomVertexData(const string &name, + const GeomVertexFormat *format, + UsageHint usage_hint); GeomVertexData(const GeomVertexData ©); - GeomVertexData(const GeomVertexData ©, - const GeomVertexFormat *format); + explicit GeomVertexData(const GeomVertexData ©, + const GeomVertexFormat *format); void operator = (const GeomVertexData ©); virtual ~GeomVertexData(); ALLOC_DELETED_CHAIN(GeomVertexData); diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index 5381e5af26..d3fc0c4bb8 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -43,6 +43,7 @@ #include "pnmImage.h" #include "colorSpace.h" #include "geomEnums.h" +#include "bamCacheRecord.h" class PNMImage; class PfmFile; @@ -51,7 +52,6 @@ class FactoryParams; class PreparedGraphicsObjects; class CullTraverser; class CullTraverserData; -class BamCacheRecord; class TexturePeeker; struct DDSHeader; diff --git a/panda/src/gobj/textureStage.h b/panda/src/gobj/textureStage.h index 9831124864..9623f141a8 100644 --- a/panda/src/gobj/textureStage.h +++ b/panda/src/gobj/textureStage.h @@ -37,7 +37,7 @@ class FactoryParams; //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_GOBJ TextureStage : public TypedWritableReferenceCount { PUBLISHED: - TextureStage(const string &name); + explicit TextureStage(const string &name); INLINE TextureStage(TextureStage ©); void operator = (const TextureStage ©); diff --git a/panda/src/ode/odeGeom_ext.I b/panda/src/ode/odeGeom_ext.I index 6d1cf2bebd..e7508da018 100644 --- a/panda/src/ode/odeGeom_ext.I +++ b/panda/src/ode/odeGeom_ext.I @@ -15,10 +15,6 @@ #include "odeSpace_ext.h" #include "lpoint3.h" -#ifndef CPPPARSER -IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3f; -#endif - //////////////////////////////////////////////////////////////////// // Function: OdeGeom::get_AA_bounds // Access: Published @@ -30,8 +26,8 @@ get_AA_bounds() const { LPoint3f *max_point = new LPoint3f; _this->get_AABB(*min_point, *max_point); - PyObject *min_inst = DTool_CreatePyInstance((void*) min_point, Dtool_LPoint3f, true, false); - PyObject *max_inst = DTool_CreatePyInstance((void*) max_point, Dtool_LPoint3f, true, false); + PyObject *min_inst = DTool_CreatePyInstance(min_point, true); + PyObject *max_inst = DTool_CreatePyInstance(max_point, true); return Py_BuildValue("NN", min_inst, max_inst); } diff --git a/panda/src/ode/odeSpace_ext.I b/panda/src/ode/odeSpace_ext.I index 78e9aeb7c3..8cbccc773e 100644 --- a/panda/src/ode/odeSpace_ext.I +++ b/panda/src/ode/odeSpace_ext.I @@ -15,10 +15,6 @@ /* okcircular */ #include "odeGeom_ext.h" -#ifndef CPPPARSER -IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3f; -#endif - //////////////////////////////////////////////////////////////////// // Function: OdeSpace::get_AA_bounds // Access: Published @@ -30,8 +26,8 @@ get_AA_bounds() const { LPoint3f *max_point = new LPoint3f; _this->get_AABB(*min_point, *max_point); - PyObject *min_inst = DTool_CreatePyInstance((void*) min_point, Dtool_LPoint3f, true, false); - PyObject *max_inst = DTool_CreatePyInstance((void*) max_point, Dtool_LPoint3f, true, false); + PyObject *min_inst = DTool_CreatePyInstance(min_point, true); + PyObject *max_inst = DTool_CreatePyInstance(max_point, true); return Py_BuildValue("NN", min_inst, max_inst); } diff --git a/panda/src/pgraph/camera.h b/panda/src/pgraph/camera.h index 54c0eeb945..c02c60da00 100644 --- a/panda/src/pgraph/camera.h +++ b/panda/src/pgraph/camera.h @@ -36,7 +36,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_PGRAPH Camera : public LensNode { PUBLISHED: - Camera(const string &name, Lens *lens = new PerspectiveLens()); + explicit Camera(const string &name, Lens *lens = new PerspectiveLens()); Camera(const Camera ©); public: diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index 74ce52c3a8..68a5196550 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -177,8 +177,8 @@ PUBLISHED: INLINE explicit NodePath(const string &top_node_name, Thread *current_thread = Thread::get_current_thread()); INLINE explicit NodePath(PandaNode *node, Thread *current_thread = Thread::get_current_thread()); INLINE static NodePath any_path(PandaNode *node, Thread *current_thread = Thread::get_current_thread()); - NodePath(const NodePath &parent, PandaNode *child_node, - Thread *current_thread = Thread::get_current_thread()); + explicit NodePath(const NodePath &parent, PandaNode *child_node, + Thread *current_thread = Thread::get_current_thread()); INLINE NodePath(const NodePath ©); INLINE void operator = (const NodePath ©); diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index c1719a7658..dda7244acb 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/panda/src/pgraph/pandaNode.h @@ -72,7 +72,7 @@ class GraphicsStateGuardianBase; class EXPCL_PANDA_PGRAPH PandaNode : public TypedWritableReferenceCount, public Namable, public LinkedListNode { PUBLISHED: - PandaNode(const string &name); + explicit PandaNode(const string &name); virtual ~PandaNode(); //published so that characters can be combined. virtual PandaNode *combine_with(PandaNode *other); diff --git a/panda/src/pnmimage/pnmImage.h b/panda/src/pnmimage/pnmImage.h index 4fba969690..10e3377635 100644 --- a/panda/src/pnmimage/pnmImage.h +++ b/panda/src/pnmimage/pnmImage.h @@ -68,10 +68,10 @@ class PNMFileType; class EXPCL_PANDA_PNMIMAGE PNMImage : public PNMImageHeader { PUBLISHED: INLINE PNMImage(); - PNMImage(const Filename &filename, PNMFileType *type = NULL); - INLINE PNMImage(int x_size, int y_size, int num_channels = 3, - xelval maxval = 255, PNMFileType *type = NULL, - ColorSpace color_space = CS_linear); + explicit PNMImage(const Filename &filename, PNMFileType *type = NULL); + INLINE explicit PNMImage(int x_size, int y_size, int num_channels = 3, + xelval maxval = 255, PNMFileType *type = NULL, + ColorSpace color_space = CS_linear); INLINE PNMImage(const PNMImage ©); INLINE void operator = (const PNMImage ©); diff --git a/panda/src/pnmimage/pnmimage_base.h b/panda/src/pnmimage/pnmimage_base.h index b75e6b0b74..ad5cf47555 100644 --- a/panda/src/pnmimage/pnmimage_base.h +++ b/panda/src/pnmimage/pnmimage_base.h @@ -42,8 +42,9 @@ typedef unsigned char gray; struct pixel { PUBLISHED: pixel() { } + pixel(gray fill) : r(fill), g(fill), b(fill) { } pixel(gray r, gray g, gray b) : r(r), g(g), b(b) { } - static int size() { return 3; } + gray operator [](int i) const { nassertr(i >= 0 && i < 3, 0); return *(&r + i); } gray &operator [](int i) { nassertr(i >= 0 && i < 3, r); return *(&r + i); } pixel operator + (const pixel &other) const @@ -60,6 +61,7 @@ PUBLISHED: { r *= mult; g *= mult; b *= mult; } #ifdef HAVE_PYTHON + static int size() { return 3; } void output(ostream &out) { out << "pixel(r=" << r << ", g=" << g << ", b=" << b << ")"; } diff --git a/panda/src/pstatclient/pStatThread.h b/panda/src/pstatclient/pStatThread.h index df0435585b..36a091faeb 100644 --- a/panda/src/pstatclient/pStatThread.h +++ b/panda/src/pstatclient/pStatThread.h @@ -29,7 +29,7 @@ class Thread; // with Panda's Thread instance. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_PSTATCLIENT PStatThread { -private: +public: INLINE PStatThread(); PUBLISHED: