mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 00:32:57 -04:00
interrogate: various fixes:
* handle static methods with explicit self * fix len() and __setitem__ of mapping types * fix inheritance of __getattr__ and __setattr__ * fix overload resolution error with nullptr_t arguments * bool overloads now come after float/double overloads * record whether class is final in interrogatedb * add Dtool_EmptyTuple * optimization for final classes: no need for downcast
This commit is contained in:
parent
4018efc50d
commit
7ff8b62fb8
@ -772,16 +772,14 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
|
||||
first_param = 1;
|
||||
}
|
||||
|
||||
if (_has_this || _type == T_constructor) {
|
||||
if (_parameters.size() > (size_t)first_param && _parameters[first_param]._name == "self" &&
|
||||
TypeManager::is_pointer_to_PyObject(_parameters[first_param]._remap->get_orig_type())) {
|
||||
// Here's a special case. If the first parameter of a nonstatic method
|
||||
// is a PyObject * called "self", then we will automatically fill it in
|
||||
// from the this pointer, and remove it from the generated parameter
|
||||
// list.
|
||||
_parameters.erase(_parameters.begin() + first_param);
|
||||
_flags |= F_explicit_self;
|
||||
}
|
||||
if (_parameters.size() > (size_t)first_param && _parameters[first_param]._name == "self" &&
|
||||
TypeManager::is_pointer_to_PyObject(_parameters[first_param]._remap->get_orig_type())) {
|
||||
// Here's a special case. If the first parameter of a nonstatic method
|
||||
// is a PyObject * called "self", then we will automatically fill it in
|
||||
// from the this pointer, and remove it from the generated parameter
|
||||
// list.
|
||||
_parameters.erase(_parameters.begin() + first_param);
|
||||
_flags |= F_explicit_self;
|
||||
}
|
||||
|
||||
if ((int)_parameters.size() == first_param) {
|
||||
|
@ -616,7 +616,7 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) {
|
||||
|
||||
// If *any* of the variants of this function has a "this" pointer,
|
||||
// the entire set of functions is deemed to have a "this" pointer.
|
||||
if (remap->_has_this) {
|
||||
if (remap->_has_this || (remap->_flags & FunctionRemap::F_explicit_self) != 0) {
|
||||
func->_has_this = true;
|
||||
}
|
||||
|
||||
|
@ -478,6 +478,11 @@ get_slotted_function_def(Object *obj, Function *func, FunctionRemap *remap,
|
||||
def._wrapper_type = WT_mapping_setitem;
|
||||
return true;
|
||||
}
|
||||
if (remap->_flags & FunctionRemap::F_size) {
|
||||
def._answer_location = "mp_length";
|
||||
def._wrapper_type = WT_sequence_size;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->_protocol_types & Object::PT_iter) {
|
||||
@ -707,7 +712,10 @@ write_python_instance(ostream &out, int indent_level, const string &return_expr,
|
||||
|
||||
string class_name = itype.get_scoped_name();
|
||||
|
||||
if (IsPandaTypedObject(itype._cpptype->as_struct_type())) {
|
||||
// We don't handle final classes via DTool_CreatePyInstanceTyped since we
|
||||
// know it can't be of a subclass type, so we don't need to do the downcast.
|
||||
CPPStructType *struct_type = itype._cpptype->as_struct_type();
|
||||
if (IsPandaTypedObject(struct_type) && !struct_type->is_final()) {
|
||||
// We can't let DTool_CreatePyInstanceTyped do the NULL check since we
|
||||
// will be grabbing the type index (which would obviously crash when
|
||||
// called on a NULL pointer), so we do it here.
|
||||
@ -2100,10 +2108,10 @@ write_module_class(ostream &out, Object *obj) {
|
||||
for (ri = def._remaps.begin(); ri != def._remaps.end(); ++ri) {
|
||||
FunctionRemap *remap = (*ri);
|
||||
|
||||
if (remap->_flags & FunctionRemap::F_setitem_int) {
|
||||
if (remap->_flags & FunctionRemap::F_setitem) {
|
||||
setitem_remaps.insert(remap);
|
||||
|
||||
} else if (remap->_flags & FunctionRemap::F_delitem_int) {
|
||||
} else if (remap->_flags & FunctionRemap::F_delitem) {
|
||||
delitem_remaps.insert(remap);
|
||||
}
|
||||
}
|
||||
@ -2137,14 +2145,21 @@ write_module_class(ostream &out, Object *obj) {
|
||||
out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n";
|
||||
out << "//////////////////\n";
|
||||
out << "static int " << def._wrapper_name << "(PyObject *self) {\n";
|
||||
out << " " << cClassName << " *local_this = NULL;\n";
|
||||
out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n";
|
||||
out << " return -1;\n";
|
||||
out << " }\n\n";
|
||||
|
||||
// Find the remap. There should be only one.
|
||||
FunctionRemap *remap = *def._remaps.begin();
|
||||
const char *container = "";
|
||||
|
||||
if (remap->_has_this) {
|
||||
out << " " << cClassName << " *local_this = NULL;\n";
|
||||
out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n";
|
||||
out << " return -1;\n";
|
||||
out << " }\n\n";
|
||||
container = "local_this";
|
||||
}
|
||||
|
||||
vector_string params;
|
||||
out << " return (int) " << remap->call_function(out, 4, false, "local_this", params) << ";\n";
|
||||
out << " return (int) " << remap->call_function(out, 4, false, container, params) << ";\n";
|
||||
out << "}\n\n";
|
||||
}
|
||||
break;
|
||||
@ -2374,23 +2389,25 @@ write_module_class(ostream &out, Object *obj) {
|
||||
out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n";
|
||||
out << "//////////////////\n";
|
||||
out << "static int " << def._wrapper_name << "(PyObject *self, visitproc visit, void *arg) {\n";
|
||||
out << " " << cClassName << " *local_this = NULL;\n";
|
||||
out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **) &local_this);\n";
|
||||
out << " if (local_this == NULL) {\n";
|
||||
out << " return 0;\n";
|
||||
out << " }\n\n";
|
||||
|
||||
// Find the remap. There should be only one.
|
||||
FunctionRemap *remap = *def._remaps.begin();
|
||||
const char *container = "";
|
||||
|
||||
vector_string params(1);
|
||||
if (remap->_flags & FunctionRemap::F_explicit_self) {
|
||||
params.push_back("self");
|
||||
if (remap->_has_this) {
|
||||
out << " " << cClassName << " *local_this = NULL;\n";
|
||||
out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **) &local_this);\n";
|
||||
out << " if (local_this == NULL) {\n";
|
||||
out << " return 0;\n";
|
||||
out << " }\n\n";
|
||||
container = "local_this";
|
||||
}
|
||||
|
||||
vector_string params((int)remap->_has_this);
|
||||
params.push_back("visit");
|
||||
params.push_back("arg");
|
||||
|
||||
out << " return " << remap->call_function(out, 2, false, "local_this", params) << ";\n";
|
||||
out << " return " << remap->call_function(out, 2, false, container, params) << ";\n";
|
||||
out << "}\n\n";
|
||||
}
|
||||
break;
|
||||
@ -2857,11 +2874,9 @@ write_module_class(ostream &out, Object *obj) {
|
||||
}
|
||||
|
||||
// getattrofunc tp_getattro;
|
||||
write_function_slot(out, 4, slots, "tp_getattro",
|
||||
"PyObject_GenericGetAttr");
|
||||
write_function_slot(out, 4, slots, "tp_getattro");
|
||||
// setattrofunc tp_setattro;
|
||||
write_function_slot(out, 4, slots, "tp_setattro",
|
||||
"PyObject_GenericSetAttr");
|
||||
write_function_slot(out, 4, slots, "tp_setattro");
|
||||
|
||||
// PyBufferProcs *tp_as_buffer;
|
||||
if (has_parent_class || has_local_getbuffer) {
|
||||
@ -4180,7 +4195,7 @@ int get_type_sort(CPPType *type) {
|
||||
return 7;
|
||||
} else if (TypeManager::is_longlong(type)) {
|
||||
return 6;
|
||||
} else if (TypeManager::is_integer(type)) {
|
||||
} else if (TypeManager::is_integer(type) && !TypeManager::is_bool(type)) {
|
||||
return 5;
|
||||
} else if (TypeManager::is_double(type)) {
|
||||
return 4;
|
||||
@ -4973,7 +4988,7 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
||||
format_specifiers += "O";
|
||||
parameter_list += ", &" + param_name;
|
||||
}
|
||||
pexpr_string = "NULL";
|
||||
pexpr_string = "nullptr";
|
||||
expected_params += "NoneType";
|
||||
|
||||
} else if (TypeManager::is_char(type)) {
|
||||
@ -5800,7 +5815,8 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
||||
indent_level += 2;
|
||||
}
|
||||
|
||||
if (!remap->_has_this && (remap->_flags & FunctionRemap::F_explicit_self) != 0) {
|
||||
if (is_constructor && !remap->_has_this &&
|
||||
(remap->_flags & FunctionRemap::F_explicit_self) != 0) {
|
||||
// If we'll be passing "self" to the constructor, we need to pre-
|
||||
// initialize it here. Unfortunately, we can't pre-load the "this"
|
||||
// pointer, but the constructor itself can do this.
|
||||
|
@ -1850,12 +1850,24 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
|
||||
continue;
|
||||
}
|
||||
|
||||
const CPPParameterList::Parameters ¶ms = ftype->_parameters->_parameters;
|
||||
|
||||
size_t expected_num_args = (size_t)is_seq;
|
||||
size_t index_arg = 0;
|
||||
|
||||
if (!params.empty() && params[0]->get_simple_name() == "self" &&
|
||||
TypeManager::is_pointer_to_PyObject(params[0]->_type)) {
|
||||
// Taking a PyObject *self argument.
|
||||
expected_num_args += 1;
|
||||
index_arg += 1;
|
||||
}
|
||||
|
||||
// The getter must either take no arguments, or all defaults.
|
||||
if (ftype->_parameters->_parameters.size() == (size_t)is_seq ||
|
||||
(ftype->_parameters->_parameters.size() > (size_t)is_seq &&
|
||||
ftype->_parameters->_parameters[(size_t)is_seq]->_initializer != NULL)) {
|
||||
if (params.size() == expected_num_args ||
|
||||
(params.size() > expected_num_args &&
|
||||
params[expected_num_args]->_initializer != NULL)) {
|
||||
// If this is a sequence getter, it must take an index argument.
|
||||
if (is_seq && !TypeManager::is_integer(ftype->_parameters->_parameters[0]->_type)) {
|
||||
if (is_seq && !TypeManager::is_integer(params[index_arg]->_type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2428,6 +2440,10 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
|
||||
break;
|
||||
}
|
||||
|
||||
if (cpptype->is_final()) {
|
||||
itype._flags |= InterrogateType::F_final;
|
||||
}
|
||||
|
||||
if (cpptype->_file.is_c_file()) {
|
||||
// This type declaration appears in a .C file. We can only export types
|
||||
// defined in a .h file.
|
||||
|
@ -289,6 +289,14 @@ is_union() const {
|
||||
return (_flags & F_union) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE bool InterrogateType::
|
||||
is_final() const {
|
||||
return (_flags & F_final) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -75,6 +75,7 @@ public:
|
||||
INLINE bool is_struct() const;
|
||||
INLINE bool is_class() const;
|
||||
INLINE bool is_union() const;
|
||||
INLINE bool is_final() const;
|
||||
|
||||
INLINE bool is_fully_defined() const;
|
||||
INLINE bool is_unpublished() const;
|
||||
@ -139,6 +140,7 @@ private:
|
||||
F_typedef = 0x200000,
|
||||
F_array = 0x400000,
|
||||
F_scoped_enum = 0x800000,
|
||||
F_final =0x1000000,
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
PyTupleObject Dtool_EmptyTuple;
|
||||
|
||||
PyMemberDef standard_type_members[] = {
|
||||
{(char *)"this", (sizeof(void*) == sizeof(int)) ? T_UINT : T_ULONGLONG, offsetof(Dtool_PyInstDef, _ptr_to_object), READONLY, (char *)"C++ 'this' pointer, if any"},
|
||||
{(char *)"this_ownership", T_BOOL, offsetof(Dtool_PyInstDef, _memory_rules), READONLY, (char *)"C++ 'this' ownership rules"},
|
||||
@ -65,15 +67,6 @@ size_t PyLongOrInt_AsSize_t(PyObject *vv) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if PY_VERSION_HEX < 0x03060000
|
||||
INLINE static PyObject *_PyObject_CallNoArg(PyObject *func) {
|
||||
PyObject *args = PyTuple_New(0);
|
||||
PyObject *result = PyObject_Call(func, args, NULL);
|
||||
Py_DECREF(args);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Given a valid (non-NULL) PyObject, does a simple check to see if it might
|
||||
* be an instance of a Panda type. It does this using a signature that is
|
||||
@ -625,6 +618,9 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
|
||||
return Dtool_Raise_TypeError("PyType_Ready(Dtool_StaticProperty_Type)");
|
||||
}
|
||||
|
||||
// Initialize the "empty tuple".
|
||||
(void)PyObject_INIT_VAR((PyObject *)&Dtool_EmptyTuple, &PyTuple_Type, 0);
|
||||
|
||||
// Initialize the base class of everything.
|
||||
Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(NULL);
|
||||
}
|
||||
|
@ -138,6 +138,12 @@ typedef long Py_hash_t;
|
||||
#define FMTCHAR_BYTES "s"
|
||||
#endif
|
||||
|
||||
extern EXPCL_INTERROGATEDB PyTupleObject Dtool_EmptyTuple;
|
||||
|
||||
#ifndef _PyObject_CallNoArg
|
||||
#define _PyObject_CallNoArg(func) PyObject_Call((func), (PyObject *)&Dtool_EmptyTuple, NULL)
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
// this is tempory .. untill this is glued better into the panda build system
|
||||
|
Loading…
x
Reference in New Issue
Block a user