interrogate: fix refcount trouble assigning PyObject* properties

In particular, this fixes accessing PythonTask.__dict__
This commit is contained in:
rdb 2019-03-04 16:46:28 +01:00
parent 45778b9e9f
commit 8e4add0326
4 changed files with 36 additions and 4 deletions

View File

@ -397,17 +397,25 @@ get_call_str(const string &container, const vector_string &pexprs) const {
}
// It's not possible to assign arrays in C++, we have to copy them.
CPPArrayType *array_type = _parameters[_first_true_parameter]._remap->get_orig_type()->as_array_type();
bool paren_close = false;
CPPType *param_type = _parameters[_first_true_parameter]._remap->get_orig_type();
CPPArrayType *array_type = param_type->as_array_type();
if (array_type != nullptr) {
call << "std::copy(" << expr << ", " << expr << " + " << *array_type->_bounds << ", ";
} else {
paren_close = true;
}
else if (TypeManager::is_pointer_to_PyObject(param_type)) {
call << "Dtool_Assign_PyObject(" << expr << ", ";
paren_close = true;
}
else {
call << expr << " = ";
}
_parameters[_first_true_parameter]._remap->pass_parameter(call,
get_parameter_expr(_first_true_parameter, pexprs));
if (array_type != nullptr) {
if (paren_close) {
call << ')';
}
@ -772,6 +780,11 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
_return_value_destructor = builder.get_destructor_for(return_meat_type);
}
if (_type == T_getter && TypeManager::is_pointer_to_PyObject(return_type)) {
_manage_reference_count = true;
_return_value_needs_management = true;
}
// Check for a special meaning by name and signature.
size_t first_param = 0;
if (_has_this) {

View File

@ -5979,7 +5979,11 @@ write_function_instance(ostream &out, FunctionRemap *remap,
indent(out, indent_level) << "}\n";
}
return_expr = manage_return_value(out, indent_level, remap, "return_value");
if (TypeManager::is_pointer_to_PyObject(remap->_return_type->get_orig_type())) {
indent(out, indent_level) << "Py_XINCREF(return_value);\n";
} else {
return_expr = manage_return_value(out, indent_level, remap, "return_value");
}
return_expr = remap->_return_type->temporary_to_return(return_expr);
}

View File

@ -90,6 +90,19 @@ INLINE PyObject *DtoolInstance_RichComparePointers(PyObject *v1, PyObject *v2, i
Py_RETURN_RICHCOMPARE(cmpval, 0, op);
}
/**
* Utility function for assigning a PyObject pointer while managing refcounts.
*/
ALWAYS_INLINE void
Dtool_Assign_PyObject(PyObject *&ptr, PyObject *value) {
PyObject *prev_value = ptr;
if (prev_value != value) {
Py_XINCREF(value);
ptr = value;
Py_XDECREF(prev_value);
}
}
/**
* Converts the enum value to a C long.
*/

View File

@ -238,6 +238,8 @@ EXPCL_PYPANDA PyObject *_Dtool_Return(PyObject *value);
#define Dtool_Return(value) _Dtool_Return(value)
#endif
ALWAYS_INLINE void Dtool_Assign_PyObject(PyObject *&ptr, PyObject *value);
/**
* Wrapper around Python 3.4's enum library, which does not have a C API.
*/