1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 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 IGNITION_PLUGIN_PLUGIN_HH_
#define IGNITION_PLUGIN_PLUGIN_HH_
#include <memory>
#include <map>
#include <string>
#include <ignition/utilities/SuppressWarning.hh>
#include <ignition/plugin/Export.hh>
#include <ignition/plugin/Info.hh>
namespace ignition
{
namespace plugin
{
// Forward declaration
namespace detail {
template <class, class> class ComposePlugin;
template <class> 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 <class Interface>
Interface *QueryInterface();
/// \brief const-qualified version of QueryInterface<Interface>()
public: template <class Interface>
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 <class Interface>
IGN_DEPRECATED(0.0)
Interface *QueryInterface(const std::string &/*_interfaceName*/);
/// \brief const-qualified version of
/// QueryInterface<Interface>(std::string)
public: template <class Interface>
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 <class Interface>
std::shared_ptr<Interface> QueryInterfaceSharedPtr();
/// \brief Same as QueryInterfaceSharedPtr<Interface>(), but it returns a
/// std::shared_ptr to a const-qualified Interface.
public: template <class Interface>
std::shared_ptr<const Interface> 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 <class Interface>
IGN_DEPRECATED(0.0)
std::shared_ptr<Interface> QueryInterfaceSharedPtr(
const std::string &/*_interfaceName*/);
/// \brief Same as QueryInterfaceSharedPtr<Interface>(std::string), but
/// it returns a std::shared_ptr to a const-qualified Interface.
public: template <class Interface>
IGN_DEPRECATED(0.0)
std::shared_ptr<const Interface> 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 <class Interface>
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 <class> friend class TemplatePluginPtr;
template <class...> friend class SpecializedPlugin;
template <class, class> friend class detail::ComposePlugin;
template <class> 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<void> &_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<void> &_dlHandlePtr) const;
/// \brief Get a reference to the abstract instance being managed by this
/// wrapper
private: const std::shared_ptr<void> &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<T>. 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<std::string, void*>;
/// \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<Implementation> dataPtr;
IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING
/// \brief Virtual destructor
public: virtual ~Plugin();
};
}
}
#include "ignition/plugin/detail/Plugin.hh"
#endif
|