diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index fabbb8a311..d5d6ab643c 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/dtool/src/interrogate/functionRemap.cxx @@ -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) { diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index 4d606c65d9..c617b6597e 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -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); } diff --git a/dtool/src/interrogatedb/py_panda.I b/dtool/src/interrogatedb/py_panda.I index 12f20f1f1e..d6b95efe35 100644 --- a/dtool/src/interrogatedb/py_panda.I +++ b/dtool/src/interrogatedb/py_panda.I @@ -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. */ diff --git a/dtool/src/interrogatedb/py_panda.h b/dtool/src/interrogatedb/py_panda.h index 353af53608..026d1c6858 100644 --- a/dtool/src/interrogatedb/py_panda.h +++ b/dtool/src/interrogatedb/py_panda.h @@ -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. */