From fce4f39dc85980f1f54e4af25cc232569e6edaad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 28 Feb 2021 19:58:15 +0100 Subject: [PATCH] Fix deleting of shared_ptr create from C++. --- src/runner/gamefeatureswrappers.cpp | 5 ++++- src/runner/proxypluginwrappers.cpp | 8 ++++++-- src/runner/shared_ptr_converter.h | 24 ++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/runner/gamefeatureswrappers.cpp b/src/runner/gamefeatureswrappers.cpp index f83dd2a..936bf7f 100644 --- a/src/runner/gamefeatureswrappers.cpp +++ b/src/runner/gamefeatureswrappers.cpp @@ -9,6 +9,7 @@ #include #include +#include "shared_ptr_converter.h" #include "ifiletree.h" #include "pythonwrapperutilities.h" @@ -108,7 +109,9 @@ ModDataChecker::CheckReturn ModDataCheckerWrapper::dataLooksValid(std::shared_pt } std::shared_ptr ModDataCheckerWrapper::fix(std::shared_ptr fileTree) const { - return basicWrapperFunctionImplementationWithDefault>(this, [](auto&&... args) { return nullptr; }, "fix", fileTree); + return utils::clean_shared_ptr( + basicWrapperFunctionImplementationWithDefault>( + this, [](auto&&... args) { return nullptr; }, "fix", fileTree)); } /// end ModDataChecker Wrapper diff --git a/src/runner/proxypluginwrappers.cpp b/src/runner/proxypluginwrappers.cpp index 3d6e99e..58bb234 100644 --- a/src/runner/proxypluginwrappers.cpp +++ b/src/runner/proxypluginwrappers.cpp @@ -4,6 +4,7 @@ #include #include +#include "shared_ptr_converter.h" #include "pythonwrapperutilities.h" #include "uibasewrappers.h" @@ -330,10 +331,10 @@ IPluginInstaller::EInstallResult IPluginInstallerSimpleWrapper::install( using return_type = std::variant< IPluginInstaller::EInstallResult, std::shared_ptr, - std::tuple, QString, int>> ; + std::tuple, QString, int>>; auto ret = basicWrapperFunctionImplementation(this, "install", boost::ref(modName), tree, version, nexusID); - return std::visit([&](auto const& t) { + auto result = std::visit([&](auto const& t) { using type = std::decay_t; if constexpr (std::is_same_v) { return t; @@ -349,6 +350,9 @@ IPluginInstaller::EInstallResult IPluginInstallerSimpleWrapper::install( return std::get<0>(t); } }, ret); + + tree = utils::clean_shared_ptr(tree); + return result; } /// end IPluginInstallerSimple Wrapper diff --git a/src/runner/shared_ptr_converter.h b/src/runner/shared_ptr_converter.h index 8c3cf83..ab80ac3 100644 --- a/src/runner/shared_ptr_converter.h +++ b/src/runner/shared_ptr_converter.h @@ -96,6 +96,30 @@ namespace utils { } }; + // release the bpy::object associated with the deleter of the given shared_ptr, + // if the given shared_ptr has a Boost.Python deleter + // + // this should only be used when returning from Python objects that have been created + // on the C++ side, e.g. if IFileTree.createOrphanTree() from Python and then return + // the tree + // + // for reason yet to be known, Boost.Python had a custom deleter in this case that tries + // to delete the bpy::object and fails, so we have to release the object manually + // + template + SharedPtr clean_shared_ptr(SharedPtr&& ptr) { + if (auto* d = get_deleter(ptr); d != nullptr) { + // we cannot do a proper reset() here, even with the GIL lock, for unknown reason, + // so we only release + // + // this might create lost references to Python object but this should not happen + // too often so hopefully it's not a big issue + // + d->owner.release(); + } + return ptr; + } + } #endif \ No newline at end of file