Copy return value from `SetConstIterator::operator*`

`SetConstIterator::operator*` returns a reference, this is visible in
cpp and the user behaves accordingly.

In Python the user expects automatic memory management, the object
returned from query iterator should be valid as long as there is a
reference to it.
To ensure this add swig typemaps that copy the returned object.
It works because none of the queries (RepoQeury, GroupQuery,
EnvironmentQuery) store the actual data. They just store some kind of
proxy (RepoWeakPtr or wrapped libsolv ids) so if we copy the RepoWeakPtr
it still points to the same Repo object.

The PackageQuery and AdvisoryQuery return by value even in cpp so they
don't have this problem.
This commit is contained in:
Aleš Matěj 2025-07-14 14:04:00 +02:00 committed by pkratoch
parent 6ae73f6c5d
commit 141dabd943
3 changed files with 9 additions and 0 deletions

View File

@ -225,6 +225,12 @@ fix_swigtype_trait(ClassName)
%ignore libdnf5::SetConstIterator::operator++(int);
%ignore libdnf5::SetConstIterator::operator--(int);
%ignore libdnf5::SetConstIterator::operator->() const;
%typemap(out, noblock=1) copy_return_value {
// create a copy that is owned by the caller
$result = SWIG_NewPointerObj((new $*1_ltype(*$1)), $1_descriptor, 1);
}
%include "libdnf5/common/set.hpp"
#if defined(SWIGPYTHON)
%extend libdnf5::Set {

View File

@ -41,6 +41,7 @@
%include "libdnf5/comps/group/package.hpp"
%include "libdnf5/comps/group/group.hpp"
%template(VectorPackage) std::vector<libdnf5::comps::Package>;
%typemap(out) libdnf5::comps::Group & libdnf5::SetConstIterator<libdnf5::comps::Group>::operator* = copy_return_value;
%template(SetConstIteratorGroup) libdnf5::SetConstIterator<libdnf5::comps::Group>;
%template(SetGroup) libdnf5::Set<libdnf5::comps::Group>;
%template(SackQueryGroup) libdnf5::sack::Query<libdnf5::comps::Group>;
@ -48,6 +49,7 @@
add_iterator(SetGroup)
%include "libdnf5/comps/environment/environment.hpp"
%typemap(out) libdnf5::comps::Environment & libdnf5::SetConstIterator<libdnf5::comps::Environment>::operator* = copy_return_value;
%template(SetConstIteratorEnvironment) libdnf5::SetConstIterator<libdnf5::comps::Environment>;
%template(SetEnvironment) libdnf5::Set<libdnf5::comps::Environment>;
%template(SackQueryEnvironment) libdnf5::sack::Query<libdnf5::comps::Environment>;

View File

@ -144,6 +144,7 @@ wrap_unique_ptr(DownloadCallbacksUniquePtr, libdnf5::repo::DownloadCallbacks);
%include "libdnf5/repo/repo_weak.hpp"
%template(RepoWeakPtr) libdnf5::WeakPtr<libdnf5::repo::Repo, false>;
%typemap(out) libdnf5::WeakPtr<libdnf5::repo::Repo, false> & libdnf5::SetConstIterator<libdnf5::repo::RepoWeakPtr>::operator* = copy_return_value;
%template(SetConstIteratorRepoWeakPtr) libdnf5::SetConstIterator<libdnf5::repo::RepoWeakPtr>;
%template(SetRepoWeakPtr) libdnf5::Set<libdnf5::repo::RepoWeakPtr>;
%template(SackQueryRepoWeakPtr) libdnf5::sack::Query<libdnf5::repo::RepoWeakPtr>;