From b78d809d10f6003519960903bd962cc503c2c2a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 7 May 2023 20:59:19 +0200 Subject: [PATCH] python: put PyPluginHolder into a public header as well. Will need it for exposing Trade::AbstractImporter instances returned from SceneTools. --- src/Corrade/CMakeLists.txt | 4 ++ src/Corrade/PluginManager/CMakeLists.txt | 32 ++++++++++ src/Corrade/PluginManager/PythonBindings.h | 71 ++++++++++++++++++++++ src/python/corrade/pluginmanager.h | 38 +----------- 4 files changed, 110 insertions(+), 35 deletions(-) create mode 100644 src/Corrade/PluginManager/CMakeLists.txt create mode 100644 src/Corrade/PluginManager/PythonBindings.h diff --git a/src/Corrade/CMakeLists.txt b/src/Corrade/CMakeLists.txt index 394038c..34a43cc 100644 --- a/src/Corrade/CMakeLists.txt +++ b/src/Corrade/CMakeLists.txt @@ -33,3 +33,7 @@ if(MAGNUM_WITH_PYTHON) endif() add_subdirectory(Containers) + +if(Corrade_PluginManager_FOUND) + add_subdirectory(PluginManager) +endif() diff --git a/src/Corrade/PluginManager/CMakeLists.txt b/src/Corrade/PluginManager/CMakeLists.txt new file mode 100644 index 0000000..4af90f8 --- /dev/null +++ b/src/Corrade/PluginManager/CMakeLists.txt @@ -0,0 +1,32 @@ +# +# This file is part of Magnum. +# +# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, +# 2020, 2021, 2022 Vladimír Vondruš +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +if(MAGNUM_WITH_PYTHON) + set(CorradePluginManagerPython_HEADERS + PythonBindings.h) + + add_custom_target(CorradePluginManagerPython SOURCES ${CorradePluginManagerPython_HEADERS}) + install(FILES ${CorradePluginManagerPython_HEADERS} DESTINATION ${CORRADE_INCLUDE_INSTALL_DIR}/PluginManager) +endif() diff --git a/src/Corrade/PluginManager/PythonBindings.h b/src/Corrade/PluginManager/PythonBindings.h new file mode 100644 index 0000000..22f1135 --- /dev/null +++ b/src/Corrade/PluginManager/PythonBindings.h @@ -0,0 +1,71 @@ +#ifndef Corrade_PluginManager_PythonBindings_h +#define Corrade_PluginManager_PythonBindings_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include /* :( */ +#include +#include +#include + +namespace Corrade { namespace PluginManager { + +/* Stores additional stuff needed for proper refcounting of plugin instances. + Due to obvious reasons we can't subclass plugins so this is the only + possible way. */ +template struct PyPluginHolder: std::unique_ptr { + explicit PyPluginHolder(T* object) noexcept: std::unique_ptr{object} { + /* Plugin instance without an owner can only be without a manager and + thus without any metadata */ + CORRADE_INTERNAL_ASSERT(!object->metadata()); + } + + explicit PyPluginHolder(T* object, pybind11::object manager) noexcept: std::unique_ptr{object}, manager{std::move(manager)} {} + + PyPluginHolder(PyPluginHolder&&) noexcept = default; + PyPluginHolder(const PyPluginHolder&) = delete; + PyPluginHolder& operator=(PyPluginHolder&&) noexcept = default; + PyPluginHolder& operator=(const PyPluginHolder&) = default; + + ~PyPluginHolder() { + /* On destruction, first `manager` and then the plugin would be + destroyed, which would mean it asserts due to the manager being + destructed while plugins are still around. To flip the order, we + need to reset the pointer first */ + std::unique_ptr::reset(); + } + + pybind11::object manager; +}; + +template PyPluginHolder pyPluginHolder(Containers::Pointer&& plugin, pybind11::object owner) { + return PyPluginHolder{plugin.release(), std::move(owner)}; +} + +}} + +PYBIND11_DECLARE_HOLDER_TYPE(T, Corrade::PluginManager::PyPluginHolder) + +#endif diff --git a/src/python/corrade/pluginmanager.h b/src/python/corrade/pluginmanager.h index b77c2c9..13dbf9a 100644 --- a/src/python/corrade/pluginmanager.h +++ b/src/python/corrade/pluginmanager.h @@ -33,42 +33,10 @@ #include #include "Corrade/PythonBindings.h" +#include "Corrade/PluginManager/PythonBindings.h" #include "corrade/bootstrap.h" -namespace Corrade { namespace PluginManager { - -/* Stores additional stuff needed for proper refcounting of plugin instances. - Due to obvious reasons we can't subclass plugins so this is the only - possible way. */ -template struct PyPluginHolder: std::unique_ptr { - explicit PyPluginHolder(T*) { - /* Pybind needs this signature, but it should never be called */ - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - explicit PyPluginHolder(T* object, pybind11::object manager) noexcept: std::unique_ptr{object}, manager{std::move(manager)} {} - - PyPluginHolder(PyPluginHolder&&) noexcept = default; - PyPluginHolder(const PyPluginHolder&) = delete; - PyPluginHolder& operator=(PyPluginHolder&&) noexcept = default; - PyPluginHolder& operator=(const PyPluginHolder&) = default; - - ~PyPluginHolder() { - /* On destruction, first `manager` and then the plugin would be - destroyed, which would mean it asserts due to the manager being - destructed while plugins are still around. To flip the order, we - need to reset the pointer first */ - std::unique_ptr::reset(); - } - - pybind11::object manager; -}; - -}} - -PYBIND11_DECLARE_HOLDER_TYPE(T, Corrade::PluginManager::PyPluginHolder) - namespace corrade { template void plugin(py::class_, PluginManager::AbstractPlugin>& c) { @@ -115,7 +83,7 @@ template void manager(py::class_, PluginManag throw py::error_already_set{}; } - return PluginManager::PyPluginHolder{loaded.release(), py::cast(self)}; + return PluginManager::pyPluginHolder(std::move(loaded), py::cast(self)); }) .def("load_and_instantiate", [](PluginManager::Manager& self, const std::string& plugin) { auto loaded = self.loadAndInstantiate(plugin); @@ -124,7 +92,7 @@ template void manager(py::class_, PluginManag throw py::error_already_set{}; } - return PluginManager::PyPluginHolder{loaded.release(), py::cast(self)}; + return PluginManager::pyPluginHolder(std::move(loaded), py::cast(self)); }); }