Use dynamic type lookup for interrogate to eliminate inter-module dependencies

It is now no longer necessary to link to core.pyd
Also includes a slight coercion optimization for trivial types
This commit is contained in:
rdb 2015-06-06 19:35:44 +02:00
parent 8e58e9e11c
commit 11ed8a4d8d
57 changed files with 910 additions and 439 deletions

View File

@ -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)

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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));
}
}
////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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 &copy) : _index(copy._index) {
}
////////////////////////////////////////////////////////////////////
// Function: TypeHandle::Equality Operator
// Access: Published

View File

@ -94,8 +94,10 @@ PUBLISHED:
// enum value.
};
INLINE TypeHandle();
INLINE TypeHandle(const TypeHandle &copy);
// 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));

View File

@ -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.

View File

@ -40,7 +40,6 @@
#include <set>
#include <map>
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<CPPType *>::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) &copy_from_make_copy, METH_NOARGS, NULL},\n";
out << " {\"__copy__\", (PyCFunction) &copy_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) &copy_from_copy_constructor, METH_NOARGS, NULL},\n";
out << " {\"__copy__\", (PyCFunction) &copy_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<string>::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_" <<ClassName << ".As_PyTypeObject().tp_dict,\"" <<export_class_name<< "\",&Dtool_" <<ClassName << ".As_PyObject());\n";
bool is_runtime_typed = IsPandaTypedObject(obj->_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();
}
////////////////////////////////////////////////////////////////////

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}

View File

@ -146,7 +146,7 @@ public:
static bool is_exported(CPPType *type);
static bool is_local(CPPType *type);
static bool is_trivial(CPPType *type);
};
#endif

View File

@ -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

View File

@ -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;
};

View File

@ -231,14 +231,4 @@ INLINE istream &operator >> (istream &in, InterrogateType::EnumValue &d);
#include "interrogateType.I"
#include <set>
#include <map>
struct Dtool_PyTypedObject;
typedef std::map< int , Dtool_PyTypedObject *> RunTimeTypeDictionary;
typedef std::set<int > RunTimeTypeList;
EXPCL_DTOOLCONFIG RunTimeTypeDictionary & GetRunTimeDictionary();
EXPCL_DTOOLCONFIG RunTimeTypeList & GetRunTimeTypeList();
#endif

View File

@ -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<NamedTypeMap::iterator, bool> 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<RunTimeTypeDictionary::iterator, bool> 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<RuntimeTypeMap::iterator, bool> 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

View File

@ -143,17 +143,17 @@ using namespace std;
///////////////////////////////////////////////////////////////////////////////////
struct Dtool_PyTypedObject;
typedef std::map<int, Dtool_PyTypedObject *> RunTimeTypeDictionary;
typedef std::set<int> RunTimeTypeList;
EXPCL_DTOOLCONFIG RunTimeTypeDictionary &GetRunTimeDictionary();
EXPCL_DTOOLCONFIG RunTimeTypeList &GetRunTimeTypeList();
typedef std::map<int, Dtool_PyTypedObject *> RuntimeTypeMap;
typedef std::set<int> RuntimeTypeSet;
typedef std::map<std::string, Dtool_PyTypedObject *> 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<class T> 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_

View File

@ -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:

View File

@ -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'])

View File

@ -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

View File

@ -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

View File

@ -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
////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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 &copy);
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;

View File

@ -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 &copy);

View File

@ -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 &copy);
void operator = (const GeomVertexArrayData &copy);
virtual ~GeomVertexArrayData();

View File

@ -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 &copy);
GeomVertexData(const GeomVertexData &copy,
const GeomVertexFormat *format);
explicit GeomVertexData(const GeomVertexData &copy,
const GeomVertexFormat *format);
void operator = (const GeomVertexData &copy);
virtual ~GeomVertexData();
ALLOC_DELETED_CHAIN(GeomVertexData);

View File

@ -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;

View File

@ -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 &copy);
void operator = (const TextureStage &copy);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 &copy);
public:

View File

@ -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 &copy);
INLINE void operator = (const NodePath &copy);

View File

@ -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);

View File

@ -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 &copy);
INLINE void operator = (const PNMImage &copy);

View File

@ -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 << ")";
}

View File

@ -29,7 +29,7 @@ class Thread;
// with Panda's Thread instance.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_PSTATCLIENT PStatThread {
private:
public:
INLINE PStatThread();
PUBLISHED: