mirror of
https://github.com/ModOrganizer2/modorganizer-plugin_python.git
synced 2026-07-27 14:03:33 -07:00
Merge pull request #91 from Holt59/fix-ifiletree-sharedptr
Fix deletion of shared_ptr created from C++.
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include <isavegame.h>
|
||||
#include <isavegameinfowidget.h>
|
||||
|
||||
#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<MOBase::IFileTree> ModDataCheckerWrapper::fix(std::shared_ptr<MOBase::IFileTree> fileTree) const {
|
||||
return basicWrapperFunctionImplementationWithDefault<std::shared_ptr<MOBase::IFileTree>>(this, [](auto&&... args) { return nullptr; }, "fix", fileTree);
|
||||
return utils::clean_shared_ptr(
|
||||
basicWrapperFunctionImplementationWithDefault<std::shared_ptr<MOBase::IFileTree>>(
|
||||
this, [](auto&&... args) { return nullptr; }, "fix", fileTree));
|
||||
}
|
||||
|
||||
/// end ModDataChecker Wrapper
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <QUrl>
|
||||
#include <QWidget>
|
||||
|
||||
#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<IFileTree>,
|
||||
std::tuple<IPluginInstaller::EInstallResult, std::shared_ptr<IFileTree>, QString, int>> ;
|
||||
std::tuple<IPluginInstaller::EInstallResult, std::shared_ptr<IFileTree>, QString, int>>;
|
||||
auto ret = basicWrapperFunctionImplementation<return_type>(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<decltype(t)>;
|
||||
if constexpr (std::is_same_v<type, IPluginInstaller::EInstallResult>) {
|
||||
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
|
||||
|
||||
@@ -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 <class SharedPtr>
|
||||
SharedPtr clean_shared_ptr(SharedPtr&& ptr) {
|
||||
if (auto* d = get_deleter<boost::python::converter::shared_ptr_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
|
||||
Reference in New Issue
Block a user