32 #ifndef CLASS_LOADER__CLASS_LOADER_CORE_HPP_ 33 #define CLASS_LOADER__CLASS_LOADER_CORE_HPP_ 35 #include <boost/thread/recursive_mutex.hpp> 43 #include "Poco/SharedLibrary.h" 57 namespace class_loader_private
65 typedef std::map<ClassName, class_loader_private::AbstractMetaObjectBase *>
FactoryMap;
67 typedef std::pair<LibraryPath, Poco::SharedLibrary *>
LibraryPair;
126 template<
typename Base>
161 template<
typename Derived,
typename Base>
162 void registerPlugin(
const std::string & class_name,
const std::string & base_class_name)
168 "class_loader.class_loader_private: " 169 "Registering plugin factory for class = %s, ClassLoader* = %p and library name %s.",
175 "class_loader.impl: ALERT!!! " 176 "A library containing plugins has been opened through a means other than through the " 177 "class_loader or pluginlib package. " 178 "This can happen if you build plugin libraries that contain more than just plugins " 179 "(i.e. normal code your app links against). " 180 "This inherently will trigger a dlopen() prior to main() and cause problems as class_loader " 181 "is not aware of plugin factories that autoregister under the hood. " 182 "The class_loader package can compensate, but you may run into namespace collision problems " 183 "(e.g. if you have the same plugin class in two different libraries and you load them both " 184 "at the same time). " 185 "The biggest problem is that library can now no longer be safely unloaded as the " 186 "ClassLoader does not know when non-plugin code is still in use. " 187 "In fact, no ClassLoader instance in your application will be unable to unload any library " 188 "once a non-pure one has been opened. " 189 "Please refactor your code to isolate plugins into their own libraries.");
202 FactoryMap & factoryMap = getFactoryMapForBaseClass<Base>();
203 if (factoryMap.find(class_name) != factoryMap.end()) {
205 "class_loader.impl: SEVERE WARNING!!! " 206 "A namespace collision has occured with plugin factory for class %s. " 207 "New factory will OVERWRITE existing one. " 208 "This situation occurs when libraries containing plugins are directly linked against an " 209 "executable (the one running right now generating this message). " 210 "Please separate plugins out into their own library or just don't link against the library " 211 "and use either class_loader::ClassLoader/MultiLibraryClassLoader to open.",
214 factoryMap[class_name] = new_factory;
218 "class_loader.class_loader_private: " 219 "Registration of %s complete (Metaobject Address = %p)",
220 class_name.c_str(), new_factory);
229 template<
typename Base>
235 FactoryMap & factoryMap = getFactoryMapForBaseClass<Base>();
236 if (factoryMap.find(derived_class_name) != factoryMap.end()) {
238 factoryMap[derived_class_name]);
241 "class_loader.class_loader_private: No metaobject exists for class type %s.",
242 derived_class_name.c_str());
247 if (factory != NULL && factory->
isOwnedBy(loader)) {
252 if (factory && factory->
isOwnedBy(NULL)) {
254 "class_loader.impl: ALERT!!! " 255 "A metaobject (i.e. factory) exists for desired class, but has no owner. " 256 "This implies that the library containing the class was dlopen()ed by means other than " 257 "through the class_loader interface. " 258 "This can happen if you build plugin libraries that contain more than just plugins " 259 "(i.e. normal code your app links against) -- that intrinsically will trigger a dlopen() " 261 "You should isolate your plugins into their own library, otherwise it will not be " 262 "possible to shutdown the library!");
267 "Could not create instance of type " + derived_class_name));
272 "class_loader.class_loader_private: " 273 "Created instance of type %s and object pointer = %p",
274 (
typeid(obj).name()), obj);
284 template<
typename Base>
289 FactoryMap & factory_map = getFactoryMapForBaseClass<Base>();
290 std::vector<std::string> classes;
291 std::vector<std::string> classes_with_no_owner;
293 for (FactoryMap::const_iterator itr = factory_map.begin(); itr != factory_map.end(); ++itr) {
296 classes.push_back(itr->first);
298 classes_with_no_owner.push_back(itr->first);
304 classes.insert(classes.end(), classes_with_no_owner.begin(), classes_with_no_owner.end());
348 #endif // CLASS_LOADER__CLASS_LOADER_CORE_HPP_ #define CONSOLE_BRIDGE_logWarn(fmt,...)
std::vector< std::string > getAllLibrariesUsedByClassLoader(const ClassLoader *loader)
This function returns the names of all libraries in use by a given class loader.
bool hasANonPurePluginLibraryBeenOpened()
Indicates if a library containing more than just plugins has been opened by the running process...
boost::recursive_mutex & getPluginBaseToFactoryMapMapMutex()
std::map< BaseClassName, FactoryMap > BaseToFactoryMapMap
boost::recursive_mutex & getLoadedLibraryVectorMutex()
To provide thread safety, all exposed plugin functions can only be run serially by multiple threads...
ClassLoader * getCurrentlyActiveClassLoader()
Gets the ClassLoader currently in scope which used when a library is being loaded.
BaseToFactoryMapMap & getGlobalPluginBaseToFactoryMapMap()
Gets a handle to a global data structure that holds a map of base class names (Base class describes p...
std::string getCurrentlyLoadingLibraryName()
When a library is being loaded, in order for factories to know which library they are being associate...
Base * createInstance(const std::string &derived_class_name, ClassLoader *loader)
This function creates an instance of a plugin class given the derived name of the class and returns a...
void loadLibrary(const std::string &library_path, ClassLoader *loader)
Loads a library into memory if it has not already been done so. Attempting to load an already loaded ...
#define CONSOLE_BRIDGE_logDebug(fmt,...)
void setCurrentlyLoadingLibraryName(const std::string &library_name)
When a library is being loaded, in order for factories to know which library they are being associate...
An exception class thrown when class_loader is unable to create a plugin.
This class allows loading and unloading of dynamically linked libraries which contain class definitio...
void unloadLibrary(const std::string &library_path, ClassLoader *loader)
Unloads a library if it loaded in memory and cleans up its corresponding class factories. If it is not loaded, the function has no effect.
std::vector< AbstractMetaObjectBase * > MetaObjectVector
LibraryVector & getLoadedLibraryVector()
Gets a handle to a list of open libraries in the form of LibraryPairs which encode the library path+n...
std::vector< std::string > getAvailableClasses(ClassLoader *loader)
This function returns all the available class_loader in the plugin system that are derived from Base ...
std::vector< LibraryPair > LibraryVector
void setCurrentlyActiveClassLoader(ClassLoader *loader)
Sets the ClassLoader currently in scope which used when a library is being loaded.
void registerPlugin(const std::string &class_name, const std::string &base_class_name)
This function is called by the CLASS_LOADER_REGISTER_CLASS macro in plugin_register_macro.h to register factories. Classes that use that macro will cause this function to be invoked when the library is loaded. The function will create a MetaObject (i.e. factory) for the corresponding Derived class and insert it into the appropriate FactoryMap in the global Base-to-FactoryMap map. Note that the passed class_name is the literal class name and not the mangled version.
bool isLibraryLoaded(const std::string &library_path, ClassLoader *loader)
Indicates if passed library loaded within scope of a ClassLoader. The library maybe loaded in memory...
void printDebugInfoToScreen()
FactoryMap & getFactoryMapForBaseClass(const std::string &typeid_base_class_name)
This function extracts a reference to the FactoryMap for appropriate base class out of the global plu...
std::pair< LibraryPath, Poco::SharedLibrary * > LibraryPair
#define CONSOLE_BRIDGE_logError(fmt,...)
bool isLibraryLoadedByAnybody(const std::string &library_path)
Indicates if passed library has been loaded by ANY ClassLoader.
std::map< ClassName, class_loader_private::AbstractMetaObjectBase * > FactoryMap
std::string BaseClassName