From 3c08e2851d1382d156fffee7f2f8dfb54bb26442 Mon Sep 17 00:00:00 2001 From: methylDragon Date: Wed, 10 Aug 2022 12:13:49 -0700 Subject: [PATCH 1/9] Remove redundant namespace references (#100) Signed-off-by: methylDragon --- loader/src/ign.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/src/ign.cc b/loader/src/ign.cc index 7f17739c..368b7f1d 100644 --- a/loader/src/ign.cc +++ b/loader/src/ign.cc @@ -34,7 +34,7 @@ extern "C" void IGNITION_PLUGIN_LOADER_VISIBLE cmdPluginInfo( return; } - ignition::plugin::Loader pl; + Loader pl; std::cout << "Loading plugin library file [" << _plugin << "]\n"; // Print names of plugins exported by library file From 0575edae6ff882cefb3ddfd3e0d23bd41e9230d3 Mon Sep 17 00:00:00 2001 From: Louise Poubel Date: Mon, 15 Aug 2022 16:50:58 -0700 Subject: [PATCH 2/9] =?UTF-8?q?=F0=9F=8E=88=201.3.0=20(#103)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Louise Poubel Signed-off-by: Louise Poubel --- CMakeLists.txt | 2 +- Changelog.md | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d474f949..a75c51fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR) #============================================================================ # Initialize the project #============================================================================ -project(ignition-plugin1 VERSION 1.2.1) +project(ignition-plugin1 VERSION 1.3.0) #============================================================================ # Find ignition-cmake diff --git a/Changelog.md b/Changelog.md index 1b126a0d..df4031ad 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,27 @@ -## Ignition Plugin 1.x +## Gazebo Plugin 1.x + +### Gazebo Plugin 1.3.0 (2022-08-15) + +1. Remove redundant namespace references + * [Pull request #100](https://github.com/gazebosim/gz-plugin/pull/100) + +1. Change `IGN_DESIGNATION` to `GZ_DESIGNATION` + * [Pull request #96](https://github.com/gazebosim/gz-plugin/pull/96) + +1. Ignition -> Gazebo + * [Pull request #94](https://github.com/gazebosim/gz-plugin/pull/94) + +1. Bash completion for flags + * [Pull request #81](https://github.com/gazebosim/gz-plugin/pull/81) + +1. Add LICENSE file + * [Pull request #72](https://github.com/gazebosim/gz-plugin/pull/72) + +1. Add Ubuntu Jammy CI + * [Pull request #68](https://github.com/gazebosim/gz-plugin/pull/68) + +1. Install ruby commands on Windows + * [Pull request #63](https://github.com/gazebosim/gz-plugin/pull/63) ### Ignition Plugin 1.2.1 (2021-09-24) From daa9a6589312f08d84f371a8e92b7c9dc10496e6 Mon Sep 17 00:00:00 2001 From: methylDragon Date: Wed, 17 Aug 2022 14:12:00 -0700 Subject: [PATCH 3/9] Hotfix installation directory (#104) Signed-off-by: methylDragon --- core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 591ee0d0..83831137 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -17,4 +17,4 @@ gz_build_tests( add_subdirectory(include/gz/plugin) -install(DIRECTORY include/gz DESTINATION ${GZ_INCLUDE_INSTALL_DIR_FULL}) +install(DIRECTORY include/ignition DESTINATION ${GZ_INCLUDE_INSTALL_DIR_FULL}) From c189b784480892b2eb76a6ae858b3ad1511cf225 Mon Sep 17 00:00:00 2001 From: "Addisu Z. Taddese" Date: Wed, 31 Aug 2022 11:19:19 -0500 Subject: [PATCH 4/9] Add option to use RTLD_NODELETE when loading a library (#102) Signed-off-by: Addisu Z. Taddese Signed-off-by: Louise Poubel Co-authored-by: Steve Peters Co-authored-by: Louise Poubel --- loader/include/gz/plugin/Loader.hh | 11 ++++ loader/src/Loader.cc | 21 +++++-- test/integration/CMakeLists.txt | 5 +- test/integration/plugin_unload.hh | 63 +++++++++++++++++++ .../plugin_unload_with_nodelete.cc | 30 +++++++++ .../plugin_unload_without_nodelete.cc | 30 +++++++++ test/plugins/CMakeLists.txt | 3 + test/plugins/InstanceCounter.cc | 59 +++++++++++++++++ test/plugins/InstanceCounter.hh | 36 +++++++++++ 9 files changed, 253 insertions(+), 5 deletions(-) create mode 100644 test/integration/plugin_unload.hh create mode 100644 test/integration/plugin_unload_with_nodelete.cc create mode 100644 test/integration/plugin_unload_without_nodelete.cc create mode 100644 test/plugins/InstanceCounter.cc create mode 100644 test/plugins/InstanceCounter.hh diff --git a/loader/include/gz/plugin/Loader.hh b/loader/include/gz/plugin/Loader.hh index 4be3be9a..56d79c19 100644 --- a/loader/include/gz/plugin/Loader.hh +++ b/loader/include/gz/plugin/Loader.hh @@ -133,6 +133,17 @@ namespace gz public: std::unordered_set LoadLib( const std::string &_pathToLibrary); + /// \brief Load a library at the given path + /// + /// \param[in] _pathToLibrary + /// The path to a library + /// \param[in] _noDelete + /// If true, RTLD_NODELETE will be used when loading the library. + /// + /// \returns The set of plugins that have been loaded from the library + public: std::unordered_set LoadLib( + const std::string &_pathToLibrary, bool _noDelete); + /// \brief Instantiates a plugin for the given plugin name /// /// \param[in] _pluginNameOrAlias diff --git a/loader/src/Loader.cc b/loader/src/Loader.cc index e35b80e3..9296d454 100644 --- a/loader/src/Loader.cc +++ b/loader/src/Loader.cc @@ -46,7 +46,7 @@ namespace gz /// \return If a library exists at the given path, get a point to its dl /// handle. If the library does not exist, get a nullptr. public: std::shared_ptr LoadLib( - const std::string &_pathToLibrary); + const std::string &_pathToLibrary, bool _noDelete); /// \brief Using a dl handle produced by LoadLib, extract the /// Info from the loaded library. @@ -139,12 +139,18 @@ namespace gz ///////////////////////////////////////////////// std::unordered_set Loader::LoadLib( const std::string &_pathToLibrary) + { + return this->LoadLib(_pathToLibrary, false); + } + ///////////////////////////////////////////////// + std::unordered_set Loader::LoadLib( + const std::string &_pathToLibrary, bool _noDelete) { std::unordered_set newPlugins; // Attempt to load the library at this path const std::shared_ptr &dlHandle = - this->dataPtr->LoadLib(_pathToLibrary); + this->dataPtr->LoadLib(_pathToLibrary, _noDelete); // Quit early and return an empty set of plugin names if we did not // actually get a valid dlHandle. @@ -420,7 +426,7 @@ namespace gz ///////////////////////////////////////////////// std::shared_ptr Loader::Implementation::LoadLib( - const std::string &_full_path) + const std::string &_full_path, bool _noDelete) { std::shared_ptr dlHandlePtr; @@ -431,7 +437,14 @@ namespace gz // NOTE: We open using RTLD_LOCAL instead of RTLD_GLOBAL to prevent the // symbols of different libraries from writing over each other. - void *dlHandle = dlopen(_full_path.c_str(), RTLD_LAZY | RTLD_LOCAL); +#ifdef _WIN32 + // RTLD_NODELETE is not defined in dlfcn-32. + (void) _noDelete; + int dlopenMode = RTLD_LAZY | RTLD_LOCAL; +#else + int dlopenMode = RTLD_LAZY | RTLD_LOCAL | (_noDelete ? RTLD_NODELETE : 0); +#endif + void *dlHandle = dlopen(_full_path.c_str(), dlopenMode); const char *loadError = dlerror(); if (nullptr == dlHandle || nullptr != loadError) diff --git a/test/integration/CMakeLists.txt b/test/integration/CMakeLists.txt index cea2931c..881d2f13 100644 --- a/test/integration/CMakeLists.txt +++ b/test/integration/CMakeLists.txt @@ -20,7 +20,8 @@ foreach(test ${test_targets}) GzBadPluginSize GzDummyPlugins GzFactoryPlugins - GzTemplatedPlugins) + GzTemplatedPlugins + GzInstanceCounter) target_compile_definitions(${test} PRIVATE "${plugin_target}_LIB=\"$\"") @@ -33,6 +34,8 @@ foreach(test INTEGRATION_EnablePluginFromThis_TEST INTEGRATION_factory INTEGRATION_plugin + INTEGRATION_plugin_unload_with_nodelete + INTEGRATION_plugin_unload_without_nodelete INTEGRATION_WeakPluginPtr) if(TARGET ${test}) diff --git a/test/integration/plugin_unload.hh b/test/integration/plugin_unload.hh new file mode 100644 index 00000000..4c198c6c --- /dev/null +++ b/test/integration/plugin_unload.hh @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GZ_PLUGIN_TEST_INTEGRATION_PLUGIN_UNLOAD_HH +#define GZ_PLUGIN_TEST_INTEGRATION_PLUGIN_UNLOAD_HH + +#include + +#include +#include +#include + +#include "../plugins/InstanceCounter.hh" +#include "gz/plugin/Loader.hh" +#include "gz/plugin/PluginPtr.hh" +#include "gz/plugin/SpecializedPluginPtr.hh" + +///////////////////////////////////////////////// +/// \brief Load the InstanceCounter plugin +/// \param[in] _nodelete True if RTLD_NODELETE should be used when loading the +/// \return Pointer to the plugin +gz::plugin::PluginPtr LoadInstanceCounter(bool _nodelete) +{ + gz::plugin::Loader pl; + + std::unordered_set pluginNames = + pl.LoadLib(GzInstanceCounter_LIB, _nodelete); + + return pl.Instantiate("test::util::InstanceCounter"); +} + +///////////////////////////////////////////////// +/// \brief Load plugin, Instantiate the InstanceCounter, check the number of +/// instances, and finally unload the plugin. Note, the plugin is unloaded when +/// `instanceCounterPlugin` goes out of scope. +/// \param[in] _nodelete True if RTLD_NODELETE should be used when loading the +/// library. +/// \param[in] _numExpectedInstances Expected number of instances of the plugin. +void LoadAndTestInstanceCounter(bool _nodelete, int _numExpectedInstances) +{ + gz::plugin::PluginPtr instanceCounterPlugin = LoadInstanceCounter(_nodelete); + test::util::InstanceCounterBase *instanceCounter = + instanceCounterPlugin->QueryInterface(); + ASSERT_NE(nullptr, instanceCounter); + + EXPECT_EQ(_numExpectedInstances, instanceCounter->Instances()); +} + +#endif diff --git a/test/integration/plugin_unload_with_nodelete.cc b/test/integration/plugin_unload_with_nodelete.cc new file mode 100644 index 00000000..e1f02ea4 --- /dev/null +++ b/test/integration/plugin_unload_with_nodelete.cc @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "plugin_unload.hh" + +///////////////////////////////////////////////// +TEST(PluginsWithNoDelete, + GZ_UTILS_TEST_ENABLED_ONLY_ON_LINUX(AreNotDeletedOnUnload)) +{ + LoadAndTestInstanceCounter(true, 1); + // Since the plugin is not deleted on unload, the second time we load the + // plugin, the instance count is incremenetd. + LoadAndTestInstanceCounter(true, 2); +} diff --git a/test/integration/plugin_unload_without_nodelete.cc b/test/integration/plugin_unload_without_nodelete.cc new file mode 100644 index 00000000..60c36bbc --- /dev/null +++ b/test/integration/plugin_unload_without_nodelete.cc @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "plugin_unload.hh" + +///////////////////////////////////////////////// +TEST(PluginsWithoutNoDelete, + GZ_UTILS_TEST_ENABLED_ONLY_ON_LINUX(AreDeletedOnUnload)) +{ + LoadAndTestInstanceCounter(false, 1); + // Unlike the test in *with* nodelete, the number of instances will remain 1 + // after loading the plugin a second time. + LoadAndTestInstanceCounter(false, 1); +} diff --git a/test/plugins/CMakeLists.txt b/test/plugins/CMakeLists.txt index df8e4792..43604b6d 100644 --- a/test/plugins/CMakeLists.txt +++ b/test/plugins/CMakeLists.txt @@ -10,6 +10,8 @@ add_library(GzDummyPlugins SHARED DummyPlugins.cc DummyPluginsOtherTranslationUnit.cc) +add_library(GzInstanceCounter SHARED InstanceCounter.cc) + add_library(GzDummyStaticPlugin STATIC DummyStaticPlugin.cc) # Create a variable for the name of the header which will contain the dummy plugin path. @@ -23,6 +25,7 @@ foreach(plugin_target GzDummyPlugins GzFactoryPlugins GzTemplatedPlugins + GzInstanceCounter GzDummyStaticPlugin) target_link_libraries(${plugin_target} PRIVATE diff --git a/test/plugins/InstanceCounter.cc b/test/plugins/InstanceCounter.cc new file mode 100644 index 00000000..516c3329 --- /dev/null +++ b/test/plugins/InstanceCounter.cc @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "InstanceCounter.hh" + +namespace test +{ +namespace util +{ + +namespace { + +///////////////////////////////////////////////// +int numInstancesImpl() { + // Use a static variable that never gets deleted as a way to demonstrate + // that plugins with RTLD_NODELETE are not deleted when unloaded. + static int *instances = new int(0); + ++(*instances); + return *instances; +} +} + +/// \brief A class that counts the number of times a plugin has been +/// instantiated. +class InstanceCounter : public InstanceCounterBase +{ + public: InstanceCounter() : instances(numInstancesImpl()) + { + } + + public: ~InstanceCounter() override = default; + + public: int Instances() override + { + return this->instances; + } + + private: int instances; +}; + +GZ_ADD_PLUGIN(InstanceCounter, InstanceCounterBase) +} // namespace util +} // namespace test diff --git a/test/plugins/InstanceCounter.hh b/test/plugins/InstanceCounter.hh new file mode 100644 index 00000000..c58415e9 --- /dev/null +++ b/test/plugins/InstanceCounter.hh @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GZ_PLUGIN_TEST_PLUGINS_INSTANCECOUNTER_HH_ +#define GZ_PLUGIN_TEST_PLUGINS_INSTANCECOUNTER_HH_ + +namespace test +{ +namespace util +{ +/// \brief Get the instance count of this plugin, that's the number of times +/// this plugin has been instantiated in this process. +class InstanceCounterBase +{ + public: virtual ~InstanceCounterBase() = default; + + public: virtual int Instances() = 0; +}; + +} // namespace util +} // namespace test +#endif From c0b12e9b099ce6b353c74612a733ecbda3150dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Hern=C3=A1ndez=20Cordero?= Date: Tue, 13 Sep 2022 16:15:48 +0200 Subject: [PATCH 5/9] Improved install instructions (#106) Signed-off-by: ahcorde --- tutorials/02_installation.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tutorials/02_installation.md b/tutorials/02_installation.md index 333c5bc2..37603a42 100644 --- a/tutorials/02_installation.md +++ b/tutorials/02_installation.md @@ -48,9 +48,12 @@ sudo apt install libgz-plugin2-dev 1. Install Gazebo Tools if you want to use the `gz plugin` command line tool: ```bash sudo apt-get install gz-tools2 + ``` 2. Clone the repository ```bash + # Optionally, append `-b gz-plugin#` (replace # with a number) to check out a specific version + # From version 2 use `gz-plugin#`, lower versions `ign-plugin#` git clone https://github.com/gazebosim/gz-plugin ``` @@ -101,6 +104,8 @@ Sierra (10.12) or later. 2. Clone the repository ```bash + # Optionally, append `-b gz-plugin#` (replace # with a number) to check out a specific version + # From version 2 use `gz-plugin#`, lower versions `ign-plugin#` git clone https://github.com/gazebosim/gz-plugin ``` @@ -159,7 +164,8 @@ This assumes you have created and activated a Conda environment while installing 2. Navigate to where you would like to build the library, and clone the repository. ```bash - # Optionally, append `-b ign-plugin#` (replace # with a number) to check out a specific version + # Optionally, append `-b gz-plugin#` (replace # with a number) to check out a specific version + # From version 2 use `gz-plugin#`, lower versions `ign-plugin#` git clone https://github.com/gazebosim/gz-plugin ``` @@ -191,6 +197,8 @@ You can also generate the documentation from a clone of this repository by follo 2. Clone the repository ```bash + # Optionally, append `-b gz-plugin#` (replace # with a number) to check out a specific version + # From version 2 use `gz-plugin#`, lower versions `ign-plugin#` git clone https://github.com/gazebosim/gz-plugin ``` From 931428a201f9965e1d086a349020342c39257a7a Mon Sep 17 00:00:00 2001 From: Nate Koenig Date: Fri, 23 Sep 2022 05:33:37 -0700 Subject: [PATCH 6/9] 2.0.0 release (#107) * 2.0.0 release Signed-off-by: Nate Koenig * add a few more entries Signed-off-by: Steve Peters Signed-off-by: Nate Koenig Signed-off-by: Steve Peters Co-authored-by: Nate Koenig Co-authored-by: Steve Peters --- CMakeLists.txt | 2 +- Changelog.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 429407d4..7e2bfd93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ set(GZ_CMAKE_VER ${gz-cmake3_VERSION_MAJOR}) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -gz_configure_project(VERSION_SUFFIX pre1) +gz_configure_project(VERSION_SUFFIX) #============================================================================ # Set project-specific options diff --git a/Changelog.md b/Changelog.md index ba73ee51..a12c97e6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,47 @@ +## Gazebo Plugin 2.x + +### Gazebo Plugin 2.0.0 + +1. Add option to use `RTLD_NODELETE` when loading a library. + * [Pull request #102](https://github.com/gazebosim/gz-plugin/pull/102) + +1. Improve install instructions. + * [Pull request #106](https://github.com/gazebosim/gz-plugin/pull/106) + +1. Version bumps for Garden and deprecations. + * [Pull request #74](https://github.com/gazebosim/gz-plugin/pull/74) + * [Pull request #76](https://github.com/gazebosim/gz-plugin/pull/76) + * [Pull request #77](https://github.com/gazebosim/gz-plugin/pull/77) + +1. Ignition to Gazebo rename + * [Pull request #78](https://github.com/gazebosim/gz-plugin/pull/78) + * [Pull request #79](https://github.com/gazebosim/gz-plugin/pull/79) + * [Pull request #82](https://github.com/gazebosim/gz-plugin/pull/82) + * [Pull request #83](https://github.com/gazebosim/gz-plugin/pull/83) + * [Pull request #86](https://github.com/gazebosim/gz-plugin/pull/86) + * [Pull request #87](https://github.com/gazebosim/gz-plugin/pull/87) + * [Pull request #88](https://github.com/gazebosim/gz-plugin/pull/88) + * [Pull request #89](https://github.com/gazebosim/gz-plugin/pull/89) + * [Pull request #90](https://github.com/gazebosim/gz-plugin/pull/90) + * [Pull request #93](https://github.com/gazebosim/gz-plugin/pull/93) + * [Pull request #104](https://github.com/gazebosim/gz-plugin/pull/104) + +1. CLI tool updates. + * [Pull request #55](https://github.com/gazebosim/gz-plugin/pull/55) + * [Pull request #65](https://github.com/gazebosim/gz-plugin/pull/65) + * [Pull request #69](https://github.com/gazebosim/gz-plugin/pull/69) + * [Pull request #80](https://github.com/gazebosim/gz-plugin/pull/80) + * [Pull request #92](https://github.com/gazebosim/gz-plugin/pull/92) + +1. Update GoogleTest to latest version. + * [Pull request #91](https://github.com/gazebosim/gz-plugin/pull/91) + +1. Clean unused lambda capture warning. + * [Pull request #95](https://github.com/gazebosim/gz-plugin/pull/95) + +1. Support static plugins. + * [Pull request #97](https://github.com/gazebosim/gz-plugin/pull/97) + ## Gazebo Plugin 1.x ### Gazebo Plugin 1.2.1 (2021-09-24) From e86f92516ee954e0f56645753fc8ea841380ac7b Mon Sep 17 00:00:00 2001 From: methylDragon Date: Fri, 11 Nov 2022 22:50:45 +0800 Subject: [PATCH 7/9] ign -> gz Migrate Ignition Headers : gz-plugin (#101) Signed-off-by: methylDragon --- CMakeLists.txt | 6 +- MIGRATION.md | 7 +- core/CMakeLists.txt | 3 +- core/include/CMakeLists.txt | 2 + .../{ignition => gz}/plugin/CMakeLists.txt | 0 .../include/gz/plugin/EnablePluginFromThis.hh | 86 ++++++ core/include/gz/plugin/Factory.hh | 148 ++++++++++ core/include/gz/plugin/Info.hh | 105 +++++++ core/include/gz/plugin/Plugin.hh | 220 +++++++++++++++ core/include/gz/plugin/PluginPtr.hh | 223 +++++++++++++++ core/include/gz/plugin/SpecializedPlugin.hh | 165 +++++++++++ .../include/gz/plugin/SpecializedPluginPtr.hh | 75 +++++ core/include/gz/plugin/WeakPluginPtr.hh | 102 +++++++ .../{ignition => gz}/plugin/config.hh.in | 13 +- .../{ignition => gz}/plugin/detail/Factory.hh | 8 +- .../{ignition => gz}/plugin/detail/Plugin.hh | 6 +- .../plugin/detail/PluginPtr.hh | 8 +- .../plugin/detail/SpecializedPlugin.hh | 6 +- .../{ignition => gz}/plugin/detail/utility.hh | 4 +- core/include/gz/plugin/utility.hh | 64 +++++ core/include/ignition/plugin.hh | 19 ++ .../ignition/plugin/EnablePluginFromThis.hh | 73 +---- core/include/ignition/plugin/Export.hh | 19 ++ core/include/ignition/plugin/Factory.hh | 137 +--------- core/include/ignition/plugin/Info.hh | 92 +------ core/include/ignition/plugin/Plugin.hh | 207 +------------- core/include/ignition/plugin/PluginPtr.hh | 210 +------------- .../ignition/plugin/SpecializedPlugin.hh | 152 +---------- .../ignition/plugin/SpecializedPluginPtr.hh | 62 +---- core/include/ignition/plugin/WeakPluginPtr.hh | 89 +----- core/include/ignition/plugin/config.hh | 33 +++ core/include/ignition/plugin/utility.hh | 51 +--- core/src/EnablePluginFromThis.cc | 4 +- core/src/Factory.cc | 2 +- core/src/Factory_TEST.cc | 2 +- core/src/Info.cc | 2 +- core/src/Info_TEST.cc | 2 +- core/src/Plugin.cc | 4 +- core/src/WeakPluginPtr.cc | 2 +- core/src/utility.cc | 2 +- core/src/utility_TEST.cc | 2 +- examples/integrators.cc | 4 +- examples/plugins/ExponentialODE.cc | 2 +- examples/plugins/ForwardEuler.cc | 2 +- examples/plugins/PolynomialODE.cc | 2 +- examples/plugins/RungeKutta4.cc | 2 +- examples/plugins/integrators.hh | 4 +- examples/plugins/robot.hh | 10 +- examples/robot.cc | 6 +- loader/CMakeLists.txt | 8 +- loader/include/CMakeLists.txt | 2 + loader/include/gz/plugin/Loader.hh | 256 ++++++++++++++++++ .../{ignition => gz}/plugin/detail/Loader.hh | 8 +- loader/include/ignition/plugin/Loader.hh | 243 +---------------- .../include/ignition/plugin/loader/Export.hh | 19 ++ loader/src/Loader.cc | 8 +- loader/src/Loader_TEST.cc | 6 +- loader/src/{ign.cc => gz.cc} | 4 +- loader/src/{ign_TEST.cc => gz_TEST.cc} | 2 +- register/include/CMakeLists.txt | 2 + register/include/gz/plugin/Register.hh | 140 ++++++++++ register/include/gz/plugin/RegisterMore.hh | 36 +++ .../plugin/detail/Register.hh | 12 +- register/include/ignition/plugin/Register.hh | 129 +-------- .../include/ignition/plugin/RegisterMore.hh | 25 +- test/integration/EnablePluginFromThis_TEST.cc | 8 +- test/integration/WeakPluginPtr.cc | 4 +- test/integration/aliases.cc | 2 +- test/integration/deprecated_TEST.cc | 26 ++ test/integration/factory.cc | 4 +- test/integration/plugin.cc | 6 +- test/integration/templated_plugins.cc | 4 +- test/integration/utils.hh | 4 +- test/performance/plugin_specialization.cc | 4 +- test/plugins/BadPluginAPIVersionNew.cc | 2 +- test/plugins/BadPluginAPIVersionOld.cc | 2 +- test/plugins/BadPluginAlign.cc | 2 +- test/plugins/BadPluginNoInfo.cc | 2 +- test/plugins/BadPluginSize.cc | 2 +- test/plugins/DummyMultiPlugin.hh | 6 +- test/plugins/DummyPlugins.cc | 2 +- test/plugins/DummyPlugins.hh | 4 +- .../DummyPluginsOtherTranslationUnit.cc | 2 +- test/plugins/FactoryPlugins.cc | 2 +- test/plugins/FactoryPlugins.hh | 6 +- test/plugins/GenericExport.hh | 4 +- test/plugins/TemplatedPlugins.cc | 2 +- test/plugins/TemplatedPlugins.hh | 4 +- .../plugin_bad_const_assignment.cc | 2 +- .../plugin_bad_const_construct.cc | 2 +- .../static_assertions/plugin_no_base_class.cc | 2 +- .../plugin_wrong_base_class.cc | 2 +- 92 files changed, 1910 insertions(+), 1551 deletions(-) create mode 100644 core/include/CMakeLists.txt rename core/include/{ignition => gz}/plugin/CMakeLists.txt (100%) create mode 100644 core/include/gz/plugin/EnablePluginFromThis.hh create mode 100644 core/include/gz/plugin/Factory.hh create mode 100644 core/include/gz/plugin/Info.hh create mode 100644 core/include/gz/plugin/Plugin.hh create mode 100644 core/include/gz/plugin/PluginPtr.hh create mode 100644 core/include/gz/plugin/SpecializedPlugin.hh create mode 100644 core/include/gz/plugin/SpecializedPluginPtr.hh create mode 100644 core/include/gz/plugin/WeakPluginPtr.hh rename core/include/{ignition => gz}/plugin/config.hh.in (82%) rename core/include/{ignition => gz}/plugin/detail/Factory.hh (97%) rename core/include/{ignition => gz}/plugin/detail/Plugin.hh (96%) rename core/include/{ignition => gz}/plugin/detail/PluginPtr.hh (97%) rename core/include/{ignition => gz}/plugin/detail/SpecializedPlugin.hh (98%) rename core/include/{ignition => gz}/plugin/detail/utility.hh (92%) create mode 100644 core/include/gz/plugin/utility.hh create mode 100644 core/include/ignition/plugin.hh create mode 100644 core/include/ignition/plugin/Export.hh create mode 100644 core/include/ignition/plugin/config.hh create mode 100644 loader/include/CMakeLists.txt create mode 100644 loader/include/gz/plugin/Loader.hh rename loader/include/{ignition => gz}/plugin/detail/Loader.hh (91%) create mode 100644 loader/include/ignition/plugin/loader/Export.hh rename loader/src/{ign.cc => gz.cc} (96%) rename loader/src/{ign_TEST.cc => gz_TEST.cc} (99%) create mode 100644 register/include/CMakeLists.txt create mode 100644 register/include/gz/plugin/Register.hh create mode 100644 register/include/gz/plugin/RegisterMore.hh rename register/include/{ignition => gz}/plugin/detail/Register.hh (98%) create mode 100644 test/integration/deprecated_TEST.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index a75c51fc..f27ce6c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,10 @@ set(IGN_CMAKE_VER ${ignition-cmake2_VERSION_MAJOR}) #============================================================================ # Configure the project #============================================================================ -ign_configure_project(VERSION_SUFFIX) +ign_configure_project( + REPLACE_IGNITION_INCLUDE_PATH gz/plugin + VERSION_SUFFIX +) #============================================================================ # Set project-specific options @@ -71,4 +74,3 @@ ign_create_docs( API_MAINPAGE_MD "${CMAKE_BINARY_DIR}/api.md" TUTORIALS_MAINPAGE_MD "${CMAKE_BINARY_DIR}/tutorials.md" ) - diff --git a/MIGRATION.md b/MIGRATION.md index 2a7ce03f..568dcb9a 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -68,9 +68,9 @@ simply need to make sure that the compiler can resolve the names of the classes that you pass to it (and there will be a compilation error if it cannot). It is now possible to register plugins across **multiple translation units** -within a single library. To do this, use `#include ` +within a single library. To do this, use `#include ` in **exactly one** of your library's translation units, and then use -`#include ` in all other translation units. It +`#include ` in all other translation units. It does not matter which translation unit you choose to be the "first", as long as you choose exactly one. @@ -84,7 +84,7 @@ then you should continue to use it. It does not have a replacement in `ign-plugi Here is a list of things that you *should* replace: -* `#include ` should be replaced with `#include ` +* `#include ` should be replaced with `#include ` * `ignition::common::PluginLoader` should be replaced with `ignition::plugin::Loader` * When calling `Loader::Instantiate("....")` do **NOT** prefix the class name with `::`. E.g. `"::some_namespace::MyClass"` should now be `"some_namespace::MyClass"`. @@ -164,4 +164,3 @@ In general, plugin names that get passed to a `Loader` should not be hard-coded. They should be selected by either inspecting what interfaces they provide, or by having a user specify the plugin name. This rule of thumb applies to both template-based classes and to regular classes. - diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 67ecec46..775972ff 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -16,5 +16,4 @@ ign_build_tests( TYPE UNIT SOURCES ${tests}) - -add_subdirectory(include/ignition/plugin) +add_subdirectory(include) diff --git a/core/include/CMakeLists.txt b/core/include/CMakeLists.txt new file mode 100644 index 00000000..58b89f97 --- /dev/null +++ b/core/include/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(gz/plugin) +install(DIRECTORY ignition DESTINATION ${IGN_INCLUDE_INSTALL_DIR_FULL}) diff --git a/core/include/ignition/plugin/CMakeLists.txt b/core/include/gz/plugin/CMakeLists.txt similarity index 100% rename from core/include/ignition/plugin/CMakeLists.txt rename to core/include/gz/plugin/CMakeLists.txt diff --git a/core/include/gz/plugin/EnablePluginFromThis.hh b/core/include/gz/plugin/EnablePluginFromThis.hh new file mode 100644 index 00000000..6deaf4d9 --- /dev/null +++ b/core/include/gz/plugin/EnablePluginFromThis.hh @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GZ_PLUGIN_ENABLEPLUGINFROMTHIS_HH_ +#define GZ_PLUGIN_ENABLEPLUGINFROMTHIS_HH_ + +#include + +#include + +namespace ignition +{ + namespace plugin + { + // Forward declaration + class Loader; + + /// \brief EnablePluginFromThis is an optional base class which can be + /// inherited by Plugin classes. When a Plugin class inherits it and that + /// Plugin class is instantiated using the Loader class, its instance will + /// be able to access the PluginPtr that manages its lifecycle. This + /// interface will also be available by calling + /// `instance->QueryInterface()` + /// + /// \remark This class is analogous to std::enable_shared_from_this + class IGNITION_PLUGIN_VISIBLE EnablePluginFromThis + { + /// \brief Default constructor + public: EnablePluginFromThis(); + + /// \brief Get a copy of the PluginPtr that manages this object. + /// \return a copy of the PluginPtr that manages this object. + public: PluginPtr PluginFromThis(); + + /// \brief Get a const-qualified copy of the PluginPtr that manages this + /// object. + /// \return a const-qualified copy of the PluginPtr that manages this + /// object. + public: ConstPluginPtr PluginFromThis() const; + + /// \brief Destructor + public: virtual ~EnablePluginFromThis(); + + /// \brief This is an abstract shared_ptr to the Plugin instance. This + /// shared_ptr will maintain a reference count on the shared library that + /// provides the plugin so that the shared library does not get unloaded + /// while this shared_ptr is still alive. + /// + /// This function is meant for advanced use-cases, such as creating + /// Factory plugins, so we keep it protected. Only use this if you know + /// what you are doing. + /// + /// \return shared_ptr to the Plugin instance. + protected: std::shared_ptr PluginInstancePtrFromThis() const; + + // Declare friendship so that the internal WeakPluginPtr can be set by + // the Loader class. + friend class Loader; + + /// \brief This function is called by the Loader class whenever a plugin + /// containing this interface gets instantiated. + private: void PrivateSetPluginFromThis(const PluginPtr &_ptr); + + private: class Implementation; + IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING + private: std::unique_ptr pimpl; + IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING + }; + } +} + +#endif diff --git a/core/include/gz/plugin/Factory.hh b/core/include/gz/plugin/Factory.hh new file mode 100644 index 00000000..0b533c78 --- /dev/null +++ b/core/include/gz/plugin/Factory.hh @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ + +#ifndef GZ_PLUGIN_FACTORY_HH_ +#define GZ_PLUGIN_FACTORY_HH_ + +#include +#include +#include +#include + +#include + +namespace ignition +{ + namespace plugin + { + /// \brief This class provides a unary operator for safely deleting pointers + /// to plugin factory products with the type `Interface`. If it gets passed + /// an `Interface` pointer that is not pointing to a factory plugin product, + /// then this just performs a normal delete. + template class ProductDeleter; + + /// \brief ProductPtr is a derivative of std::unique_ptr that can safely + /// manage the products that come out of a plugin factory. It is strongly + /// recommended that factory products use a ProductPtr to manage the + /// lifecycle of a factory product. + /// + /// If you MUST release a factory product pointer, then it should at least + /// be passed to a ProductDeleter to be deleted at the end of its lifecycle. + /// If it is not possible to delete the product with a ProductDeleter, then + /// you will need to periodically call CleanupLostProducts() or else you + /// will experience memory leaks, and your factory plugin libraries will + /// never get unloaded. + template + using ProductPtr = + std::unique_ptr>; + + /// \brief The Factory class defines a plugin factory that can be used by + /// the Loader class to produce products that implement an interface. + /// + /// To define the inputs and outputs of a factory, set the template + /// arguments, for example: + /// + /// \code + /// using MyFactory = Factory; + /// \endcode + /// + /// defines a factory that can produce a `std::unique_ptr` + /// given arguments of `InputType1` and `InputType2`. + /// + /// To register a factory, use the `IGNITION_ADD_FACTORY` macro, e.g.: + /// + /// \code + /// IGNITION_ADD_FACTORY(ImplementedClass, MyFactory) + /// \endcode + /// + /// where `ImplementedClass` is the name of the class that your plugin + /// library has used to implement `InterfaceClass`. + template + class Factory : public EnablePluginFromThis + { + public: using ProductPtrType = ProductPtr; + + /// \brief This function is called by Loader to construct the class that + /// implements the InterfacePtr interface. + /// \param[in] _args + /// The arguments as defined by the template parameters. + /// \return an RAII-managed reference to the interface type as defined by + /// the template parameters. + public: ProductPtrType Construct(Args&&... _args); + + /// \internal \brief This function gets implemented by Producing + /// to manufacture the product instance. + /// \param[in] _args + /// The arguments as defined by the template parameters + /// \return a raw pointer to the product + private: virtual Interface *ImplConstruct(Args&&... _args) = 0; + + /// \private This nested class is used to implement the plugin factory. + /// It is not intended for external use. + public: template + class Producing; + }; + + /// \brief Call this function to cleanup the Factories of any Products which + /// were not managed by a ProductPtr or deleted by a ProductDeleter (in + /// other words, the Product was released from its ProductPtr and then its + /// lifecycle was managed by a framework that does not know it has special + /// deletion requirements). + /// + /// If you never call the .release() function on a ProductPtr, then you will + /// never need to call this function. + /// + /// \warning Note that this function should be called ONLY while there are + /// no Products that are actively destructing, or else there is a miniscule + /// probability of causing a segmentation fault. This is never an issue in a + /// single-threaded application. + /// + /// \warning If you have a multi-threaded application where you have + /// absolutely no control over the lifecycle of the products, and you cannot + /// reliably predict a safe window in which you know that no products are + /// being actively deleted, then you can specify a short safety wait to the + /// cleanup call. If any products were being deleted while this function is + /// called, this wait can give them time to fully exit their destructors + /// before we unload their libraries. + /// + /// \note For some applications, it might not be important if there are tiny + /// memory leaks or if plugin libraries remain loaded until the application + /// exits. For those applications, it is okay to not bother calling this + /// function at all. + /// + /// \param[in] _safetyWait + /// For multi-threaded applications, this short waiting window gives time + /// for products that are currently being deleted to exit their + /// destructors before we unload their libraries. If you can reliably + /// predict a window of time in which no products are actively being + /// destructed (or if you have a single-threaded application), then it is + /// okay to set this waiting time to 0. Note that any threads which are + /// about to destruct a product will be blocked until this wait is over. + void IGNITION_PLUGIN_VISIBLE CleanupLostProducts( + const std::chrono::nanoseconds &_safetyWait = + std::chrono::nanoseconds(5)); + + /// \brief Get the number of lost products that have currently accumulated + /// since the last time CleanupLostProducts() was called (or since the + /// program began, if CleanupLostProducts() has not been called yet). + std::size_t IGNITION_PLUGIN_VISIBLE LostProductCount(); + } +} + +#include + +#endif diff --git a/core/include/gz/plugin/Info.hh b/core/include/gz/plugin/Info.hh new file mode 100644 index 00000000..78c28b50 --- /dev/null +++ b/core/include/gz/plugin/Info.hh @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef GZ_PLUGIN_INFO_HH_ +#define GZ_PLUGIN_INFO_HH_ + +#include +#include +#include +#include +#include + +#include + +#include + +namespace ignition +{ + namespace plugin + { + /// \brief sentinel value to check if a plugin was built with the same + /// version of the Info struct + // + /// This must be incremented when the Info struct changes + const int INFO_API_VERSION = 1; + + // We use an inline namespace to assist in forward-compatibility. Eventually + // we may want to support a version-2 of the Info API, in which case + // we will remove the "inline" declaration here, and create a new inline + // namespace called "v2". This original Info object will continue to + // be accessible for backwards compatibility, and even its symbol name in + // the ABI should remain the same. + inline namespace v1 + { + /// \brief Holds info required to construct a plugin + struct IGNITION_PLUGIN_VISIBLE Info + { + /// \brief Clear out all information contained in this Info object + void Clear(); + + /// \brief The name of the plugin + IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING + std::string name; + IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING + + /// \brief Alternative names that may be used to instantiate the plugin + IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING + std::set aliases; + IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING + + /// \brief The keys are the names of the types of interfaces that this + /// plugin provides. The values are functions that convert a void + /// pointer (which actually points to the plugin instance) to another + /// void pointer (which actually points to the location of the interface + /// within the plugin instance). + IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING + using InterfaceCastingMap = + std::unordered_map< std::string, std::function >; + InterfaceCastingMap interfaces; + IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING + + /// \brief This is a set containing the demangled versions of the names + /// of the interfaces provided by this plugin. This gets filled in by + /// the Loader after receiving the Info. It is only used by + /// the user-facing API. Internally, when looking up Interfaces, the + /// mangled `interfaces` map will still be used. + IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING + std::set demangledInterfaces; + IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING + + /// \brief A method that instantiates a new instance of a plugin + IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING + std::function factory; + IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING + + /// \brief A method that safely deletes an instance of the plugin + IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING + std::function deleter; + IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING + }; + } + + /// This typedef is used simultaneously by detail/Register.hh and Loader.cc, + /// so we store it in a location that is visible to both of them. + using InfoMap = std::unordered_map; + using ConstInfoPtr = std::shared_ptr; + } +} + +#endif diff --git a/core/include/gz/plugin/Plugin.hh b/core/include/gz/plugin/Plugin.hh new file mode 100644 index 00000000..cae84e90 --- /dev/null +++ b/core/include/gz/plugin/Plugin.hh @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef GZ_PLUGIN_PLUGIN_HH_ +#define GZ_PLUGIN_PLUGIN_HH_ + +#include +#include +#include + +#include + +#include +#include + +namespace ignition +{ + namespace plugin + { + // Forward declaration + namespace detail { + template class ComposePlugin; + template class SelectSpecializers; + } + class EnablePluginFromThis; + class WeakPluginPtr; + + class IGNITION_PLUGIN_VISIBLE Plugin + { + // -------------------- Public API --------------------- + + /// \brief Get an interface of the specified type, if it is provided by + /// this plugin. + /// + /// Note that the interface pointer you receive is owned by the Plugin + /// object. You MUST NOT ever try to deallocate it yourself. Moreover, the + /// pointer will be invalidated once all Plugin objects that refer to the + /// same Plugin instance are destructed. Use the QueryInterfaceSharedPtr + /// function in order to get a reference-counting pointer to an interface + /// of this Plugin object. The pointer will remain valid as long as the + /// std::shared_ptr provided by QueryInterfaceSharedPtr is alive. + /// + /// \return A raw pointer to the specified interface. If the requested + /// _interfaceName is not provided by this Plugin, this returns a nullptr. + /// This pointer is invalidated when the reference count of the plugin + /// instance drops to zero. + public: template + Interface *QueryInterface(); + + /// \brief const-qualified version of QueryInterface() + public: template + const Interface *QueryInterface() const; + + /// \brief This function has been deprecated in favor of the version of + /// QueryInterface which does not take a std::string argument. + public: template + IGN_DEPRECATED(0.0) + Interface *QueryInterface(const std::string &/*_interfaceName*/); + + /// \brief const-qualified version of + /// QueryInterface(std::string) + public: template + IGN_DEPRECATED(0.0) + const Interface *QueryInterface( + const std::string &/*_interfaceName*/) const; + + /// \brief Get the requested interface as a std::shared_ptr. The template + /// argument Interface must exactly match the underlying type associated + /// with _interfaceName, or else the behavior of this function is + /// undefined. + /// + /// This std::shared_ptr and the interface+plugin that it refers to will + /// remain valid, even if all Plugin objects which refer to the plugin + /// instance are destructed. + /// + /// You MUST NOT attempt to pass a QueryInterface pointer into a + /// std::shared_ptr yourself; that will result in double-delete memory + /// errors. You must always call QueryInterfaceSharedPtr for a reference- + /// counting pointer to an interface. + /// + /// \return A reference-counting pointer to the specified interface. This + /// will keep the interface valid and the plugin instance alive, even if + /// all Plugin objects that refer to this plugin instance are destructed. + public: template + std::shared_ptr QueryInterfaceSharedPtr(); + + /// \brief Same as QueryInterfaceSharedPtr(), but it returns a + /// std::shared_ptr to a const-qualified Interface. + public: template + std::shared_ptr QueryInterfaceSharedPtr() const; + + /// \brief This version of QueryInterfaceSharedPtr has been deprecated in + /// favor of the version that does not take a std::string argument. + public: template + IGN_DEPRECATED(0.0) + std::shared_ptr QueryInterfaceSharedPtr( + const std::string &/*_interfaceName*/); + + /// \brief Same as QueryInterfaceSharedPtr(std::string), but + /// it returns a std::shared_ptr to a const-qualified Interface. + public: template + IGN_DEPRECATED(0.0) + std::shared_ptr QueryInterfaceSharedPtr( + const std::string &/*_interfaceName*/) const; + + /// \brief Checks if this Plugin has the specified type of interface. + /// \return Returns true if this Plugin has the specified type of + /// interface, and false otherwise. + public: template + bool HasInterface() const; + + /// \brief Checks if this Plugin has the specified type of interface. + /// + /// By default, we expect you to pass in a demangled version of the + /// interface name. If you want to use a mangled version of the name, + /// set the `demangled` argument to false. + /// + /// \param[in] _interfaceName The name of the desired interface, as a + /// std::string. Note that this expects the name to be mangled. + /// \param[in] _demangled If _interfaceName is demangled, set this to + /// true. If you are instead using the raw mangled name that gets provided + /// by typeid(T).name(), then set _demangled to false. + /// \return Returns true if this Plugin has the specified type of + /// interface, and false otherwise. + public: bool HasInterface(const std::string &_interfaceName, + const bool _demangled = true) const; + + /// \brief Gets the name of this Plugin. + /// \return A pointer to the name of this Plugin, or nullptr if this + /// Plugin is not instantiated. + public: const std::string *Name() const; + + // -------------------- Private API ----------------------- + + template friend class TemplatePluginPtr; + template friend class SpecializedPlugin; + template friend class detail::ComposePlugin; + template friend class detail::SelectSpecializers; + friend class EnablePluginFromThis; + friend class WeakPluginPtr; + + /// \brief Default constructor. This is kept protected to discourage users + /// from instantiating them directly. They should instead only be + /// retrieved as a PluginPtr from the plugin Loader. + protected: Plugin(); + + /// \brief Type-agnostic retriever for interfaces + private: void *PrivateQueryInterface( + const std::string &_interfaceName) const; + + /// \brief Copy the plugin instance from another Plugin object + private: void PrivateCopyPluginInstance(const Plugin &_other) const; + + /// \brief Copy an existing plugin instance into this plugin + /// \param[in] _info + /// Pointer to the Info for this plugin + /// \param[in] _instancePtr + /// Pointer to an already-existing abstract plugin instance pointer + private: void PrivateCopyPluginInstance( + const ConstInfoPtr &_info, + const std::shared_ptr &_instancePtr) const; + + /// \brief Create a new plugin instance based on the info provided + /// \param[in] _info + /// Pointer to the Info for this plugin + /// \param[in] _dlHandlePtr + /// Reference counter for the dl handle of this Plugin + private: void PrivateCreatePluginInstance( + const ConstInfoPtr &_info, + const std::shared_ptr &_dlHandlePtr) const; + + /// \brief Get a reference to the abstract instance being managed by this + /// wrapper + private: const std::shared_ptr &PrivateGetInstancePtr() const; + + /// \brief Get a reference to the Info being used by this wrapper + private: const ConstInfoPtr &PrivateGetInfoPtr() const; + + /// \brief The InterfaceMap type needs to get used in several places, like + /// Plugin::Implementation and SpecializedPlugin. We make the typedef + /// public so that those other classes can use it without needing to be + /// friends of Plugin. End-users should not have any need for this + /// typedef. + public: using InterfaceMap = std::map; + + /// \brief Get or create an iterator to the std::map that holds pointers + /// to the various interfaces provided by this plugin instance. + private: InterfaceMap::iterator PrivateGetOrCreateIterator( + const std::string &_interfaceName); + + class Implementation; + IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING + /// \brief PIMPL pointer to the implementation of this class. + private: const std::unique_ptr dataPtr; + IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING + + /// \brief Virtual destructor + public: virtual ~Plugin(); + }; + } +} + +#include "gz/plugin/detail/Plugin.hh" + +#endif diff --git a/core/include/gz/plugin/PluginPtr.hh b/core/include/gz/plugin/PluginPtr.hh new file mode 100644 index 00000000..51d547c6 --- /dev/null +++ b/core/include/gz/plugin/PluginPtr.hh @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef GZ_PLUGIN_PLUGINPTR_HH_ +#define GZ_PLUGIN_PLUGINPTR_HH_ + +#include +#include +#include + +#include + +namespace ignition +{ + namespace plugin + { + // Forward declarations + namespace detail { template class ComposePlugin; } + + /// \brief This class manages the lifecycle of a plugin instance. It can + /// receive a plugin instance from the ignition::plugin::Loader class + /// or by copy-construction or assignment from another PluginPtr instance. + /// + /// This class behaves similarly to a std::shared_ptr where multiple + /// PluginPtr objects can share a single plugin instance, and the plugin + /// instance will not be deleted until all PluginPtr objects that refer to + /// it are either destroyed, cleared, or begin referring to a different + /// plugin instance. + /// + /// A PluginPtr object can be "cast" to a SpecializedPluginPtr object by + /// simply using the copy/move constructor or assignment operator of a + /// SpecializedPluginPtr object. Note that this "cast" does have a small + /// amount of overhead associated with it, but it may result in huge savings + /// after initialization is finished if you frequently access the interfaces + /// that the SpecializedPluginPtr is specialized for. + template + class TemplatePluginPtr final + { + /// \brief Destructor. Deletes this PluginPtr's reference to the plugin + /// instance. Once all PluginPtrs that refer to a plugin instance are + /// deleted, the plugin will also be deleted. + public: ~TemplatePluginPtr() = default; + + /// \brief Default constructor. Creates a PluginPtr object that does not + /// point to any plugin instance. IsEmpty() will return true until a + /// plugin instance is provided. + public: TemplatePluginPtr(); + + /// \brief Copy constructor. This PluginPtr will now point at the same + /// plugin instance as _other, and they will share ownership. + /// \param[in] _other Pointer to plugin being copied. + public: TemplatePluginPtr(const TemplatePluginPtr &_other); + + /// \brief Move constructor. This PluginPtr will take ownership of the + /// plugin instance held by _other. If this PluginPtr was holding an + /// instance to another plugin, that instance will be deleted if no other + /// PluginPtr is referencing which is being moved. + /// \param[in] _other Plugin being moved. + public: TemplatePluginPtr(TemplatePluginPtr &&_other); + + /// \brief Casting constructor. This PluginPtr will now point at the same + /// plugin instance as _other, and they will share ownership. This + /// essentially allows casting between PluginPtrs that are holding + /// different types of plugin wrappers (for example, you can cast a + /// generic PluginPtr to any SpecializedPluginPtr type, or you can cast + /// between different types of specializations). + /// \param[in] _other Pointer to plugin being casted, which is of a + /// different type. + public: template + TemplatePluginPtr( + const TemplatePluginPtr &_other); + + /// \brief Copy assignment operator. This PluginPtr will now point at the + /// same plugin instance as _other, and they will share ownership. If this + /// PluginPtr was holding an instance to another plugin, that instance + /// will be deleted if no other PluginPtr is referencing it. + /// \param[in] _other Pointer to plugin being copied. + public: TemplatePluginPtr &operator =(const TemplatePluginPtr &_other); + + /// \brief Casting operator. This PluginPtr will now point at the same + /// plugin instance as _other, and they will share ownership. This + /// essentially allows casting between PluginPtrs that are holding + /// different types of plugin wrappers. + /// \param[in] _other Pointer to plugin being casted, which is of a + /// different type. + /// \return A reference to this object. + public: template + TemplatePluginPtr &operator =( + const TemplatePluginPtr &_other); + + /// \brief Move assignment operator. This PluginPtr will take ownership + /// of the plugin instance held by _other. If this PluginPtr was holding + /// an instance to another plugin, that instance will be deleted if no + /// other PluginPtr is referencing it. + /// \param[in] _other Plugin being moved. + /// \return A reference to this object. + public: TemplatePluginPtr &operator=(TemplatePluginPtr &&_other); + + /// \brief nullptr assignment operator. Same as calling Clear() + /// \param[in] _null nullptr object. + /// \return A reference to this object. + public: TemplatePluginPtr &operator=(std::nullptr_t _null); + + /// \brief Access the wrapper for the plugin instance and call one of its + /// member functions. + /// \return The ability to call a member function on the underlying Plugin + /// object. + public: PluginType *operator->() const; + + /// \brief Get a reference to the wrapper for the plugin instance that is + /// being managed by this PluginPtr. + /// \return A reference to the underlying Plugin object. + public: PluginType &operator*() const; + + /// \brief Comparison operator. + /// \param[in] _other Plugin to compare to. + /// \returns True if this Plugin is holding the same plugin + /// instance as _other, otherwise returns false. + public: bool operator ==(const TemplatePluginPtr &_other) const; + + /// \brief Comparison operator. + /// \param[in] _other Plugin to compare to. + /// \returns True if the pointer value of the plugin instance held + /// by this PluginPtr is less than the pointer value of the instance held + /// by _other. + public: bool operator <(const TemplatePluginPtr &_other) const; + + /// \brief Comparison operator. + /// \param[in] _other Plugin to compare to. + /// \returns True if the pointer value of the plugin instance held + /// by this PluginPtr is greater than the pointer value of the instance + /// held by _other. + public: bool operator >(const TemplatePluginPtr &_other) const; + + /// \brief Comparison operator. + /// \param[in] _other Plugin to compare to. + /// \returns True if the pointer instance held by this PluginPtr is + /// different from the pointer instance held by _other. + public: bool operator !=(const TemplatePluginPtr &_other) const; + + /// \brief Comparison operator. + /// \param[in] _other Plugin to compare to. + /// \returns True if the value of the pointer instance held by this + /// PluginPtr is less than or equal to the value of the pointer instance + /// held by _other. + public: bool operator <=(const TemplatePluginPtr &_other) const; + + /// \brief Comparison operator. + /// \param[in] _other Plugin to compare to. + /// \returns True if the value of the pointer instance held by this + /// PluginPtr is greater than or equal to the value of the pointer + /// instance held by _other. + public: bool operator >=(const TemplatePluginPtr &_other) const; + + /// \brief Produces a hash for the plugin instance that this PluginPtr is + /// holding. This function allows PluginPtr instances to be used as values + /// in a std::unordered_set or keys in a + /// std::unordered_map. Using this function directly should + /// not normally be necessary. + /// \return A hash of the underlying pointer object. + public: std::size_t Hash() const; + + /// \brief Check whether this is pointing at a valid plugin. + /// \returns False if this PluginPtr is pointing at a valid plugin + /// instance. If it is instead pointing at a nullptr, this returns true. + public: bool IsEmpty() const; + + /// \brief Implicitly convert this PluginPtr to a boolean. + /// \return The opposite value of IsEmpty(). + public: operator bool() const; + + /// \brief Clears the Plugin instance from this PluginPtr. IsEmpty() will + /// return true after this is used, and none of the interfaces will be + /// available any longer. + public: void Clear(); + + /// \brief Pointer to the plugin wrapper that this PluginPtr is managing. + private: std::unique_ptr dataPtr; + + // Declare friendship + friend class Loader; + template friend class TemplatePluginPtr; + + /// \brief Private constructor. Creates a plugin instance based on the + /// Info provided. This should only be called by Loader to ensure that + /// the Info is well-formed, so we keep it private. + /// \param[in] _info An Info instance that was generated by + /// Loader. Alternatively, this can take a nullptr to create an + /// empty PluginPtr. + /// \param[in] _dlHandlePtr A reference count for the DL handle. + private: explicit TemplatePluginPtr( + const ConstInfoPtr &_info, + const std::shared_ptr &_dlHandlePtr); + }; + + /// \brief Typical usage for TemplatePluginPtr is to just hold a generic + /// Plugin type. + using PluginPtr = TemplatePluginPtr; + + /// \brief This produces a PluginPtr whose Plugin wrapper only grants access + /// to const-qualified interfaces of the plugin instance. + using ConstPluginPtr = TemplatePluginPtr; + } +} + +#include "gz/plugin/detail/PluginPtr.hh" + +#endif diff --git a/core/include/gz/plugin/SpecializedPlugin.hh b/core/include/gz/plugin/SpecializedPlugin.hh new file mode 100644 index 00000000..71fbcced --- /dev/null +++ b/core/include/gz/plugin/SpecializedPlugin.hh @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef GZ_PLUGIN_SPECIALIZEDPLUGIN_HH_ +#define GZ_PLUGIN_SPECIALIZEDPLUGIN_HH_ + +#include +#include "gz/plugin/Plugin.hh" + +namespace ignition +{ + namespace plugin + { + // Forward declarations + namespace detail { + template class ComposePlugin; + template class SelectSpecializers; + } + + // Forward declaration of the variadic template SpecializedPlugin class. + template + class SpecializedPlugin; + + /// \brief This class allows Plugin instances to have high-speed access to + /// interfaces that can be anticipated at compile time. The plugin does + /// not have to actually offer the specialized interface in order to get + /// this performance improvement. This template is variadic, so it can + /// support arbitrarily many interfaces. + /// + /// Usage example: + /// + /// \code + /// using MySpecialPluginPtr = SpecializedPluginPtr< + /// MyInterface1, FooInterface, MyInterface2, BarInterface>; + /// + /// MySpecialPluginPtr plugin = loader->Instantiate(pluginName); + /// \endcode + /// + /// Then, calling the function + /// + /// \code + /// plugin->QueryInterface(); + /// \endcode + /// + /// will have extremely high-speed associated with it. It will provide + /// direct access to the the `FooInterface*` of `plugin`. If `plugin` does + /// not actually offer `FooInterface`, then it will return a nullptr, still + /// at extremely high speed. + template + class SpecializedPlugin : public virtual Plugin + { + // -------------------- Public API --------------------- + + // Inherit function overloads + public: using Plugin::QueryInterface; + public: using Plugin::QueryInterfaceSharedPtr; + public: using Plugin::HasInterface; + + // Documentation inherited + public: template + Interface *QueryInterface(); + + // Documentation inherited + public: template + const Interface *QueryInterface() const; + + // Documentation inherited + public: template + std::shared_ptr QueryInterfaceSharedPtr(); + + // Documentation inherited + public: template + std::shared_ptr QueryInterfaceSharedPtr() const; + + // Documentation inherited + public: template + bool HasInterface() const; + + + // -------------------- Private API --------------------- + + // Declare friendship + template friend class SpecializedPlugin; + template friend class detail::ComposePlugin; + template friend class detail::SelectSpecializers; + template friend class TemplatePluginPtr; + + /// \brief type is an empty placeholder class which is used by the private + /// member functions to provide two overloads: a high-performance one for + /// the specialized interface, and a normal-performance one for all other + /// Interface types. + private: template struct type { }; + + /// \brief Delegate the function to the standard Plugin method + /// \param[in] _type Empty object meant to guide the compiler to pick the + /// desired implementation. + /// \return Pointer to the intergace + private: template + Interface *PrivateQueryInterface(type); + + /// \brief Use a high-speed accessor to provide this specialized interface + /// \param[in] _type Empty object meant to guide the compiler to pick the + /// desired implementation. + /// \return Pointer to the specialized intergace + private: SpecInterface *PrivateQueryInterface(type); + + /// \brief Delegate the function to the standard Plugin method + /// \param[in] _type Empty object meant to guide the compiler to pick the + /// desired implementation. + /// \return Pointer to the specialized intergace + private: template + const Interface *PrivateQueryInterface(type) const; + + /// \brief Use a high-speed accessor to provide this specialized interface + /// \param[in] _type Empty object meant to guide the compiler to pick the + /// desired implementation. + /// \return Pointer to the specialized intergace + private: const SpecInterface *PrivateQueryInterface( + type) const; + + /// \brief Delegate the function to the standard PluginPtr method + /// \param[in] _type Empty object meant to guide the compiler to pick the + /// desired implementation. + /// \return True if the interface is present. + private: template + bool PrivateHasInterface(type) const; + + /// \brief Use a high-speed accessor to check this specialized interface + /// \param[in] _type Empty object meant to guide the compiler to pick the + /// desired implementation. + /// \return True if the interface is present. + private: bool PrivateHasInterface(type) const; + + // Dev note (MXG): The privateSpecializedInterfaceIterator object must be + // available to the user during their compile time, so it cannot be hidden + // using PIMPL. The iterator is const because it must always point to the + // same entry throughout its entire lifecycle. + /// \brief Iterator that points to the entry of the specialized interface + private: + const Plugin::InterfaceMap::iterator privateSpecializedInterfaceIterator; + + /// \brief Default constructor + protected: SpecializedPlugin(); + }; + } +} + +#include "gz/plugin/detail/SpecializedPlugin.hh" + +#endif diff --git a/core/include/gz/plugin/SpecializedPluginPtr.hh b/core/include/gz/plugin/SpecializedPluginPtr.hh new file mode 100644 index 00000000..6e9ba354 --- /dev/null +++ b/core/include/gz/plugin/SpecializedPluginPtr.hh @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef GZ_PLUGIN_SPECIALIZEDPLUGINPTR_HH_ +#define GZ_PLUGIN_SPECIALIZEDPLUGINPTR_HH_ + +#include "gz/plugin/PluginPtr.hh" +#include "gz/plugin/SpecializedPlugin.hh" + +namespace ignition +{ + namespace plugin + { + /// \brief This alias allows PluginPtr instances to have high-speed access + /// to interfaces that can be anticipated at compile time. The plugin does + /// not have to actually offer the specialized interface in order to get + /// this performance improvement. This template is variadic, so it can + /// support arbitrarily many interfaces. + /// + /// Usage example: + /// + /// Suppose you want to instantiate a plugin that might (or might not) have + /// some combination of four interfaces which are known at compile time: + /// `MyInterface1`, `FooInterface`, `MyInterface2`, and `BarInterface`. You + /// can use SpecializedPluginPtr as shown here: + /// + /// \code + /// using MySpecialPluginPtr = SpecializedPluginPtr< + /// MyInterface1, FooInterface, MyInterface2, BarInterface>; + /// + /// MySpecialPluginPtr plugin = loader->Instantiate(pluginName); + /// \endcode + /// + /// Then, calling the function + /// + /// \code + /// plugin->QueryInterface(); + /// \endcode + /// + /// will have extremely high speed associated with it. It will provide + /// direct access to the the `FooInterface*` of `plugin`. If `plugin` does + /// not actually offer `FooInterface`, then it will return a nullptr, still + /// at extremely high speed. + /// + /// This same rule also applies to `MyInterface1`, `MyInterface2`, and + /// `BarInterface`, because those interfaces were also provided to + /// SpecializedPluginPtr<...> at compile time. + template + using SpecializedPluginPtr = + TemplatePluginPtr< SpecializedPlugin >; + + /// \brief This alias creates a specialized PluginPtr whose interfaces are + /// all const-qualified. + template + using ConstSpecializedPluginPtr = + TemplatePluginPtr< const SpecializedPlugin >; + } +} + +#endif diff --git a/core/include/gz/plugin/WeakPluginPtr.hh b/core/include/gz/plugin/WeakPluginPtr.hh new file mode 100644 index 00000000..5968d71b --- /dev/null +++ b/core/include/gz/plugin/WeakPluginPtr.hh @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GZ_PLUGIN_WEAKPLUGINPTR_HH_ +#define GZ_PLUGIN_WEAKPLUGINPTR_HH_ + +#include + +#include + +namespace ignition +{ + namespace plugin + { + /// \brief WeakPluginPtr is a non-reference-holding smart pointer for a + /// Plugin. WeakPluginPtr is analogous to std::weak_ptr where PluginPtr is + /// analogous to std::shared_ptr. + /// + /// Use Lock() to receive a reference-holding PluginPtr that points to the + /// Plugin that this WeakPluginPtr is meant to reference. + /// + /// If the Plugin is deleted while this WeakPluginPtr is referring to it, + /// then Lock() will return an empty PluginPtr, and IsExpired() will return + /// true. + class IGNITION_PLUGIN_VISIBLE WeakPluginPtr + { + /// \brief Default constructor + public: WeakPluginPtr(); + + /// \brief Copy constructor + /// \param[in] _other + /// Another WeakPluginPtr to copy + public: WeakPluginPtr(const WeakPluginPtr &_other); + + /// \brief Move constructor + /// \param[in] _other + /// Another WeakPluginPtr to move from + public: WeakPluginPtr(WeakPluginPtr &&_other); + + /// \brief Construct from a live PluginPtr + /// \param[in] _ptr + /// A live PluginPtr to refer to. As long as the Plugin instance + /// continues to be held by PluginPtr containers, you can use Lock() to + /// retrieve a reference to it. + // cppcheck-suppress noExplicitConstructor + public: WeakPluginPtr(const PluginPtr &_ptr); + + /// \brief Copy assignment operator + /// \param[in] _other + /// Another WeakPluginPtr to copy + /// \return reference to this + public: WeakPluginPtr &operator=(const WeakPluginPtr &_other); + + /// \brief Move assignment operator + /// \param[in] _other + /// Another WeakPluginPtr to move from + /// \return reference to this + public: WeakPluginPtr &operator=(WeakPluginPtr &&_other); + + /// \brief Assign from a live PluginPtr + /// \param[in] _ptr + /// A live PluginPtr to refer to. As long as the Plugin instance + /// continues to be held by PluginPtr containers, you can use Lock() to + /// retrieve a reference to it. + public: WeakPluginPtr &operator=(const PluginPtr &_ptr); + + /// \brief Retrieve the PluginPtr that this WeakPluginPtr refers to, if it + /// is still available. Otherwise, retrieve an empty PluginPtr. + /// \return The PluginPtr that this WeakPluginPtr refers to. + public: PluginPtr Lock() const; + + /// \brief Check whether the referenced Plugin has already expired. + /// \return true if this PluginPtr is expired, false otherwise. + public: bool IsExpired() const; + + /// \brief Destructor + public: ~WeakPluginPtr(); + + private: class Implementation; + IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING + /// \brief PIMPL pointer to the implementation of this class + private: std::unique_ptr pimpl; + IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING + }; + } +} + +#endif diff --git a/core/include/ignition/plugin/config.hh.in b/core/include/gz/plugin/config.hh.in similarity index 82% rename from core/include/ignition/plugin/config.hh.in rename to core/include/gz/plugin/config.hh.in index 8a33747f..85fc4a9b 100644 --- a/core/include/ignition/plugin/config.hh.in +++ b/core/include/gz/plugin/config.hh.in @@ -1,7 +1,7 @@ /* Config.hh. Generated by CMake for @PROJECT_NAME_NO_VERSION@. */ -#ifndef IGNITION_PLUGIN_CONFIG_HH_ -#define IGNITION_PLUGIN_CONFIG_HH_ +#ifndef GZ_PLUGIN_CONFIG_HH_ +#define GZ_PLUGIN_CONFIG_HH_ /* Version number */ #define IGNITION_PLUGIN_MAJOR_VERSION ${PROJECT_VERSION_MAJOR} @@ -13,4 +13,13 @@ #define IGNITION_PLUGIN_VERSION_HEADER "Ignition Plugin, version ${PROJECT_VERSION_FULL}\nCopyright (C) 2017 Open Source Robotics Foundation.\nReleased under the Apache 2.0 License.\n\n" +namespace ignition +{ +} + +namespace gz +{ + using namespace ignition; +} + #endif diff --git a/core/include/ignition/plugin/detail/Factory.hh b/core/include/gz/plugin/detail/Factory.hh similarity index 97% rename from core/include/ignition/plugin/detail/Factory.hh rename to core/include/gz/plugin/detail/Factory.hh index 584ca929..abfb9bc9 100644 --- a/core/include/ignition/plugin/detail/Factory.hh +++ b/core/include/gz/plugin/detail/Factory.hh @@ -15,15 +15,15 @@ * */ -#ifndef IGNITION_PLUGIN_DETAIL_FACTORY_HH_ -#define IGNITION_PLUGIN_DETAIL_FACTORY_HH_ +#ifndef GZ_PLUGIN_DETAIL_FACTORY_HH_ +#define GZ_PLUGIN_DETAIL_FACTORY_HH_ #include #include -#include +#include -#include +#include namespace ignition { diff --git a/core/include/ignition/plugin/detail/Plugin.hh b/core/include/gz/plugin/detail/Plugin.hh similarity index 96% rename from core/include/ignition/plugin/detail/Plugin.hh rename to core/include/gz/plugin/detail/Plugin.hh index 8562c840..cc8528ff 100644 --- a/core/include/ignition/plugin/detail/Plugin.hh +++ b/core/include/gz/plugin/detail/Plugin.hh @@ -16,12 +16,12 @@ */ -#ifndef IGNITION_PLUGIN_DETAIL_PLUGIN_HH_ -#define IGNITION_PLUGIN_DETAIL_PLUGIN_HH_ +#ifndef GZ_PLUGIN_DETAIL_PLUGIN_HH_ +#define GZ_PLUGIN_DETAIL_PLUGIN_HH_ #include #include -#include +#include namespace ignition { diff --git a/core/include/ignition/plugin/detail/PluginPtr.hh b/core/include/gz/plugin/detail/PluginPtr.hh similarity index 97% rename from core/include/ignition/plugin/detail/PluginPtr.hh rename to core/include/gz/plugin/detail/PluginPtr.hh index 242c92c9..2372928d 100644 --- a/core/include/ignition/plugin/detail/PluginPtr.hh +++ b/core/include/gz/plugin/detail/PluginPtr.hh @@ -16,13 +16,13 @@ */ -#ifndef IGNITION_PLUGIN_DETAIL_PLUGINPTR_HH_ -#define IGNITION_PLUGIN_DETAIL_PLUGINPTR_HH_ +#ifndef GZ_PLUGIN_DETAIL_PLUGINPTR_HH_ +#define GZ_PLUGIN_DETAIL_PLUGINPTR_HH_ #include #include -#include -#include +#include +#include namespace ignition { diff --git a/core/include/ignition/plugin/detail/SpecializedPlugin.hh b/core/include/gz/plugin/detail/SpecializedPlugin.hh similarity index 98% rename from core/include/ignition/plugin/detail/SpecializedPlugin.hh rename to core/include/gz/plugin/detail/SpecializedPlugin.hh index 41853dae..78427252 100644 --- a/core/include/ignition/plugin/detail/SpecializedPlugin.hh +++ b/core/include/gz/plugin/detail/SpecializedPlugin.hh @@ -16,11 +16,11 @@ */ -#ifndef IGNITION_PLUGIN_DETAIL_SPECIALIZEDPLUGIN_HH_ -#define IGNITION_PLUGIN_DETAIL_SPECIALIZEDPLUGIN_HH_ +#ifndef GZ_PLUGIN_DETAIL_SPECIALIZEDPLUGIN_HH_ +#define GZ_PLUGIN_DETAIL_SPECIALIZEDPLUGIN_HH_ #include -#include "ignition/plugin/SpecializedPlugin.hh" +#include "gz/plugin/SpecializedPlugin.hh" // This preprocessor token should only be used by the unittest that is // responsible for checking that the specialized routines are being used to diff --git a/core/include/ignition/plugin/detail/utility.hh b/core/include/gz/plugin/detail/utility.hh similarity index 92% rename from core/include/ignition/plugin/detail/utility.hh rename to core/include/gz/plugin/detail/utility.hh index 1f6d32f1..af24e17d 100644 --- a/core/include/ignition/plugin/detail/utility.hh +++ b/core/include/gz/plugin/detail/utility.hh @@ -16,8 +16,8 @@ */ -#ifndef IGNITION_PLUGIN_DETAIL_UTILITY_HH_ -#define IGNITION_PLUGIN_DETAIL_UTILITY_HH_ +#ifndef GZ_PLUGIN_DETAIL_UTILITY_HH_ +#define GZ_PLUGIN_DETAIL_UTILITY_HH_ #include diff --git a/core/include/gz/plugin/utility.hh b/core/include/gz/plugin/utility.hh new file mode 100644 index 00000000..867f9e1f --- /dev/null +++ b/core/include/gz/plugin/utility.hh @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef GZ_PLUGIN_UTILITY_HH_ +#define GZ_PLUGIN_UTILITY_HH_ + +#include + +#include +#include + +namespace ignition +{ + namespace plugin + { + ///////////////////////////////////////////////// + /// \brief Contains a static constexpr field named `value` which will be + /// true if the type `From` has a const-quality less than or equal to the + /// type `To`. + /// + /// The following expressions will return true: + /// + /// \code + /// ConstCompatible::value + /// ConstCompatible::value + /// \endcode + /// + /// The following expression will return false: + /// + /// \code + /// ConstCompatible::value + /// \endcode + /// + template + using ConstCompatible = detail::ConstCompatible; + + + ///////////////////////////////////////////////// + /// \brief Demangle the ABI typeinfo name of a symbol into a human-readable + /// version. + /// \param[in] _symbol + /// Pass in the result of typeid(T).name() + /// \return The demangled (human-readable) version of the symbol name + std::string IGNITION_PLUGIN_VISIBLE DemangleSymbol( + const std::string &_symbol); + } +} + +#endif diff --git a/core/include/ignition/plugin.hh b/core/include/ignition/plugin.hh new file mode 100644 index 00000000..f495c7e2 --- /dev/null +++ b/core/include/ignition/plugin.hh @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include diff --git a/core/include/ignition/plugin/EnablePluginFromThis.hh b/core/include/ignition/plugin/EnablePluginFromThis.hh index 01ad28a9..68d8775f 100644 --- a/core/include/ignition/plugin/EnablePluginFromThis.hh +++ b/core/include/ignition/plugin/EnablePluginFromThis.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Open Source Robotics Foundation + * Copyright (C) 2022 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,72 +15,5 @@ * */ -#ifndef IGNITION_PLUGIN_ENABLEPLUGINFROMTHIS_HH_ -#define IGNITION_PLUGIN_ENABLEPLUGINFROMTHIS_HH_ - -#include - -#include - -namespace ignition -{ - namespace plugin - { - // Forward declaration - class Loader; - - /// \brief EnablePluginFromThis is an optional base class which can be - /// inherited by Plugin classes. When a Plugin class inherits it and that - /// Plugin class is instantiated using the Loader class, its instance will - /// be able to access the PluginPtr that manages its lifecycle. This - /// interface will also be available by calling - /// `instance->QueryInterface()` - /// - /// \remark This class is analogous to std::enable_shared_from_this - class IGNITION_PLUGIN_VISIBLE EnablePluginFromThis - { - /// \brief Default constructor - public: EnablePluginFromThis(); - - /// \brief Get a copy of the PluginPtr that manages this object. - /// \return a copy of the PluginPtr that manages this object. - public: PluginPtr PluginFromThis(); - - /// \brief Get a const-qualified copy of the PluginPtr that manages this - /// object. - /// \return a const-qualified copy of the PluginPtr that manages this - /// object. - public: ConstPluginPtr PluginFromThis() const; - - /// \brief Destructor - public: virtual ~EnablePluginFromThis(); - - /// \brief This is an abstract shared_ptr to the Plugin instance. This - /// shared_ptr will maintain a reference count on the shared library that - /// provides the plugin so that the shared library does not get unloaded - /// while this shared_ptr is still alive. - /// - /// This function is meant for advanced use-cases, such as creating - /// Factory plugins, so we keep it protected. Only use this if you know - /// what you are doing. - /// - /// \return shared_ptr to the Plugin instance. - protected: std::shared_ptr PluginInstancePtrFromThis() const; - - // Declare friendship so that the internal WeakPluginPtr can be set by - // the Loader class. - friend class Loader; - - /// \brief This function is called by the Loader class whenever a plugin - /// containing this interface gets instantiated. - private: void PrivateSetPluginFromThis(const PluginPtr &_ptr); - - private: class Implementation; - IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING - private: std::unique_ptr pimpl; - IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING - }; - } -} - -#endif +#include +#include diff --git a/core/include/ignition/plugin/Export.hh b/core/include/ignition/plugin/Export.hh new file mode 100644 index 00000000..38bf8c26 --- /dev/null +++ b/core/include/ignition/plugin/Export.hh @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include diff --git a/core/include/ignition/plugin/Factory.hh b/core/include/ignition/plugin/Factory.hh index 3cf47113..8b691f9d 100644 --- a/core/include/ignition/plugin/Factory.hh +++ b/core/include/ignition/plugin/Factory.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Open Source Robotics Foundation + * Copyright (C) 2022 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,136 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * -*/ + */ -#ifndef IGNITION_PLUGIN_FACTORY_HH_ -#define IGNITION_PLUGIN_FACTORY_HH_ - -#include -#include -#include -#include - -#include - -namespace ignition -{ - namespace plugin - { - /// \brief This class provides a unary operator for safely deleting pointers - /// to plugin factory products with the type `Interface`. If it gets passed - /// an `Interface` pointer that is not pointing to a factory plugin product, - /// then this just performs a normal delete. - template class ProductDeleter; - - /// \brief ProductPtr is a derivative of std::unique_ptr that can safely - /// manage the products that come out of a plugin factory. It is strongly - /// recommended that factory products use a ProductPtr to manage the - /// lifecycle of a factory product. - /// - /// If you MUST release a factory product pointer, then it should at least - /// be passed to a ProductDeleter to be deleted at the end of its lifecycle. - /// If it is not possible to delete the product with a ProductDeleter, then - /// you will need to periodically call CleanupLostProducts() or else you - /// will experience memory leaks, and your factory plugin libraries will - /// never get unloaded. - template - using ProductPtr = - std::unique_ptr>; - - /// \brief The Factory class defines a plugin factory that can be used by - /// the Loader class to produce products that implement an interface. - /// - /// To define the inputs and outputs of a factory, set the template - /// arguments, for example: - /// - /// \code - /// using MyFactory = Factory; - /// \endcode - /// - /// defines a factory that can produce a `std::unique_ptr` - /// given arguments of `InputType1` and `InputType2`. - /// - /// To register a factory, use the `IGNITION_ADD_FACTORY` macro, e.g.: - /// - /// \code - /// IGNITION_ADD_FACTORY(ImplementedClass, MyFactory) - /// \endcode - /// - /// where `ImplementedClass` is the name of the class that your plugin - /// library has used to implement `InterfaceClass`. - template - class Factory : public EnablePluginFromThis - { - public: using ProductPtrType = ProductPtr; - - /// \brief This function is called by Loader to construct the class that - /// implements the InterfacePtr interface. - /// \param[in] _args - /// The arguments as defined by the template parameters. - /// \return an RAII-managed reference to the interface type as defined by - /// the template parameters. - public: ProductPtrType Construct(Args&&... _args); - - /// \internal \brief This function gets implemented by Producing - /// to manufacture the product instance. - /// \param[in] _args - /// The arguments as defined by the template parameters - /// \return a raw pointer to the product - private: virtual Interface *ImplConstruct(Args&&... _args) = 0; - - /// \private This nested class is used to implement the plugin factory. - /// It is not intended for external use. - public: template - class Producing; - }; - - /// \brief Call this function to cleanup the Factories of any Products which - /// were not managed by a ProductPtr or deleted by a ProductDeleter (in - /// other words, the Product was released from its ProductPtr and then its - /// lifecycle was managed by a framework that does not know it has special - /// deletion requirements). - /// - /// If you never call the .release() function on a ProductPtr, then you will - /// never need to call this function. - /// - /// \warning Note that this function should be called ONLY while there are - /// no Products that are actively destructing, or else there is a miniscule - /// probability of causing a segmentation fault. This is never an issue in a - /// single-threaded application. - /// - /// \warning If you have a multi-threaded application where you have - /// absolutely no control over the lifecycle of the products, and you cannot - /// reliably predict a safe window in which you know that no products are - /// being actively deleted, then you can specify a short safety wait to the - /// cleanup call. If any products were being deleted while this function is - /// called, this wait can give them time to fully exit their destructors - /// before we unload their libraries. - /// - /// \note For some applications, it might not be important if there are tiny - /// memory leaks or if plugin libraries remain loaded until the application - /// exits. For those applications, it is okay to not bother calling this - /// function at all. - /// - /// \param[in] _safetyWait - /// For multi-threaded applications, this short waiting window gives time - /// for products that are currently being deleted to exit their - /// destructors before we unload their libraries. If you can reliably - /// predict a window of time in which no products are actively being - /// destructed (or if you have a single-threaded application), then it is - /// okay to set this waiting time to 0. Note that any threads which are - /// about to destruct a product will be blocked until this wait is over. - void IGNITION_PLUGIN_VISIBLE CleanupLostProducts( - const std::chrono::nanoseconds &_safetyWait = - std::chrono::nanoseconds(5)); - - /// \brief Get the number of lost products that have currently accumulated - /// since the last time CleanupLostProducts() was called (or since the - /// program began, if CleanupLostProducts() has not been called yet). - std::size_t IGNITION_PLUGIN_VISIBLE LostProductCount(); - } -} - -#include - -#endif +#include +#include diff --git a/core/include/ignition/plugin/Info.hh b/core/include/ignition/plugin/Info.hh index 4ad8f645..6ffd5468 100644 --- a/core/include/ignition/plugin/Info.hh +++ b/core/include/ignition/plugin/Info.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Open Source Robotics Foundation + * Copyright (C) 2022 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,91 +15,5 @@ * */ - -#ifndef IGNITION_PLUGIN_INFO_HH_ -#define IGNITION_PLUGIN_INFO_HH_ - -#include -#include -#include -#include -#include - -#include - -#include - -namespace ignition -{ - namespace plugin - { - /// \brief sentinel value to check if a plugin was built with the same - /// version of the Info struct - // - /// This must be incremented when the Info struct changes - const int INFO_API_VERSION = 1; - - // We use an inline namespace to assist in forward-compatibility. Eventually - // we may want to support a version-2 of the Info API, in which case - // we will remove the "inline" declaration here, and create a new inline - // namespace called "v2". This original Info object will continue to - // be accessible for backwards compatibility, and even its symbol name in - // the ABI should remain the same. - inline namespace v1 - { - /// \brief Holds info required to construct a plugin - struct IGNITION_PLUGIN_VISIBLE Info - { - /// \brief Clear out all information contained in this Info object - void Clear(); - - /// \brief The name of the plugin - IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING - std::string name; - IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING - - /// \brief Alternative names that may be used to instantiate the plugin - IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING - std::set aliases; - IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING - - /// \brief The keys are the names of the types of interfaces that this - /// plugin provides. The values are functions that convert a void - /// pointer (which actually points to the plugin instance) to another - /// void pointer (which actually points to the location of the interface - /// within the plugin instance). - IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING - using InterfaceCastingMap = - std::unordered_map< std::string, std::function >; - InterfaceCastingMap interfaces; - IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING - - /// \brief This is a set containing the demangled versions of the names - /// of the interfaces provided by this plugin. This gets filled in by - /// the Loader after receiving the Info. It is only used by - /// the user-facing API. Internally, when looking up Interfaces, the - /// mangled `interfaces` map will still be used. - IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING - std::set demangledInterfaces; - IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING - - /// \brief A method that instantiates a new instance of a plugin - IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING - std::function factory; - IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING - - /// \brief A method that safely deletes an instance of the plugin - IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING - std::function deleter; - IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING - }; - } - - /// This typedef is used simultaneously by detail/Register.hh and Loader.cc, - /// so we store it in a location that is visible to both of them. - using InfoMap = std::unordered_map; - using ConstInfoPtr = std::shared_ptr; - } -} - -#endif +#include +#include diff --git a/core/include/ignition/plugin/Plugin.hh b/core/include/ignition/plugin/Plugin.hh index 2e3f3f78..6047f9ce 100644 --- a/core/include/ignition/plugin/Plugin.hh +++ b/core/include/ignition/plugin/Plugin.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Open Source Robotics Foundation + * Copyright (C) 2022 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,206 +15,5 @@ * */ - -#ifndef IGNITION_PLUGIN_PLUGIN_HH_ -#define IGNITION_PLUGIN_PLUGIN_HH_ - -#include -#include -#include - -#include - -#include -#include - -namespace ignition -{ - namespace plugin - { - // Forward declaration - namespace detail { - template class ComposePlugin; - template class SelectSpecializers; - } - class EnablePluginFromThis; - class WeakPluginPtr; - - class IGNITION_PLUGIN_VISIBLE Plugin - { - // -------------------- Public API --------------------- - - /// \brief Get an interface of the specified type, if it is provided by - /// this plugin. - /// - /// Note that the interface pointer you receive is owned by the Plugin - /// object. You MUST NOT ever try to deallocate it yourself. Moreover, the - /// pointer will be invalidated once all Plugin objects that refer to the - /// same Plugin instance are destructed. Use the QueryInterfaceSharedPtr - /// function in order to get a reference-counting pointer to an interface - /// of this Plugin object. The pointer will remain valid as long as the - /// std::shared_ptr provided by QueryInterfaceSharedPtr is alive. - /// - /// \return A raw pointer to the specified interface. If the requested - /// _interfaceName is not provided by this Plugin, this returns a nullptr. - /// This pointer is invalidated when the reference count of the plugin - /// instance drops to zero. - public: template - Interface *QueryInterface(); - - /// \brief const-qualified version of QueryInterface() - public: template - const Interface *QueryInterface() const; - - /// \brief This function has been deprecated in favor of the version of - /// QueryInterface which does not take a std::string argument. - public: template - IGN_DEPRECATED(0.0) - Interface *QueryInterface(const std::string &/*_interfaceName*/); - - /// \brief const-qualified version of - /// QueryInterface(std::string) - public: template - IGN_DEPRECATED(0.0) - const Interface *QueryInterface( - const std::string &/*_interfaceName*/) const; - - /// \brief Get the requested interface as a std::shared_ptr. The template - /// argument Interface must exactly match the underlying type associated - /// with _interfaceName, or else the behavior of this function is - /// undefined. - /// - /// This std::shared_ptr and the interface+plugin that it refers to will - /// remain valid, even if all Plugin objects which refer to the plugin - /// instance are destructed. - /// - /// You MUST NOT attempt to pass a QueryInterface pointer into a - /// std::shared_ptr yourself; that will result in double-delete memory - /// errors. You must always call QueryInterfaceSharedPtr for a reference- - /// counting pointer to an interface. - /// - /// \return A reference-counting pointer to the specified interface. This - /// will keep the interface valid and the plugin instance alive, even if - /// all Plugin objects that refer to this plugin instance are destructed. - public: template - std::shared_ptr QueryInterfaceSharedPtr(); - - /// \brief Same as QueryInterfaceSharedPtr(), but it returns a - /// std::shared_ptr to a const-qualified Interface. - public: template - std::shared_ptr QueryInterfaceSharedPtr() const; - - /// \brief This version of QueryInterfaceSharedPtr has been deprecated in - /// favor of the version that does not take a std::string argument. - public: template - IGN_DEPRECATED(0.0) - std::shared_ptr QueryInterfaceSharedPtr( - const std::string &/*_interfaceName*/); - - /// \brief Same as QueryInterfaceSharedPtr(std::string), but - /// it returns a std::shared_ptr to a const-qualified Interface. - public: template - IGN_DEPRECATED(0.0) - std::shared_ptr QueryInterfaceSharedPtr( - const std::string &/*_interfaceName*/) const; - - /// \brief Checks if this Plugin has the specified type of interface. - /// \return Returns true if this Plugin has the specified type of - /// interface, and false otherwise. - public: template - bool HasInterface() const; - - /// \brief Checks if this Plugin has the specified type of interface. - /// - /// By default, we expect you to pass in a demangled version of the - /// interface name. If you want to use a mangled version of the name, - /// set the `demangled` argument to false. - /// - /// \param[in] _interfaceName The name of the desired interface, as a - /// std::string. Note that this expects the name to be mangled. - /// \param[in] _demangled If _interfaceName is demangled, set this to - /// true. If you are instead using the raw mangled name that gets provided - /// by typeid(T).name(), then set _demangled to false. - /// \return Returns true if this Plugin has the specified type of - /// interface, and false otherwise. - public: bool HasInterface(const std::string &_interfaceName, - const bool _demangled = true) const; - - /// \brief Gets the name of this Plugin. - /// \return A pointer to the name of this Plugin, or nullptr if this - /// Plugin is not instantiated. - public: const std::string *Name() const; - - // -------------------- Private API ----------------------- - - template friend class TemplatePluginPtr; - template friend class SpecializedPlugin; - template friend class detail::ComposePlugin; - template friend class detail::SelectSpecializers; - friend class EnablePluginFromThis; - friend class WeakPluginPtr; - - /// \brief Default constructor. This is kept protected to discourage users - /// from instantiating them directly. They should instead only be - /// retrieved as a PluginPtr from the plugin Loader. - protected: Plugin(); - - /// \brief Type-agnostic retriever for interfaces - private: void *PrivateQueryInterface( - const std::string &_interfaceName) const; - - /// \brief Copy the plugin instance from another Plugin object - private: void PrivateCopyPluginInstance(const Plugin &_other) const; - - /// \brief Copy an existing plugin instance into this plugin - /// \param[in] _info - /// Pointer to the Info for this plugin - /// \param[in] _instancePtr - /// Pointer to an already-existing abstract plugin instance pointer - private: void PrivateCopyPluginInstance( - const ConstInfoPtr &_info, - const std::shared_ptr &_instancePtr) const; - - /// \brief Create a new plugin instance based on the info provided - /// \param[in] _info - /// Pointer to the Info for this plugin - /// \param[in] _dlHandlePtr - /// Reference counter for the dl handle of this Plugin - private: void PrivateCreatePluginInstance( - const ConstInfoPtr &_info, - const std::shared_ptr &_dlHandlePtr) const; - - /// \brief Get a reference to the abstract instance being managed by this - /// wrapper - private: const std::shared_ptr &PrivateGetInstancePtr() const; - - /// \brief Get a reference to the Info being used by this wrapper - private: const ConstInfoPtr &PrivateGetInfoPtr() const; - - /// \brief The InterfaceMap type needs to get used in several places, like - /// Plugin::Implementation and SpecializedPlugin. We make the typedef - /// public so that those other classes can use it without needing to be - /// friends of Plugin. End-users should not have any need for this - /// typedef. - public: using InterfaceMap = std::map; - - /// \brief Get or create an iterator to the std::map that holds pointers - /// to the various interfaces provided by this plugin instance. - private: InterfaceMap::iterator PrivateGetOrCreateIterator( - const std::string &_interfaceName); - - class Implementation; - IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING - /// \brief PIMPL pointer to the implementation of this class. - private: const std::unique_ptr dataPtr; - IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING - - /// \brief Virtual destructor - public: virtual ~Plugin(); - }; - } -} - -#include "ignition/plugin/detail/Plugin.hh" - -#endif +#include +#include diff --git a/core/include/ignition/plugin/PluginPtr.hh b/core/include/ignition/plugin/PluginPtr.hh index b67ea7dc..ba0bd46d 100644 --- a/core/include/ignition/plugin/PluginPtr.hh +++ b/core/include/ignition/plugin/PluginPtr.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Open Source Robotics Foundation + * Copyright (C) 2022 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,209 +15,5 @@ * */ - -#ifndef IGNITION_PLUGIN_PLUGINPTR_HH_ -#define IGNITION_PLUGIN_PLUGINPTR_HH_ - -#include -#include -#include - -#include - -namespace ignition -{ - namespace plugin - { - // Forward declarations - namespace detail { template class ComposePlugin; } - - /// \brief This class manages the lifecycle of a plugin instance. It can - /// receive a plugin instance from the ignition::plugin::Loader class - /// or by copy-construction or assignment from another PluginPtr instance. - /// - /// This class behaves similarly to a std::shared_ptr where multiple - /// PluginPtr objects can share a single plugin instance, and the plugin - /// instance will not be deleted until all PluginPtr objects that refer to - /// it are either destroyed, cleared, or begin referring to a different - /// plugin instance. - /// - /// A PluginPtr object can be "cast" to a SpecializedPluginPtr object by - /// simply using the copy/move constructor or assignment operator of a - /// SpecializedPluginPtr object. Note that this "cast" does have a small - /// amount of overhead associated with it, but it may result in huge savings - /// after initialization is finished if you frequently access the interfaces - /// that the SpecializedPluginPtr is specialized for. - template - class TemplatePluginPtr final - { - /// \brief Destructor. Deletes this PluginPtr's reference to the plugin - /// instance. Once all PluginPtrs that refer to a plugin instance are - /// deleted, the plugin will also be deleted. - public: ~TemplatePluginPtr() = default; - - /// \brief Default constructor. Creates a PluginPtr object that does not - /// point to any plugin instance. IsEmpty() will return true until a - /// plugin instance is provided. - public: TemplatePluginPtr(); - - /// \brief Copy constructor. This PluginPtr will now point at the same - /// plugin instance as _other, and they will share ownership. - /// \param[in] _other Pointer to plugin being copied. - public: TemplatePluginPtr(const TemplatePluginPtr &_other); - - /// \brief Move constructor. This PluginPtr will take ownership of the - /// plugin instance held by _other. If this PluginPtr was holding an - /// instance to another plugin, that instance will be deleted if no other - /// PluginPtr is referencing which is being moved. - /// \param[in] _other Plugin being moved. - public: TemplatePluginPtr(TemplatePluginPtr &&_other); - - /// \brief Casting constructor. This PluginPtr will now point at the same - /// plugin instance as _other, and they will share ownership. This - /// essentially allows casting between PluginPtrs that are holding - /// different types of plugin wrappers (for example, you can cast a - /// generic PluginPtr to any SpecializedPluginPtr type, or you can cast - /// between different types of specializations). - /// \param[in] _other Pointer to plugin being casted, which is of a - /// different type. - public: template - TemplatePluginPtr( - const TemplatePluginPtr &_other); - - /// \brief Copy assignment operator. This PluginPtr will now point at the - /// same plugin instance as _other, and they will share ownership. If this - /// PluginPtr was holding an instance to another plugin, that instance - /// will be deleted if no other PluginPtr is referencing it. - /// \param[in] _other Pointer to plugin being copied. - public: TemplatePluginPtr &operator =(const TemplatePluginPtr &_other); - - /// \brief Casting operator. This PluginPtr will now point at the same - /// plugin instance as _other, and they will share ownership. This - /// essentially allows casting between PluginPtrs that are holding - /// different types of plugin wrappers. - /// \param[in] _other Pointer to plugin being casted, which is of a - /// different type. - /// \return A reference to this object. - public: template - TemplatePluginPtr &operator =( - const TemplatePluginPtr &_other); - - /// \brief Move assignment operator. This PluginPtr will take ownership - /// of the plugin instance held by _other. If this PluginPtr was holding - /// an instance to another plugin, that instance will be deleted if no - /// other PluginPtr is referencing it. - /// \param[in] _other Plugin being moved. - /// \return A reference to this object. - public: TemplatePluginPtr &operator=(TemplatePluginPtr &&_other); - - /// \brief nullptr assignment operator. Same as calling Clear() - /// \param[in] _null nullptr object. - /// \return A reference to this object. - public: TemplatePluginPtr &operator=(std::nullptr_t _null); - - /// \brief Access the wrapper for the plugin instance and call one of its - /// member functions. - /// \return The ability to call a member function on the underlying Plugin - /// object. - public: PluginType *operator->() const; - - /// \brief Get a reference to the wrapper for the plugin instance that is - /// being managed by this PluginPtr. - /// \return A reference to the underlying Plugin object. - public: PluginType &operator*() const; - - /// \brief Comparison operator. - /// \param[in] _other Plugin to compare to. - /// \returns True if this Plugin is holding the same plugin - /// instance as _other, otherwise returns false. - public: bool operator ==(const TemplatePluginPtr &_other) const; - - /// \brief Comparison operator. - /// \param[in] _other Plugin to compare to. - /// \returns True if the pointer value of the plugin instance held - /// by this PluginPtr is less than the pointer value of the instance held - /// by _other. - public: bool operator <(const TemplatePluginPtr &_other) const; - - /// \brief Comparison operator. - /// \param[in] _other Plugin to compare to. - /// \returns True if the pointer value of the plugin instance held - /// by this PluginPtr is greater than the pointer value of the instance - /// held by _other. - public: bool operator >(const TemplatePluginPtr &_other) const; - - /// \brief Comparison operator. - /// \param[in] _other Plugin to compare to. - /// \returns True if the pointer instance held by this PluginPtr is - /// different from the pointer instance held by _other. - public: bool operator !=(const TemplatePluginPtr &_other) const; - - /// \brief Comparison operator. - /// \param[in] _other Plugin to compare to. - /// \returns True if the value of the pointer instance held by this - /// PluginPtr is less than or equal to the value of the pointer instance - /// held by _other. - public: bool operator <=(const TemplatePluginPtr &_other) const; - - /// \brief Comparison operator. - /// \param[in] _other Plugin to compare to. - /// \returns True if the value of the pointer instance held by this - /// PluginPtr is greater than or equal to the value of the pointer - /// instance held by _other. - public: bool operator >=(const TemplatePluginPtr &_other) const; - - /// \brief Produces a hash for the plugin instance that this PluginPtr is - /// holding. This function allows PluginPtr instances to be used as values - /// in a std::unordered_set or keys in a - /// std::unordered_map. Using this function directly should - /// not normally be necessary. - /// \return A hash of the underlying pointer object. - public: std::size_t Hash() const; - - /// \brief Check whether this is pointing at a valid plugin. - /// \returns False if this PluginPtr is pointing at a valid plugin - /// instance. If it is instead pointing at a nullptr, this returns true. - public: bool IsEmpty() const; - - /// \brief Implicitly convert this PluginPtr to a boolean. - /// \return The opposite value of IsEmpty(). - public: operator bool() const; - - /// \brief Clears the Plugin instance from this PluginPtr. IsEmpty() will - /// return true after this is used, and none of the interfaces will be - /// available any longer. - public: void Clear(); - - /// \brief Pointer to the plugin wrapper that this PluginPtr is managing. - private: std::unique_ptr dataPtr; - - // Declare friendship - friend class Loader; - template friend class TemplatePluginPtr; - - /// \brief Private constructor. Creates a plugin instance based on the - /// Info provided. This should only be called by Loader to ensure that - /// the Info is well-formed, so we keep it private. - /// \param[in] _info An Info instance that was generated by - /// Loader. Alternatively, this can take a nullptr to create an - /// empty PluginPtr. - /// \param[in] _dlHandlePtr A reference count for the DL handle. - private: explicit TemplatePluginPtr( - const ConstInfoPtr &_info, - const std::shared_ptr &_dlHandlePtr); - }; - - /// \brief Typical usage for TemplatePluginPtr is to just hold a generic - /// Plugin type. - using PluginPtr = TemplatePluginPtr; - - /// \brief This produces a PluginPtr whose Plugin wrapper only grants access - /// to const-qualified interfaces of the plugin instance. - using ConstPluginPtr = TemplatePluginPtr; - } -} - -#include "ignition/plugin/detail/PluginPtr.hh" - -#endif +#include +#include diff --git a/core/include/ignition/plugin/SpecializedPlugin.hh b/core/include/ignition/plugin/SpecializedPlugin.hh index 5dcb3063..134cff1d 100644 --- a/core/include/ignition/plugin/SpecializedPlugin.hh +++ b/core/include/ignition/plugin/SpecializedPlugin.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Open Source Robotics Foundation + * Copyright (C) 2022 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,151 +15,5 @@ * */ - -#ifndef IGNITION_PLUGIN_SPECIALIZEDPLUGIN_HH_ -#define IGNITION_PLUGIN_SPECIALIZEDPLUGIN_HH_ - -#include -#include "ignition/plugin/Plugin.hh" - -namespace ignition -{ - namespace plugin - { - // Forward declarations - namespace detail { - template class ComposePlugin; - template class SelectSpecializers; - } - - // Forward declaration of the variadic template SpecializedPlugin class. - template - class SpecializedPlugin; - - /// \brief This class allows Plugin instances to have high-speed access to - /// interfaces that can be anticipated at compile time. The plugin does - /// not have to actually offer the specialized interface in order to get - /// this performance improvement. This template is variadic, so it can - /// support arbitrarily many interfaces. - /// - /// Usage example: - /// - /// \code - /// using MySpecialPluginPtr = SpecializedPluginPtr< - /// MyInterface1, FooInterface, MyInterface2, BarInterface>; - /// - /// MySpecialPluginPtr plugin = loader->Instantiate(pluginName); - /// \endcode - /// - /// Then, calling the function - /// - /// \code - /// plugin->QueryInterface(); - /// \endcode - /// - /// will have extremely high-speed associated with it. It will provide - /// direct access to the the `FooInterface*` of `plugin`. If `plugin` does - /// not actually offer `FooInterface`, then it will return a nullptr, still - /// at extremely high speed. - template - class SpecializedPlugin : public virtual Plugin - { - // -------------------- Public API --------------------- - - // Inherit function overloads - public: using Plugin::QueryInterface; - public: using Plugin::QueryInterfaceSharedPtr; - public: using Plugin::HasInterface; - - // Documentation inherited - public: template - Interface *QueryInterface(); - - // Documentation inherited - public: template - const Interface *QueryInterface() const; - - // Documentation inherited - public: template - std::shared_ptr QueryInterfaceSharedPtr(); - - // Documentation inherited - public: template - std::shared_ptr QueryInterfaceSharedPtr() const; - - // Documentation inherited - public: template - bool HasInterface() const; - - - // -------------------- Private API --------------------- - - // Declare friendship - template friend class SpecializedPlugin; - template friend class detail::ComposePlugin; - template friend class detail::SelectSpecializers; - template friend class TemplatePluginPtr; - - /// \brief type is an empty placeholder class which is used by the private - /// member functions to provide two overloads: a high-performance one for - /// the specialized interface, and a normal-performance one for all other - /// Interface types. - private: template struct type { }; - - /// \brief Delegate the function to the standard Plugin method - /// \param[in] _type Empty object meant to guide the compiler to pick the - /// desired implementation. - /// \return Pointer to the intergace - private: template - Interface *PrivateQueryInterface(type); - - /// \brief Use a high-speed accessor to provide this specialized interface - /// \param[in] _type Empty object meant to guide the compiler to pick the - /// desired implementation. - /// \return Pointer to the specialized intergace - private: SpecInterface *PrivateQueryInterface(type); - - /// \brief Delegate the function to the standard Plugin method - /// \param[in] _type Empty object meant to guide the compiler to pick the - /// desired implementation. - /// \return Pointer to the specialized intergace - private: template - const Interface *PrivateQueryInterface(type) const; - - /// \brief Use a high-speed accessor to provide this specialized interface - /// \param[in] _type Empty object meant to guide the compiler to pick the - /// desired implementation. - /// \return Pointer to the specialized intergace - private: const SpecInterface *PrivateQueryInterface( - type) const; - - /// \brief Delegate the function to the standard PluginPtr method - /// \param[in] _type Empty object meant to guide the compiler to pick the - /// desired implementation. - /// \return True if the interface is present. - private: template - bool PrivateHasInterface(type) const; - - /// \brief Use a high-speed accessor to check this specialized interface - /// \param[in] _type Empty object meant to guide the compiler to pick the - /// desired implementation. - /// \return True if the interface is present. - private: bool PrivateHasInterface(type) const; - - // Dev note (MXG): The privateSpecializedInterfaceIterator object must be - // available to the user during their compile time, so it cannot be hidden - // using PIMPL. The iterator is const because it must always point to the - // same entry throughout its entire lifecycle. - /// \brief Iterator that points to the entry of the specialized interface - private: - const Plugin::InterfaceMap::iterator privateSpecializedInterfaceIterator; - - /// \brief Default constructor - protected: SpecializedPlugin(); - }; - } -} - -#include "ignition/plugin/detail/SpecializedPlugin.hh" - -#endif +#include +#include diff --git a/core/include/ignition/plugin/SpecializedPluginPtr.hh b/core/include/ignition/plugin/SpecializedPluginPtr.hh index 30cc436a..5d89d3b4 100644 --- a/core/include/ignition/plugin/SpecializedPluginPtr.hh +++ b/core/include/ignition/plugin/SpecializedPluginPtr.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Open Source Robotics Foundation + * Copyright (C) 2022 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,61 +15,5 @@ * */ - -#ifndef IGNITION_PLUGIN_SPECIALIZEDPLUGINPTR_HH_ -#define IGNITION_PLUGIN_SPECIALIZEDPLUGINPTR_HH_ - -#include "ignition/plugin/PluginPtr.hh" -#include "ignition/plugin/SpecializedPlugin.hh" - -namespace ignition -{ - namespace plugin - { - /// \brief This alias allows PluginPtr instances to have high-speed access - /// to interfaces that can be anticipated at compile time. The plugin does - /// not have to actually offer the specialized interface in order to get - /// this performance improvement. This template is variadic, so it can - /// support arbitrarily many interfaces. - /// - /// Usage example: - /// - /// Suppose you want to instantiate a plugin that might (or might not) have - /// some combination of four interfaces which are known at compile time: - /// `MyInterface1`, `FooInterface`, `MyInterface2`, and `BarInterface`. You - /// can use SpecializedPluginPtr as shown here: - /// - /// \code - /// using MySpecialPluginPtr = SpecializedPluginPtr< - /// MyInterface1, FooInterface, MyInterface2, BarInterface>; - /// - /// MySpecialPluginPtr plugin = loader->Instantiate(pluginName); - /// \endcode - /// - /// Then, calling the function - /// - /// \code - /// plugin->QueryInterface(); - /// \endcode - /// - /// will have extremely high speed associated with it. It will provide - /// direct access to the the `FooInterface*` of `plugin`. If `plugin` does - /// not actually offer `FooInterface`, then it will return a nullptr, still - /// at extremely high speed. - /// - /// This same rule also applies to `MyInterface1`, `MyInterface2`, and - /// `BarInterface`, because those interfaces were also provided to - /// SpecializedPluginPtr<...> at compile time. - template - using SpecializedPluginPtr = - TemplatePluginPtr< SpecializedPlugin >; - - /// \brief This alias creates a specialized PluginPtr whose interfaces are - /// all const-qualified. - template - using ConstSpecializedPluginPtr = - TemplatePluginPtr< const SpecializedPlugin >; - } -} - -#endif +#include +#include diff --git a/core/include/ignition/plugin/WeakPluginPtr.hh b/core/include/ignition/plugin/WeakPluginPtr.hh index a9e6f8ad..3e256ad3 100644 --- a/core/include/ignition/plugin/WeakPluginPtr.hh +++ b/core/include/ignition/plugin/WeakPluginPtr.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Open Source Robotics Foundation + * Copyright (C) 2022 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,88 +15,5 @@ * */ -#ifndef IGNITION_PLUGIN_WEAKPLUGINPTR_HH_ -#define IGNITION_PLUGIN_WEAKPLUGINPTR_HH_ - -#include - -#include - -namespace ignition -{ - namespace plugin - { - /// \brief WeakPluginPtr is a non-reference-holding smart pointer for a - /// Plugin. WeakPluginPtr is analogous to std::weak_ptr where PluginPtr is - /// analogous to std::shared_ptr. - /// - /// Use Lock() to receive a reference-holding PluginPtr that points to the - /// Plugin that this WeakPluginPtr is meant to reference. - /// - /// If the Plugin is deleted while this WeakPluginPtr is referring to it, - /// then Lock() will return an empty PluginPtr, and IsExpired() will return - /// true. - class IGNITION_PLUGIN_VISIBLE WeakPluginPtr - { - /// \brief Default constructor - public: WeakPluginPtr(); - - /// \brief Copy constructor - /// \param[in] _other - /// Another WeakPluginPtr to copy - public: WeakPluginPtr(const WeakPluginPtr &_other); - - /// \brief Move constructor - /// \param[in] _other - /// Another WeakPluginPtr to move from - public: WeakPluginPtr(WeakPluginPtr &&_other); - - /// \brief Construct from a live PluginPtr - /// \param[in] _ptr - /// A live PluginPtr to refer to. As long as the Plugin instance - /// continues to be held by PluginPtr containers, you can use Lock() to - /// retrieve a reference to it. - // cppcheck-suppress noExplicitConstructor - public: WeakPluginPtr(const PluginPtr &_ptr); - - /// \brief Copy assignment operator - /// \param[in] _other - /// Another WeakPluginPtr to copy - /// \return reference to this - public: WeakPluginPtr &operator=(const WeakPluginPtr &_other); - - /// \brief Move assignment operator - /// \param[in] _other - /// Another WeakPluginPtr to move from - /// \return reference to this - public: WeakPluginPtr &operator=(WeakPluginPtr &&_other); - - /// \brief Assign from a live PluginPtr - /// \param[in] _ptr - /// A live PluginPtr to refer to. As long as the Plugin instance - /// continues to be held by PluginPtr containers, you can use Lock() to - /// retrieve a reference to it. - public: WeakPluginPtr &operator=(const PluginPtr &_ptr); - - /// \brief Retrieve the PluginPtr that this WeakPluginPtr refers to, if it - /// is still available. Otherwise, retrieve an empty PluginPtr. - /// \return The PluginPtr that this WeakPluginPtr refers to. - public: PluginPtr Lock() const; - - /// \brief Check whether the referenced Plugin has already expired. - /// \return true if this PluginPtr is expired, false otherwise. - public: bool IsExpired() const; - - /// \brief Destructor - public: ~WeakPluginPtr(); - - private: class Implementation; - IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING - /// \brief PIMPL pointer to the implementation of this class - private: std::unique_ptr pimpl; - IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING - }; - } -} - -#endif +#include +#include diff --git a/core/include/ignition/plugin/config.hh b/core/include/ignition/plugin/config.hh new file mode 100644 index 00000000..232da299 --- /dev/null +++ b/core/include/ignition/plugin/config.hh @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef IGNITION_PLUGIN__CONFIG_HH_ +#define IGNITION_PLUGIN__CONFIG_HH_ + +#include + +/* Version number */ +// #define IGNITION_PLUGIN_MAJOR_VERSION GZ_PLUGIN_MAJOR_VERSION +// #define IGNITION_PLUGIN_MINOR_VERSION GZ_PLUGIN_MINOR_VERSION +// #define IGNITION_PLUGIN_PATCH_VERSION GZ_PLUGIN_PATCH_VERSION + +// #define IGNITION_PLUGIN_VERSION GZ_PLUGIN_VERSION +// #define IGNITION_PLUGIN_VERSION_FULL GZ_PLUGIN_VERSION_FULL + +// #define IGNITION_PLUGIN_VERSION_HEADER GZ_PLUGIN_VERSION_HEADER + +#endif diff --git a/core/include/ignition/plugin/utility.hh b/core/include/ignition/plugin/utility.hh index 12e60220..d49fd73c 100644 --- a/core/include/ignition/plugin/utility.hh +++ b/core/include/ignition/plugin/utility.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Open Source Robotics Foundation + * Copyright (C) 2022 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,50 +15,5 @@ * */ - -#ifndef IGNITION_PLUGIN_UTILITY_HH_ -#define IGNITION_PLUGIN_UTILITY_HH_ - -#include - -#include -#include - -namespace ignition -{ - namespace plugin - { - ///////////////////////////////////////////////// - /// \brief Contains a static constexpr field named `value` which will be - /// true if the type `From` has a const-quality less than or equal to the - /// type `To`. - /// - /// The following expressions will return true: - /// - /// \code - /// ConstCompatible::value - /// ConstCompatible::value - /// \endcode - /// - /// The following expression will return false: - /// - /// \code - /// ConstCompatible::value - /// \endcode - /// - template - using ConstCompatible = detail::ConstCompatible; - - - ///////////////////////////////////////////////// - /// \brief Demangle the ABI typeinfo name of a symbol into a human-readable - /// version. - /// \param[in] _symbol - /// Pass in the result of typeid(T).name() - /// \return The demangled (human-readable) version of the symbol name - std::string IGNITION_PLUGIN_VISIBLE DemangleSymbol( - const std::string &_symbol); - } -} - -#endif +#include +#include diff --git a/core/src/EnablePluginFromThis.cc b/core/src/EnablePluginFromThis.cc index 68664f21..9b5cf22f 100644 --- a/core/src/EnablePluginFromThis.cc +++ b/core/src/EnablePluginFromThis.cc @@ -15,8 +15,8 @@ * */ -#include -#include +#include +#include namespace ignition { diff --git a/core/src/Factory.cc b/core/src/Factory.cc index 37dabb80..b31f57cd 100644 --- a/core/src/Factory.cc +++ b/core/src/Factory.cc @@ -20,7 +20,7 @@ #include #include -#include +#include namespace { diff --git a/core/src/Factory_TEST.cc b/core/src/Factory_TEST.cc index 771ee1d8..6dcc149a 100644 --- a/core/src/Factory_TEST.cc +++ b/core/src/Factory_TEST.cc @@ -20,7 +20,7 @@ #include #include -#include +#include // Dev Note (MXG): These tests are just here to make sure that the template and // inheritance schemes for Factories are working as expected. If the diff --git a/core/src/Info.cc b/core/src/Info.cc index 22401056..3c914bcd 100644 --- a/core/src/Info.cc +++ b/core/src/Info.cc @@ -15,7 +15,7 @@ * */ -#include +#include namespace ignition { diff --git a/core/src/Info_TEST.cc b/core/src/Info_TEST.cc index 550fc6a3..27a729cc 100644 --- a/core/src/Info_TEST.cc +++ b/core/src/Info_TEST.cc @@ -17,7 +17,7 @@ #include -#include +#include struct SomeInterface { diff --git a/core/src/Plugin.cc b/core/src/Plugin.cc index e56ac091..d57c9b44 100644 --- a/core/src/Plugin.cc +++ b/core/src/Plugin.cc @@ -19,8 +19,8 @@ #include #include -#include "ignition/plugin/Plugin.hh" -#include "ignition/plugin/Info.hh" +#include "gz/plugin/Plugin.hh" +#include "gz/plugin/Info.hh" namespace ignition { diff --git a/core/src/WeakPluginPtr.cc b/core/src/WeakPluginPtr.cc index 246e66de..9d2e5647 100644 --- a/core/src/WeakPluginPtr.cc +++ b/core/src/WeakPluginPtr.cc @@ -15,7 +15,7 @@ * */ -#include +#include namespace ignition { diff --git a/core/src/utility.cc b/core/src/utility.cc index f4135309..9cc4c731 100644 --- a/core/src/utility.cc +++ b/core/src/utility.cc @@ -25,7 +25,7 @@ #include #endif -#include +#include namespace ignition { diff --git a/core/src/utility_TEST.cc b/core/src/utility_TEST.cc index 9897fc52..62849a6b 100644 --- a/core/src/utility_TEST.cc +++ b/core/src/utility_TEST.cc @@ -17,7 +17,7 @@ #include -#include +#include using namespace ignition::plugin; diff --git a/examples/integrators.cc b/examples/integrators.cc index 77c1e561..5be94e65 100644 --- a/examples/integrators.cc +++ b/examples/integrators.cc @@ -22,8 +22,8 @@ #include #include -#include -#include +#include +#include #include "plugins/integrators.hh" diff --git a/examples/plugins/ExponentialODE.cc b/examples/plugins/ExponentialODE.cc index e853f02f..a6b8e7f0 100644 --- a/examples/plugins/ExponentialODE.cc +++ b/examples/plugins/ExponentialODE.cc @@ -17,7 +17,7 @@ #include -#include +#include #include "integrators.hh" diff --git a/examples/plugins/ForwardEuler.cc b/examples/plugins/ForwardEuler.cc index d62013e5..636d97b6 100644 --- a/examples/plugins/ForwardEuler.cc +++ b/examples/plugins/ForwardEuler.cc @@ -17,7 +17,7 @@ #include -#include +#include #include "integrators.hh" diff --git a/examples/plugins/PolynomialODE.cc b/examples/plugins/PolynomialODE.cc index bce1b05d..d91a45de 100644 --- a/examples/plugins/PolynomialODE.cc +++ b/examples/plugins/PolynomialODE.cc @@ -17,7 +17,7 @@ #include -#include +#include #include "integrators.hh" diff --git a/examples/plugins/RungeKutta4.cc b/examples/plugins/RungeKutta4.cc index 7cd042f4..dbfa9e3f 100644 --- a/examples/plugins/RungeKutta4.cc +++ b/examples/plugins/RungeKutta4.cc @@ -17,7 +17,7 @@ #include -#include +#include #include "integrators.hh" diff --git a/examples/plugins/integrators.hh b/examples/plugins/integrators.hh index 7a1238d5..b83c2a59 100644 --- a/examples/plugins/integrators.hh +++ b/examples/plugins/integrators.hh @@ -15,8 +15,8 @@ * */ -#ifndef IGNITION_PLUGIN_EXAMPLES_PLUGINS_INTEGRATORS_HH_ -#define IGNITION_PLUGIN_EXAMPLES_PLUGINS_INTEGRATORS_HH_ +#ifndef GZ_PLUGIN_EXAMPLES_PLUGINS_INTEGRATORS_HH_ +#define GZ_PLUGIN_EXAMPLES_PLUGINS_INTEGRATORS_HH_ #include #include diff --git a/examples/plugins/robot.hh b/examples/plugins/robot.hh index 585711ca..f50ce215 100644 --- a/examples/plugins/robot.hh +++ b/examples/plugins/robot.hh @@ -15,15 +15,15 @@ * */ -#ifndef IGNITION_PLUGIN_EXAMPLES_PLUGINS_ROBOT_HH_ -#define IGNITION_PLUGIN_EXAMPLES_PLUGINS_ROBOT_HH_ +#ifndef GZ_PLUGIN_EXAMPLES_PLUGINS_ROBOT_HH_ +#define GZ_PLUGIN_EXAMPLES_PLUGINS_ROBOT_HH_ #include -#include -#include +#include +#include -#include +#include namespace ignition { diff --git a/examples/robot.cc b/examples/robot.cc index b258231c..7cd30dba 100644 --- a/examples/robot.cc +++ b/examples/robot.cc @@ -22,9 +22,9 @@ #include "plugins/robot.hh" -#include -#include -#include +#include +#include +#include #ifdef HAVE_BOOST_PROGRAM_OPTIONS #include diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 6420b909..8da87c81 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -3,9 +3,9 @@ # "tests" variable ign_get_libsources_and_unittests(sources tests) -# Disable ign_TEST if ignition-tools is not found +# Disable gz_TEST if ignition-tools is not found if (MSVC OR NOT IGN_TOOLS_PROGRAM) - list(REMOVE_ITEM tests src/ign_TEST.cc) + list(REMOVE_ITEM tests src/gz_TEST.cc) endif() # Create the library target @@ -44,11 +44,11 @@ foreach(test ${test_targets}) endforeach() -if(TARGET UNIT_ign_TEST) +if(TARGET UNIT_gz_TEST) set(_env_vars) list(APPEND _env_vars "IGN_CONFIG_PATH=${CMAKE_BINARY_DIR}/test/conf/$") - set_tests_properties(UNIT_ign_TEST PROPERTIES + set_tests_properties(UNIT_gz_TEST PROPERTIES ENVIRONMENT "${_env_vars}") endif() diff --git a/loader/include/CMakeLists.txt b/loader/include/CMakeLists.txt new file mode 100644 index 00000000..4b2bdd7b --- /dev/null +++ b/loader/include/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(gz) +install(DIRECTORY ignition DESTINATION ${IGN_INCLUDE_INSTALL_DIR_FULL}) diff --git a/loader/include/gz/plugin/Loader.hh b/loader/include/gz/plugin/Loader.hh new file mode 100644 index 00000000..c77b0862 --- /dev/null +++ b/loader/include/gz/plugin/Loader.hh @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef GZ_PLUGIN_LOADER_HH_ +#define GZ_PLUGIN_LOADER_HH_ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +namespace ignition +{ + namespace plugin + { + /// \brief Class for loading plugins + class IGNITION_PLUGIN_LOADER_VISIBLE Loader + { + /// \brief Constructor + public: Loader(); + + /// \brief Destructor + public: ~Loader(); + + /// \brief Makes a printable string with info about plugins + /// + /// \returns A pretty string + public: std::string PrettyStr() const; + + /// \brief Get demangled names of interfaces that the loader has plugins + /// for. + /// + /// \returns Demangled names of the interfaces that are implemented + public: std::unordered_set InterfacesImplemented() const; + + /// \brief Get plugin names that implement the specified interface + /// + /// \return names of plugins that implement the interface. + public: template + std::unordered_set PluginsImplementing() const; + + /// \brief Get plugin names that implement the specified interface string. + /// Note that the templated version of this function is recommended + /// instead of this version to avoid confusion about whether a mangled or + /// demangled version of a string is being used. Note that the function + /// InterfacesImplemented() returns demangled versions of the interface + /// names. + /// + /// If you want to pass in a mangled version of an interface name, e.g. + /// the result that would be produced by typeid(T).name(), then set + /// `demangled` to false. + /// + /// \param[in] _interface + /// Name of an interface + /// + /// \param[in] _demangled + /// Specify whether the _interface string is demangled (default, true) + /// or mangled (false). + /// + /// \returns Names of plugins that implement the interface + public: std::unordered_set PluginsImplementing( + const std::string &_interface, + const bool _demangled = true) const; + + /// \brief Get a set of the names of all plugins that are currently known + /// to this Loader. + /// \return A set of all plugin names known to this Loader. + public: std::set AllPlugins() const; + + /// \brief Get plugin names that correspond to the specified alias string. + /// + /// If there is more than one entry in this set, then the alias cannot be + /// used to instantiate any of those plugins. + /// + /// If the name of a plugin matches the alias string, then that plugin + /// will be instantiated any time the string is used to instantiate a + /// plugin, no matter how many other plugins use the alias. + /// + /// \param[in] _alias + /// The std::string of the alias + /// + /// \return A set of plugins that correspond to the desired alias + public: std::set PluginsWithAlias( + const std::string &_alias) const; + + /// \brief Get the aliases of the plugin with the given name + /// + /// \param[in] _pluginName + /// The name of the desired plugin + /// + /// \return A set of aliases corresponding to the desired plugin + public: std::set AliasesOfPlugin( + const std::string &_pluginName) const; + + /// \brief Resolve the plugin name or alias into the name of the plugin + /// that it maps to. If this is a name or alias that does not uniquely map + /// to a known plugin, then the return value will be an empty string. + /// + /// \param[in] _nameOrAlias + /// The name or alias of the plugin of interest. + /// + /// \return The name of the plugin being referred to, or an empty string + /// if no such plugin is known. + public: std::string LookupPlugin(const std::string &_nameOrAlias) const; + + /// \brief Load a library at the given path + /// + /// \param[in] _pathToLibrary + /// The path to a library + /// + /// \returns The set of plugins that have been loaded from the library + public: std::unordered_set LoadLib( + const std::string &_pathToLibrary); + + /// \brief Instantiates a plugin for the given plugin name + /// + /// \param[in] _pluginNameOrAlias + /// Name or alias of the plugin to instantiate. + /// + /// \returns Pointer to instantiated plugin + public: PluginPtr Instantiate( + const std::string &_pluginNameOrAlias) const; + + /// \brief Instantiates a plugin of PluginType for the given plugin name. + /// This can be used to create a specialized PluginPtr. + /// + /// \tparam PluginPtrType + /// The specialized type of PluginPtrPtr that you + /// want to construct. + /// + /// \param[in] _pluginNameOrAlias + /// Name or alias of the plugin that you want to instantiate. + /// + /// \returns pointer for the instantiated PluginPtr + public: template + PluginPtrType Instantiate(const std::string &_pluginNameOrAlias) const; + + /// \brief Instantiates a plugin for the given plugin name, and then + /// returns a reference-counting interface corresponding to InterfaceType. + /// + /// If you use this function to retrieve a Factory, you can call + /// Construct(...) on the returned interface, as long as the returned + /// interface is not a nullptr. + /// + /// \remark This function is identical to: + /// + /// \code + /// loader->Instantiate(_pluginNameOrAlias) + /// ->QueryInterfaceSharedPtr(); + /// \endcode + /// + /// \tparam InterfaceType + /// The type of interface to look for. This function is meant for + /// producing Factories, but any type of Interface can be requested. + /// + /// \param[in] _pluginNameOrAlias + /// Name or alias of the plugin that you want to use for production. + /// + /// \return reference to an InterfaceType if it can be provided by the + /// requested plugin. + public: template + std::shared_ptr Factory( + const std::string &_pluginNameOrAlias) const; + + /// \brief This loader will forget about the library at the given path + /// location. If you want to instantiate a plugin from this library using + /// this loader, you will first need to call LoadLib again. + /// + /// After this function has been called, once all plugin instances that + /// are tied to the library have been deleted, the library will + /// automatically be unloaded from the executable. Note that when this + /// Loader leaves scope (or gets deleted), it will have the same + /// effect as calling ForgetLibrary on all of the libraries that it + /// loaded, so there is generally no need to call this function. However, + /// it may be useful if you want to reduce clutter in the Loader + /// instance or let go of library resources that are no longer being used. + /// + /// Note that even if you have released all references to a library, it is + /// still up to the discretion of your operating system whether (or when) + /// that library will be unloaded. In some cases, the operating system + /// might not choose to unload it until the program exits completely. + /// + /// \param[in] _pathToLibrary + /// Path to the library that you want to forget + /// + /// \return True if the library was actively loaded and is now + /// successfully forgotten. If the library was not actively loaded, this + /// returns false. + public: bool ForgetLibrary(const std::string &_pathToLibrary); + + /// \brief Forget the library that provides the plugin with the given + /// name. Note that this will also forget all other plugin types which + /// are provided by that library. + /// + /// \param[in] _pluginNameOrAlias + /// Name or alias of the plugin whose library you want to forget. + /// + /// \sa bool ForgetLibrary(const std::string &_pathToLibrary) + public: bool ForgetLibraryOfPlugin(const std::string &_pluginNameOrAlias); + + /// \brief Get a pointer to the Info corresponding to _pluginName. + /// + /// \param[in] _resolvedName + /// The resolved name, i.e. the demangled class symbol name as returned + /// by LookupPlugin(~), of the plugin that you want to instantiate. + /// + /// \return Pointer to the corresponding Info, or nullptr if there + /// is no info for the requested _pluginName. + private: ConstInfoPtr PrivateGetInfo( + const std::string &_resolvedName) const; + + /// \brief Get a std::shared_ptr that manages the lifecycle of the shared + /// library handle which provides the specified plugin. + /// + /// \param[in] _resolvedName + /// The resolved name, i.e. the demangled class symbol name as returned + /// by LookupPlugin(~), of the plugin that you want to instantiate. + /// + /// \return Reference-counting pointer to a library handle, or else a + /// nullptr if the plugin is not available. + private: std::shared_ptr PrivateGetPluginDlHandlePtr( + const std::string &_resolvedName) const; + + class Implementation; + IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING + /// \brief PIMPL pointer to class implementation + private: std::unique_ptr dataPtr; + IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING + }; + } +} + +#include + +#endif diff --git a/loader/include/ignition/plugin/detail/Loader.hh b/loader/include/gz/plugin/detail/Loader.hh similarity index 91% rename from loader/include/ignition/plugin/detail/Loader.hh rename to loader/include/gz/plugin/detail/Loader.hh index 49a293ae..ce5ce0f6 100644 --- a/loader/include/ignition/plugin/detail/Loader.hh +++ b/loader/include/gz/plugin/detail/Loader.hh @@ -16,14 +16,14 @@ */ -#ifndef IGNITION_PLUGIN_DETAIL_LOADER_HH_ -#define IGNITION_PLUGIN_DETAIL_LOADER_HH_ +#ifndef GZ_PLUGIN_DETAIL_LOADER_HH_ +#define GZ_PLUGIN_DETAIL_LOADER_HH_ #include #include #include -#include -#include +#include +#include namespace ignition { diff --git a/loader/include/ignition/plugin/Loader.hh b/loader/include/ignition/plugin/Loader.hh index 0726663b..395456ba 100644 --- a/loader/include/ignition/plugin/Loader.hh +++ b/loader/include/ignition/plugin/Loader.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Open Source Robotics Foundation + * Copyright (C) 2022 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,242 +15,5 @@ * */ - -#ifndef IGNITION_PLUGIN_LOADER_HH_ -#define IGNITION_PLUGIN_LOADER_HH_ - -#include -#include -#include -#include -#include - -#include - -#include -#include - -namespace ignition -{ - namespace plugin - { - /// \brief Class for loading plugins - class IGNITION_PLUGIN_LOADER_VISIBLE Loader - { - /// \brief Constructor - public: Loader(); - - /// \brief Destructor - public: ~Loader(); - - /// \brief Makes a printable string with info about plugins - /// - /// \returns A pretty string - public: std::string PrettyStr() const; - - /// \brief Get demangled names of interfaces that the loader has plugins - /// for. - /// - /// \returns Demangled names of the interfaces that are implemented - public: std::unordered_set InterfacesImplemented() const; - - /// \brief Get plugin names that implement the specified interface - /// - /// \return names of plugins that implement the interface. - public: template - std::unordered_set PluginsImplementing() const; - - /// \brief Get plugin names that implement the specified interface string. - /// Note that the templated version of this function is recommended - /// instead of this version to avoid confusion about whether a mangled or - /// demangled version of a string is being used. Note that the function - /// InterfacesImplemented() returns demangled versions of the interface - /// names. - /// - /// If you want to pass in a mangled version of an interface name, e.g. - /// the result that would be produced by typeid(T).name(), then set - /// `demangled` to false. - /// - /// \param[in] _interface - /// Name of an interface - /// - /// \param[in] _demangled - /// Specify whether the _interface string is demangled (default, true) - /// or mangled (false). - /// - /// \returns Names of plugins that implement the interface - public: std::unordered_set PluginsImplementing( - const std::string &_interface, - const bool _demangled = true) const; - - /// \brief Get a set of the names of all plugins that are currently known - /// to this Loader. - /// \return A set of all plugin names known to this Loader. - public: std::set AllPlugins() const; - - /// \brief Get plugin names that correspond to the specified alias string. - /// - /// If there is more than one entry in this set, then the alias cannot be - /// used to instantiate any of those plugins. - /// - /// If the name of a plugin matches the alias string, then that plugin - /// will be instantiated any time the string is used to instantiate a - /// plugin, no matter how many other plugins use the alias. - /// - /// \param[in] _alias - /// The std::string of the alias - /// - /// \return A set of plugins that correspond to the desired alias - public: std::set PluginsWithAlias( - const std::string &_alias) const; - - /// \brief Get the aliases of the plugin with the given name - /// - /// \param[in] _pluginName - /// The name of the desired plugin - /// - /// \return A set of aliases corresponding to the desired plugin - public: std::set AliasesOfPlugin( - const std::string &_pluginName) const; - - /// \brief Resolve the plugin name or alias into the name of the plugin - /// that it maps to. If this is a name or alias that does not uniquely map - /// to a known plugin, then the return value will be an empty string. - /// - /// \param[in] _nameOrAlias - /// The name or alias of the plugin of interest. - /// - /// \return The name of the plugin being referred to, or an empty string - /// if no such plugin is known. - public: std::string LookupPlugin(const std::string &_nameOrAlias) const; - - /// \brief Load a library at the given path - /// - /// \param[in] _pathToLibrary - /// The path to a library - /// - /// \returns The set of plugins that have been loaded from the library - public: std::unordered_set LoadLib( - const std::string &_pathToLibrary); - - /// \brief Instantiates a plugin for the given plugin name - /// - /// \param[in] _pluginNameOrAlias - /// Name or alias of the plugin to instantiate. - /// - /// \returns Pointer to instantiated plugin - public: PluginPtr Instantiate( - const std::string &_pluginNameOrAlias) const; - - /// \brief Instantiates a plugin of PluginType for the given plugin name. - /// This can be used to create a specialized PluginPtr. - /// - /// \tparam PluginPtrType - /// The specialized type of PluginPtrPtr that you - /// want to construct. - /// - /// \param[in] _pluginNameOrAlias - /// Name or alias of the plugin that you want to instantiate. - /// - /// \returns pointer for the instantiated PluginPtr - public: template - PluginPtrType Instantiate(const std::string &_pluginNameOrAlias) const; - - /// \brief Instantiates a plugin for the given plugin name, and then - /// returns a reference-counting interface corresponding to InterfaceType. - /// - /// If you use this function to retrieve a Factory, you can call - /// Construct(...) on the returned interface, as long as the returned - /// interface is not a nullptr. - /// - /// \remark This function is identical to: - /// - /// \code - /// loader->Instantiate(_pluginNameOrAlias) - /// ->QueryInterfaceSharedPtr(); - /// \endcode - /// - /// \tparam InterfaceType - /// The type of interface to look for. This function is meant for - /// producing Factories, but any type of Interface can be requested. - /// - /// \param[in] _pluginNameOrAlias - /// Name or alias of the plugin that you want to use for production. - /// - /// \return reference to an InterfaceType if it can be provided by the - /// requested plugin. - public: template - std::shared_ptr Factory( - const std::string &_pluginNameOrAlias) const; - - /// \brief This loader will forget about the library at the given path - /// location. If you want to instantiate a plugin from this library using - /// this loader, you will first need to call LoadLib again. - /// - /// After this function has been called, once all plugin instances that - /// are tied to the library have been deleted, the library will - /// automatically be unloaded from the executable. Note that when this - /// Loader leaves scope (or gets deleted), it will have the same - /// effect as calling ForgetLibrary on all of the libraries that it - /// loaded, so there is generally no need to call this function. However, - /// it may be useful if you want to reduce clutter in the Loader - /// instance or let go of library resources that are no longer being used. - /// - /// Note that even if you have released all references to a library, it is - /// still up to the discretion of your operating system whether (or when) - /// that library will be unloaded. In some cases, the operating system - /// might not choose to unload it until the program exits completely. - /// - /// \param[in] _pathToLibrary - /// Path to the library that you want to forget - /// - /// \return True if the library was actively loaded and is now - /// successfully forgotten. If the library was not actively loaded, this - /// returns false. - public: bool ForgetLibrary(const std::string &_pathToLibrary); - - /// \brief Forget the library that provides the plugin with the given - /// name. Note that this will also forget all other plugin types which - /// are provided by that library. - /// - /// \param[in] _pluginNameOrAlias - /// Name or alias of the plugin whose library you want to forget. - /// - /// \sa bool ForgetLibrary(const std::string &_pathToLibrary) - public: bool ForgetLibraryOfPlugin(const std::string &_pluginNameOrAlias); - - /// \brief Get a pointer to the Info corresponding to _pluginName. - /// - /// \param[in] _resolvedName - /// The resolved name, i.e. the demangled class symbol name as returned - /// by LookupPlugin(~), of the plugin that you want to instantiate. - /// - /// \return Pointer to the corresponding Info, or nullptr if there - /// is no info for the requested _pluginName. - private: ConstInfoPtr PrivateGetInfo( - const std::string &_resolvedName) const; - - /// \brief Get a std::shared_ptr that manages the lifecycle of the shared - /// library handle which provides the specified plugin. - /// - /// \param[in] _resolvedName - /// The resolved name, i.e. the demangled class symbol name as returned - /// by LookupPlugin(~), of the plugin that you want to instantiate. - /// - /// \return Reference-counting pointer to a library handle, or else a - /// nullptr if the plugin is not available. - private: std::shared_ptr PrivateGetPluginDlHandlePtr( - const std::string &_resolvedName) const; - - class Implementation; - IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING - /// \brief PIMPL pointer to class implementation - private: std::unique_ptr dataPtr; - IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING - }; - } -} - -#include - -#endif +#include +#include diff --git a/loader/include/ignition/plugin/loader/Export.hh b/loader/include/ignition/plugin/loader/Export.hh new file mode 100644 index 00000000..8ef34569 --- /dev/null +++ b/loader/include/ignition/plugin/loader/Export.hh @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include diff --git a/loader/src/Loader.cc b/loader/src/Loader.cc index 4b6362f1..a0a40ba6 100644 --- a/loader/src/Loader.cc +++ b/loader/src/Loader.cc @@ -26,11 +26,11 @@ #include #include -#include -#include -#include +#include +#include +#include -#include +#include namespace ignition { diff --git a/loader/src/Loader_TEST.cc b/loader/src/Loader_TEST.cc index 13f520b1..8c641305 100644 --- a/loader/src/Loader_TEST.cc +++ b/loader/src/Loader_TEST.cc @@ -19,10 +19,10 @@ #include -#include -#include +#include +#include -#include +#include ///////////////////////////////////////////////// TEST(Loader, InitialNoInterfacesImplemented) diff --git a/loader/src/ign.cc b/loader/src/gz.cc similarity index 96% rename from loader/src/ign.cc rename to loader/src/gz.cc index 368b7f1d..a689b452 100644 --- a/loader/src/ign.cc +++ b/loader/src/gz.cc @@ -18,8 +18,8 @@ #include #include -#include "ignition/plugin/Loader.hh" -#include "ignition/plugin/config.hh" +#include "gz/plugin/Loader.hh" +#include "gz/plugin/config.hh" using namespace ignition; using namespace plugin; diff --git a/loader/src/ign_TEST.cc b/loader/src/gz_TEST.cc similarity index 99% rename from loader/src/ign_TEST.cc rename to loader/src/gz_TEST.cc index 9a2adc38..fd97a37f 100644 --- a/loader/src/ign_TEST.cc +++ b/loader/src/gz_TEST.cc @@ -21,7 +21,7 @@ #include #include "gtest/gtest.h" -#include "ignition/plugin/Loader.hh" +#include "gz/plugin/Loader.hh" #ifdef _MSC_VER # define popen _popen diff --git a/register/include/CMakeLists.txt b/register/include/CMakeLists.txt new file mode 100644 index 00000000..4b2bdd7b --- /dev/null +++ b/register/include/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(gz) +install(DIRECTORY ignition DESTINATION ${IGN_INCLUDE_INSTALL_DIR_FULL}) diff --git a/register/include/gz/plugin/Register.hh b/register/include/gz/plugin/Register.hh new file mode 100644 index 00000000..2dc7f9a1 --- /dev/null +++ b/register/include/gz/plugin/Register.hh @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ + + +#ifndef GZ_PLUGIN_REGISTER_HH_ +#define GZ_PLUGIN_REGISTER_HH_ + +#include + + +// ------------- Add a set of plugins or a set of interfaces ------------------ + +/// \brief Add a plugin and interface from this shared library. +/// +/// This macro can be put in any namespace and may be called any number of +/// times. It can be called multiple times on the same plugin class in order to +/// register multiple interfaces, e.g.: +/// +/// \code +/// IGNITION_ADD_PLUGIN(PluginClass, Interface1) +/// IGNITION_ADD_PLUGIN(PluginClass, Interface2) +/// +/// /* Some other code */ +/// +/// IGNITION_ADD_PLUGIN(PluginClass, Interface3) +/// \endcode +/// +/// Or you can list multiple interfaces in a single call to the macro, e.g.: +/// +/// \code +/// IGNITION_ADD_PLUGIN(PluginClass, Interface1, Interface2, Interface3) +/// \endcode +/// +/// If your library has multiple translation units (.cpp files) and you want to +/// register plugins in multiple translation units, use this +/// ignition/plugin/Register.hh header in ONE of the translation units, and then +/// the ignition/plugin/RegisterMore.hh header in all of the rest of the +/// translation units. +#define IGNITION_ADD_PLUGIN(PluginClass, ...) \ + DETAIL_IGNITION_ADD_PLUGIN(PluginClass, __VA_ARGS__) + +/// \brief Add an alias for one of your plugins. +/// +/// This macro can be put in any namespace and may be called any number of +/// times. It can be called multiple times on the same plugin class in order to +/// register multiple aliases, e.g.: +/// +/// \code +/// IGNITION_ADD_PLUGIN_ALIAS(PluginClass, "PluginClass") +/// IGNITION_ADD_PLUGIN_ALIAS(PluginClass, "SomeOtherName", "Yet another name") +/// IGNOTION_ADD_PLUGIN_ALIAS(AnotherPluginClass, "Foo", "Bar", "Baz") +/// \endcode +/// +/// You can give the same alias to multiple plugins, but then that alias can no +/// longer be used to instantiate any plugin. +/// +/// If you give a plugin an alias string that matches the demangled symbol name +/// of another plugin, then the Loader will always prefer to instantiate the +/// plugin whose symbol name matches that string. +#define IGNITION_ADD_PLUGIN_ALIAS(PluginClass, ...) \ + DETAIL_IGNITION_ADD_PLUGIN_ALIAS(PluginClass, __VA_ARGS__) + + +/// \brief Add a plugin factory. +/// +/// A plugin factory is a plugin that is able to generate objects that implement +/// some interface. These objects can be passed off to a consumer, and as long +/// as the object is alive, it will ensure that the shared library of the plugin +/// remains loaded. The objects are handed off with a std::unique_ptr, so the +/// raw pointer can be released from its std::unique_ptr and passed into any +/// memory management system the consumer prefers. +/// +/// The inputs and output of a factory are defined using the +/// ignition::plugin::Factory class in the ignition/plugin/Factory.hh header. +/// +/// The first argument of this macro should be the class that implements the +/// factory's output interface. The second argument should be the factory +/// definition. +/// +/// NOTE: If your factory has any input arguments, then you must define it +/// outside of this macro, or else you will get a compilation error. This +/// happens because macros will parse the commas between your template arguments +/// as separators for the macro arguments. For example: +/// +/// \code +/// class MyBase +/// { +/// public: virtual double SomeFunction() = 0; +/// }; +/// +/// class MyType : public MyBase +/// { +/// public: MyType(double value); +/// public: double SomeFunction() override; +/// }; +/// +/// /* BAD! Will not compile: +/// IGNITION_ADD_FACTORY(MyType, ignition::plugin::Factory); +/// */ +/// +/// // Instead do this: +/// using MyFactory = ignition::plugin::Factory; +/// IGNITION_ADD_FACTORY(MyType, MyFactory); +/// \endcode +#define IGNITION_ADD_FACTORY(ProductType, FactoryType) \ + DETAIL_IGNITION_ADD_FACTORY(ProductType, FactoryType) + +/// \brief Add an alias for a factory. +/// +/// This will do the same as IGNITION_ADD_FACTORY(), but you may also add in +/// any number of strings which can then be used as aliases for this factory. +/// For example: +/// +/// \code +/// IGNITION_ADD_FACTORY_ALIAS(MyType, MyFactory, "Foo", "My favorite factory") +/// \endcode +/// +/// This macro can be called any number of times for the same factory or for +/// different factories. If you call this macro, you do not need to call +/// IGNITION_ADD_FACTORY(), but there is nothing wrong with calling both (except +/// it might imperceptibly increase your compile time). +#define IGNITION_ADD_FACTORY_ALIAS(ProductType, FactoryType, ...) \ + DETAIL_IGNITION_ADD_FACTORY_ALIAS(ProductType, FactoryType, __VA_ARGS__) + + +#endif diff --git a/register/include/gz/plugin/RegisterMore.hh b/register/include/gz/plugin/RegisterMore.hh new file mode 100644 index 00000000..4763420f --- /dev/null +++ b/register/include/gz/plugin/RegisterMore.hh @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ + + +#ifndef GZ_PLUGIN_REGISTERMORE_HH_ +#define GZ_PLUGIN_REGISTERMORE_HH_ + +/// If your library already has a translation unit (.cpp file) containing +/// \code +/// #include +/// \endcode +/// +/// then any other translation units that want to register plugins should use +/// \code +/// #include +/// \endcode +/// +/// But at least one translation unit of your library must contain Register.hh. +#define IGN_PLUGIN_REGISTER_MORE_TRANS_UNITS +#include + +#endif diff --git a/register/include/ignition/plugin/detail/Register.hh b/register/include/gz/plugin/detail/Register.hh similarity index 98% rename from register/include/ignition/plugin/detail/Register.hh rename to register/include/gz/plugin/detail/Register.hh index cd62ba41..3a2432bc 100644 --- a/register/include/ignition/plugin/detail/Register.hh +++ b/register/include/gz/plugin/detail/Register.hh @@ -16,8 +16,8 @@ */ -#ifndef IGNITION_PLUGIN_DETAIL_REGISTER_HH_ -#define IGNITION_PLUGIN_DETAIL_REGISTER_HH_ +#ifndef GZ_PLUGIN_DETAIL_REGISTER_HH_ +#define GZ_PLUGIN_DETAIL_REGISTER_HH_ #include #include @@ -25,11 +25,11 @@ #include #include -#include +#include -#include -#include -#include +#include +#include +#include #if defined _WIN32 || defined __CYGWIN__ diff --git a/register/include/ignition/plugin/Register.hh b/register/include/ignition/plugin/Register.hh index e0cb43ad..f718125b 100644 --- a/register/include/ignition/plugin/Register.hh +++ b/register/include/ignition/plugin/Register.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Open Source Robotics Foundation + * Copyright (C) 2022 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,128 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * -*/ + */ - -#ifndef IGNITION_PLUGIN_REGISTER_HH_ -#define IGNITION_PLUGIN_REGISTER_HH_ - -#include - - -// ------------- Add a set of plugins or a set of interfaces ------------------ - -/// \brief Add a plugin and interface from this shared library. -/// -/// This macro can be put in any namespace and may be called any number of -/// times. It can be called multiple times on the same plugin class in order to -/// register multiple interfaces, e.g.: -/// -/// \code -/// IGNITION_ADD_PLUGIN(PluginClass, Interface1) -/// IGNITION_ADD_PLUGIN(PluginClass, Interface2) -/// -/// /* Some other code */ -/// -/// IGNITION_ADD_PLUGIN(PluginClass, Interface3) -/// \endcode -/// -/// Or you can list multiple interfaces in a single call to the macro, e.g.: -/// -/// \code -/// IGNITION_ADD_PLUGIN(PluginClass, Interface1, Interface2, Interface3) -/// \endcode -/// -/// If your library has multiple translation units (.cpp files) and you want to -/// register plugins in multiple translation units, use this -/// ignition/plugin/Register.hh header in ONE of the translation units, and then -/// the ignition/plugin/RegisterMore.hh header in all of the rest of the -/// translation units. -#define IGNITION_ADD_PLUGIN(PluginClass, ...) \ - DETAIL_IGNITION_ADD_PLUGIN(PluginClass, __VA_ARGS__) - -/// \brief Add an alias for one of your plugins. -/// -/// This macro can be put in any namespace and may be called any number of -/// times. It can be called multiple times on the same plugin class in order to -/// register multiple aliases, e.g.: -/// -/// \code -/// IGNITION_ADD_PLUGIN_ALIAS(PluginClass, "PluginClass") -/// IGNITION_ADD_PLUGIN_ALIAS(PluginClass, "SomeOtherName", "Yet another name") -/// IGNOTION_ADD_PLUGIN_ALIAS(AnotherPluginClass, "Foo", "Bar", "Baz") -/// \endcode -/// -/// You can give the same alias to multiple plugins, but then that alias can no -/// longer be used to instantiate any plugin. -/// -/// If you give a plugin an alias string that matches the demangled symbol name -/// of another plugin, then the Loader will always prefer to instantiate the -/// plugin whose symbol name matches that string. -#define IGNITION_ADD_PLUGIN_ALIAS(PluginClass, ...) \ - DETAIL_IGNITION_ADD_PLUGIN_ALIAS(PluginClass, __VA_ARGS__) - - -/// \brief Add a plugin factory. -/// -/// A plugin factory is a plugin that is able to generate objects that implement -/// some interface. These objects can be passed off to a consumer, and as long -/// as the object is alive, it will ensure that the shared library of the plugin -/// remains loaded. The objects are handed off with a std::unique_ptr, so the -/// raw pointer can be released from its std::unique_ptr and passed into any -/// memory management system the consumer prefers. -/// -/// The inputs and output of a factory are defined using the -/// ignition::plugin::Factory class in the ignition/plugin/Factory.hh header. -/// -/// The first argument of this macro should be the class that implements the -/// factory's output interface. The second argument should be the factory -/// definition. -/// -/// NOTE: If your factory has any input arguments, then you must define it -/// outside of this macro, or else you will get a compilation error. This -/// happens because macros will parse the commas between your template arguments -/// as separators for the macro arguments. For example: -/// -/// \code -/// class MyBase -/// { -/// public: virtual double SomeFunction() = 0; -/// }; -/// -/// class MyType : public MyBase -/// { -/// public: MyType(double value); -/// public: double SomeFunction() override; -/// }; -/// -/// /* BAD! Will not compile: -/// IGNITION_ADD_FACTORY(MyType, ignition::plugin::Factory); -/// */ -/// -/// // Instead do this: -/// using MyFactory = ignition::plugin::Factory; -/// IGNITION_ADD_FACTORY(MyType, MyFactory); -/// \endcode -#define IGNITION_ADD_FACTORY(ProductType, FactoryType) \ - DETAIL_IGNITION_ADD_FACTORY(ProductType, FactoryType) - -/// \brief Add an alias for a factory. -/// -/// This will do the same as IGNITION_ADD_FACTORY(), but you may also add in -/// any number of strings which can then be used as aliases for this factory. -/// For example: -/// -/// \code -/// IGNITION_ADD_FACTORY_ALIAS(MyType, MyFactory, "Foo", "My favorite factory") -/// \endcode -/// -/// This macro can be called any number of times for the same factory or for -/// different factories. If you call this macro, you do not need to call -/// IGNITION_ADD_FACTORY(), but there is nothing wrong with calling both (except -/// it might imperceptibly increase your compile time). -#define IGNITION_ADD_FACTORY_ALIAS(ProductType, FactoryType, ...) \ - DETAIL_IGNITION_ADD_FACTORY_ALIAS(ProductType, FactoryType, __VA_ARGS__) - - -#endif +#include +#include diff --git a/register/include/ignition/plugin/RegisterMore.hh b/register/include/ignition/plugin/RegisterMore.hh index a69d6d8b..68445cf3 100644 --- a/register/include/ignition/plugin/RegisterMore.hh +++ b/register/include/ignition/plugin/RegisterMore.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Open Source Robotics Foundation + * Copyright (C) 2022 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,24 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * -*/ + */ - -#ifndef IGNITION_PLUGIN_REGISTERMORE_HH_ -#define IGNITION_PLUGIN_REGISTERMORE_HH_ - -/// If your library already has a translation unit (.cpp file) containing -/// \code -/// #include -/// \endcode -/// -/// then any other translation units that want to register plugins should use -/// \code -/// #include -/// \endcode -/// -/// But at least one translation unit of your library must contain Register.hh. -#define IGN_PLUGIN_REGISTER_MORE_TRANS_UNITS -#include - -#endif +#include +#include diff --git a/test/integration/EnablePluginFromThis_TEST.cc b/test/integration/EnablePluginFromThis_TEST.cc index e385b8bf..0f3996fa 100644 --- a/test/integration/EnablePluginFromThis_TEST.cc +++ b/test/integration/EnablePluginFromThis_TEST.cc @@ -17,10 +17,10 @@ #include -#include -#include -#include -#include +#include +#include +#include +#include #include "../plugins/DummyPlugins.hh" #include "utils.hh" diff --git a/test/integration/WeakPluginPtr.cc b/test/integration/WeakPluginPtr.cc index c8c9f98e..3a4ad6d4 100644 --- a/test/integration/WeakPluginPtr.cc +++ b/test/integration/WeakPluginPtr.cc @@ -17,8 +17,8 @@ #include -#include -#include +#include +#include #include "../plugins/DummyPlugins.hh" #include "utils.hh" diff --git a/test/integration/aliases.cc b/test/integration/aliases.cc index 014d38b6..f2fca661 100644 --- a/test/integration/aliases.cc +++ b/test/integration/aliases.cc @@ -17,7 +17,7 @@ #include -#include +#include #include "../plugins/DummyPlugins.hh" diff --git a/test/integration/deprecated_TEST.cc b/test/integration/deprecated_TEST.cc new file mode 100644 index 00000000..da91c298 --- /dev/null +++ b/test/integration/deprecated_TEST.cc @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ + +#include +#include + +///////////////////////////////////////////////// +// Make sure the ignition namespace still works +TEST(Deprecated, IgnitionNamespace) +{ + ignition::plugin::Loader loader; +} diff --git a/test/integration/factory.cc b/test/integration/factory.cc index 625fbb53..2361b010 100644 --- a/test/integration/factory.cc +++ b/test/integration/factory.cc @@ -17,8 +17,8 @@ #include -#include -#include +#include +#include #include "../plugins/FactoryPlugins.hh" #include "utils.hh" diff --git a/test/integration/plugin.cc b/test/integration/plugin.cc index e372f8bf..4acab69c 100644 --- a/test/integration/plugin.cc +++ b/test/integration/plugin.cc @@ -24,9 +24,9 @@ #include #include #include -#include "ignition/plugin/Loader.hh" -#include "ignition/plugin/PluginPtr.hh" -#include "ignition/plugin/SpecializedPluginPtr.hh" +#include "gz/plugin/Loader.hh" +#include "gz/plugin/PluginPtr.hh" +#include "gz/plugin/SpecializedPluginPtr.hh" #include "../plugins/DummyPlugins.hh" #include "utils.hh" diff --git a/test/integration/templated_plugins.cc b/test/integration/templated_plugins.cc index 0ded41b9..c1973549 100644 --- a/test/integration/templated_plugins.cc +++ b/test/integration/templated_plugins.cc @@ -22,8 +22,8 @@ #include -#include -#include +#include +#include #include "../plugins/TemplatedPlugins.hh" diff --git a/test/integration/utils.hh b/test/integration/utils.hh index ff5ebfb0..6974cf1b 100644 --- a/test/integration/utils.hh +++ b/test/integration/utils.hh @@ -15,8 +15,8 @@ * */ -#ifndef IGNITION_TEST_INTEGRATION_UTILS_HH_ -#define IGNITION_TEST_INTEGRATION_UTILS_HH_ +#ifndef GZ_TEST_INTEGRATION_UTILS_HH_ +#define GZ_TEST_INTEGRATION_UTILS_HH_ #include diff --git a/test/performance/plugin_specialization.cc b/test/performance/plugin_specialization.cc index 055ea4dd..743f1c5a 100644 --- a/test/performance/plugin_specialization.cc +++ b/test/performance/plugin_specialization.cc @@ -21,8 +21,8 @@ #include #include -#include -#include +#include +#include #include "../plugins/DummyPlugins.hh" diff --git a/test/plugins/BadPluginAPIVersionNew.cc b/test/plugins/BadPluginAPIVersionNew.cc index b02e0280..bcb7c605 100644 --- a/test/plugins/BadPluginAPIVersionNew.cc +++ b/test/plugins/BadPluginAPIVersionNew.cc @@ -17,7 +17,7 @@ #include -#include +#include #include "GenericExport.hh" diff --git a/test/plugins/BadPluginAPIVersionOld.cc b/test/plugins/BadPluginAPIVersionOld.cc index e541c71b..0990550c 100644 --- a/test/plugins/BadPluginAPIVersionOld.cc +++ b/test/plugins/BadPluginAPIVersionOld.cc @@ -17,7 +17,7 @@ #include -#include +#include #include "GenericExport.hh" diff --git a/test/plugins/BadPluginAlign.cc b/test/plugins/BadPluginAlign.cc index b741bbe4..6be99f15 100644 --- a/test/plugins/BadPluginAlign.cc +++ b/test/plugins/BadPluginAlign.cc @@ -15,7 +15,7 @@ * */ -#include +#include #include "GenericExport.hh" diff --git a/test/plugins/BadPluginNoInfo.cc b/test/plugins/BadPluginNoInfo.cc index d4fa6aef..1e14d409 100644 --- a/test/plugins/BadPluginNoInfo.cc +++ b/test/plugins/BadPluginNoInfo.cc @@ -15,7 +15,7 @@ * */ -#include +#include #include "GenericExport.hh" diff --git a/test/plugins/BadPluginSize.cc b/test/plugins/BadPluginSize.cc index ef95157b..0ec47c62 100644 --- a/test/plugins/BadPluginSize.cc +++ b/test/plugins/BadPluginSize.cc @@ -15,7 +15,7 @@ * */ -#include +#include #include "GenericExport.hh" diff --git a/test/plugins/DummyMultiPlugin.hh b/test/plugins/DummyMultiPlugin.hh index c6fc5c62..b448c3e6 100644 --- a/test/plugins/DummyMultiPlugin.hh +++ b/test/plugins/DummyMultiPlugin.hh @@ -1,7 +1,7 @@ -#ifndef IGNITION_PLUGIN_TEST_PLUGINS_DUMMYMULTIPLUGIN_HH_ -#define IGNITION_PLUGIN_TEST_PLUGINS_DUMMYMULTIPLUGIN_HH_ +#ifndef GZ_PLUGIN_TEST_PLUGINS_DUMMYMULTIPLUGIN_HH_ +#define GZ_PLUGIN_TEST_PLUGINS_DUMMYMULTIPLUGIN_HH_ -#include +#include #include "DummyPlugins.hh" diff --git a/test/plugins/DummyPlugins.cc b/test/plugins/DummyPlugins.cc index 76e8303b..f35b223b 100644 --- a/test/plugins/DummyPlugins.cc +++ b/test/plugins/DummyPlugins.cc @@ -15,7 +15,7 @@ * */ -#include "ignition/plugin/Register.hh" +#include "gz/plugin/Register.hh" #include "DummyPlugins.hh" #include "DummyMultiPlugin.hh" diff --git a/test/plugins/DummyPlugins.hh b/test/plugins/DummyPlugins.hh index c0ee5b18..eb529101 100644 --- a/test/plugins/DummyPlugins.hh +++ b/test/plugins/DummyPlugins.hh @@ -16,8 +16,8 @@ */ -#ifndef IGNITION_PLUGIN_TEST_PLUGINS_DUMMYPLUGINS_HH_ -#define IGNITION_PLUGIN_TEST_PLUGINS_DUMMYPLUGINS_HH_ +#ifndef GZ_PLUGIN_TEST_PLUGINS_DUMMYPLUGINS_HH_ +#define GZ_PLUGIN_TEST_PLUGINS_DUMMYPLUGINS_HH_ #include #include diff --git a/test/plugins/DummyPluginsOtherTranslationUnit.cc b/test/plugins/DummyPluginsOtherTranslationUnit.cc index 4821525f..0d1ee1ed 100644 --- a/test/plugins/DummyPluginsOtherTranslationUnit.cc +++ b/test/plugins/DummyPluginsOtherTranslationUnit.cc @@ -15,7 +15,7 @@ * */ -#include +#include #include "DummyPlugins.hh" #include "DummyMultiPlugin.hh" diff --git a/test/plugins/FactoryPlugins.cc b/test/plugins/FactoryPlugins.cc index ae3ce688..e9dcfb46 100644 --- a/test/plugins/FactoryPlugins.cc +++ b/test/plugins/FactoryPlugins.cc @@ -15,7 +15,7 @@ * */ -#include +#include #include "FactoryPlugins.hh" diff --git a/test/plugins/FactoryPlugins.hh b/test/plugins/FactoryPlugins.hh index b7310a4e..4c71af43 100644 --- a/test/plugins/FactoryPlugins.hh +++ b/test/plugins/FactoryPlugins.hh @@ -15,10 +15,10 @@ * */ -#ifndef IGNITION_PLUGIN_TEST_PLUGINS_FACTORYPLUGINS_HH_ -#define IGNITION_PLUGIN_TEST_PLUGINS_FACTORYPLUGINS_HH_ +#ifndef GZ_PLUGIN_TEST_PLUGINS_FACTORYPLUGINS_HH_ +#define GZ_PLUGIN_TEST_PLUGINS_FACTORYPLUGINS_HH_ -#include +#include #include "DummyPlugins.hh" diff --git a/test/plugins/GenericExport.hh b/test/plugins/GenericExport.hh index f85d2414..a6159d06 100644 --- a/test/plugins/GenericExport.hh +++ b/test/plugins/GenericExport.hh @@ -1,5 +1,5 @@ -#ifndef IGNITION_PLUGIN_TEST_GENERICEXPORT_HH_ -#define IGNITION_PLUGIN_TEST_GENERICEXPORT_HH_ +#ifndef GZ_PLUGIN_TEST_GENERICEXPORT_HH_ +#define GZ_PLUGIN_TEST_GENERICEXPORT_HH_ #if defined _WIN32 || defined __CYGWIN__ #ifdef __GNUC__ diff --git a/test/plugins/TemplatedPlugins.cc b/test/plugins/TemplatedPlugins.cc index 84d4c623..23e2c42f 100644 --- a/test/plugins/TemplatedPlugins.cc +++ b/test/plugins/TemplatedPlugins.cc @@ -19,7 +19,7 @@ #include "TemplatedPlugins.hh" -#include +#include namespace test { diff --git a/test/plugins/TemplatedPlugins.hh b/test/plugins/TemplatedPlugins.hh index 134597d0..36a1eb61 100644 --- a/test/plugins/TemplatedPlugins.hh +++ b/test/plugins/TemplatedPlugins.hh @@ -15,8 +15,8 @@ * */ -#ifndef IGNITION_PLUGIN_TEST_PLUGINS_TEMPLATEPLUGIN_HH_ -#define IGNITION_PLUGIN_TEST_PLUGINS_TEMPLATEPLUGIN_HH_ +#ifndef GZ_PLUGIN_TEST_PLUGINS_TEMPLATEPLUGIN_HH_ +#define GZ_PLUGIN_TEST_PLUGINS_TEMPLATEPLUGIN_HH_ namespace test { diff --git a/test/static_assertions/plugin_bad_const_assignment.cc b/test/static_assertions/plugin_bad_const_assignment.cc index 6c1a6a7d..02e7e0a7 100644 --- a/test/static_assertions/plugin_bad_const_assignment.cc +++ b/test/static_assertions/plugin_bad_const_assignment.cc @@ -15,7 +15,7 @@ * */ -#include "ignition/plugin/PluginPtr.hh" +#include "gz/plugin/PluginPtr.hh" int main() { diff --git a/test/static_assertions/plugin_bad_const_construct.cc b/test/static_assertions/plugin_bad_const_construct.cc index 4972fe71..d211fa07 100644 --- a/test/static_assertions/plugin_bad_const_construct.cc +++ b/test/static_assertions/plugin_bad_const_construct.cc @@ -15,7 +15,7 @@ * */ -#include "ignition/plugin/PluginPtr.hh" +#include "gz/plugin/PluginPtr.hh" int main() { diff --git a/test/static_assertions/plugin_no_base_class.cc b/test/static_assertions/plugin_no_base_class.cc index 46fd23b6..3a1d24fa 100644 --- a/test/static_assertions/plugin_no_base_class.cc +++ b/test/static_assertions/plugin_no_base_class.cc @@ -15,7 +15,7 @@ * */ -#include +#include class A { diff --git a/test/static_assertions/plugin_wrong_base_class.cc b/test/static_assertions/plugin_wrong_base_class.cc index 5385ee56..925684ea 100644 --- a/test/static_assertions/plugin_wrong_base_class.cc +++ b/test/static_assertions/plugin_wrong_base_class.cc @@ -15,7 +15,7 @@ * */ -#include +#include namespace ns { From 1d5a4c987668ed0584ddbf4398dc81b519412c54 Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Fri, 11 Nov 2022 09:20:11 -0600 Subject: [PATCH 8/9] release: Prepare for 1.4.0 release (#108) Signed-off-by: Michael Carroll --- CMakeLists.txt | 2 +- Changelog.md | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f27ce6c1..606f9bf4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR) #============================================================================ # Initialize the project #============================================================================ -project(ignition-plugin1 VERSION 1.3.0) +project(ignition-plugin1 VERSION 1.4.0) #============================================================================ # Find ignition-cmake diff --git a/Changelog.md b/Changelog.md index df4031ad..8337431e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,10 @@ ## Gazebo Plugin 1.x +### Gazebo Plugin 1.3.0 (2022-11-11) + +1. ign -> gz Migrate Ignition Headers : gz-plugin + * [Pull request #101](https://github.com/gazebosim/gz-plugin/pull/101) + ### Gazebo Plugin 1.3.0 (2022-08-15) 1. Remove redundant namespace references From d18c9ddc6df3f684520ba2db6cbd0c24b82dcba9 Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Tue, 15 Nov 2022 08:08:39 -0600 Subject: [PATCH 9/9] Remove redundant CMakeLists Signed-off-by: Michael Carroll --- core/include/CMakeLists.txt | 2 -- loader/include/CMakeLists.txt | 2 -- register/include/CMakeLists.txt | 2 -- 3 files changed, 6 deletions(-) delete mode 100644 core/include/CMakeLists.txt delete mode 100644 loader/include/CMakeLists.txt delete mode 100644 register/include/CMakeLists.txt diff --git a/core/include/CMakeLists.txt b/core/include/CMakeLists.txt deleted file mode 100644 index 58b89f97..00000000 --- a/core/include/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(gz/plugin) -install(DIRECTORY ignition DESTINATION ${IGN_INCLUDE_INSTALL_DIR_FULL}) diff --git a/loader/include/CMakeLists.txt b/loader/include/CMakeLists.txt deleted file mode 100644 index 4b2bdd7b..00000000 --- a/loader/include/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(gz) -install(DIRECTORY ignition DESTINATION ${IGN_INCLUDE_INSTALL_DIR_FULL}) diff --git a/register/include/CMakeLists.txt b/register/include/CMakeLists.txt deleted file mode 100644 index 4b2bdd7b..00000000 --- a/register/include/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(gz) -install(DIRECTORY ignition DESTINATION ${IGN_INCLUDE_INSTALL_DIR_FULL})