10 #include <boost/filesystem.hpp> 11 #include <boost/filesystem/operations.hpp> 12 #include <boost/thread/mutex.hpp> 13 #include <pion/config.hpp> 14 #include <pion/error.hpp> 15 #include <pion/plugin.hpp> 28 const std::string plugin::PION_PLUGIN_CREATE(
"pion_create_");
29 const std::string plugin::PION_PLUGIN_DESTROY(
"pion_destroy_");
31 const std::string plugin::PION_PLUGIN_EXTENSION(
".dll");
33 const std::string plugin::PION_PLUGIN_EXTENSION(
".so");
35 const std::string plugin::PION_CONFIG_EXTENSION(
".conf");
36 boost::once_flag plugin::m_instance_flag = BOOST_ONCE_INIT;
37 plugin::config_type *plugin::m_config_ptr = NULL;
42 void plugin::create_plugin_config(
void)
44 static config_type UNIQUE_PION_PLUGIN_CONFIG;
45 m_config_ptr = &UNIQUE_PION_PLUGIN_CONFIG;
49 const std::string& start_path)
51 #if defined(PION_WIN32) && defined(PION_CYGWIN_DIRECTORY) 53 if (! final_path.is_complete() && final_path.has_root_directory()) {
54 final_path = boost::filesystem::path(std::string(PION_CYGWIN_DIRECTORY) + start_path);
61 boost::filesystem::path plugin_path = boost::filesystem::system_complete(dir);
63 if (! boost::filesystem::exists(plugin_path) )
65 config_type& cfg = get_plugin_config();
66 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
67 # if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3 68 cfg.m_plugin_dirs.push_back(plugin_path.string());
70 cfg.m_plugin_dirs.push_back(plugin_path.directory_string());
77 config_type& cfg = get_plugin_config();
78 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
79 cfg.m_plugin_dirs.clear();
86 config_type& cfg = get_plugin_config();
87 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
88 map_type::iterator itr = cfg.m_plugin_map.find(plugin_name);
89 if (itr != cfg.m_plugin_map.end()) {
91 m_plugin_data = itr->second;
98 std::string plugin_file;
114 config_type& cfg = get_plugin_config();
115 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
116 map_type::iterator itr = cfg.m_plugin_map.find(plugin_data.
m_plugin_name);
117 if (itr == cfg.m_plugin_map.end()) {
121 open_plugin(plugin_file, plugin_data);
124 m_plugin_data =
new data_type(plugin_data);
125 cfg.m_plugin_map.insert( std::make_pair(m_plugin_data->
m_plugin_name,
129 m_plugin_data = itr->second;
138 if (m_plugin_data != NULL) {
139 config_type& cfg = get_plugin_config();
140 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
142 if (m_plugin_data != NULL && --m_plugin_data->
m_references == 0) {
152 map_type::iterator itr = cfg.m_plugin_map.find(m_plugin_data->
m_plugin_name);
154 if (itr != cfg.m_plugin_map.end())
155 cfg.m_plugin_map.erase(itr);
158 delete m_plugin_data;
161 m_plugin_data = NULL;
168 config_type& cfg = get_plugin_config();
169 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
170 m_plugin_data =
const_cast<data_type*
>(p.m_plugin_data);
171 if (m_plugin_data != NULL) {
176 bool plugin::find_file(std::string& path_to_file,
const std::string& name,
177 const std::string& extension)
180 if (check_for_file(path_to_file, name,
"", extension))
184 config_type& cfg = get_plugin_config();
185 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
186 for (std::vector<std::string>::iterator i = cfg.m_plugin_dirs.begin();
187 i != cfg.m_plugin_dirs.end(); ++i)
189 if (check_for_file(path_to_file, *i, name, extension))
197 bool plugin::check_for_file(std::string& final_path,
const std::string& start_path,
198 const std::string& name,
const std::string& extension)
201 boost::filesystem::path cygwin_safe_path(start_path);
203 boost::filesystem::path test_path(cygwin_safe_path);
212 if (boost::filesystem::is_regular(test_path)) {
213 # if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3 214 final_path = test_path.string();
216 final_path = test_path.file_string();
225 test_path = boost::filesystem::path(start_path + extension);
230 test_path = cygwin_safe_path /
231 boost::filesystem::path(name + extension);
237 if (boost::filesystem::is_regular(test_path)) {
238 # if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3 239 final_path = test_path.string();
241 final_path = test_path.file_string();
251 void plugin::open_plugin(
const std::string& plugin_file,
259 plugin_data.
m_lib_handle = load_dynamic_library(plugin_file.c_str());
262 const char *error_msg = dlerror();
263 if (error_msg != NULL) {
264 std::string error_str(plugin_file);
266 error_str += error_msg;
270 << error::errinfo_message(error_str) );
285 << error::errinfo_symbol_name(PION_PLUGIN_CREATE + plugin_data.
m_plugin_name) );
296 << error::errinfo_symbol_name(PION_PLUGIN_DESTROY + plugin_data.
m_plugin_name) );
302 return boost::filesystem::basename(boost::filesystem::path(plugin_file));
308 std::vector<std::string>::iterator it;
309 config_type& cfg = get_plugin_config();
310 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
311 for (it = cfg.m_plugin_dirs.begin(); it != cfg.m_plugin_dirs.end(); ++it) {
313 boost::filesystem::directory_iterator end;
314 for (boost::filesystem::directory_iterator it2(*it); it2 != end; ++it2) {
315 if (boost::filesystem::is_regular(*it2)) {
316 if (boost::filesystem::extension(it2->path()) == plugin::PION_PLUGIN_EXTENSION) {
317 # if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3 328 for (map_type::const_iterator itr = cfg.m_plugin_map.begin(); itr != cfg.m_plugin_map.end(); ++itr) {
329 const data_type& plugin_data = *(itr->second);
336 void *plugin::load_dynamic_library(
const std::string& plugin_file)
340 return LoadLibraryA(plugin_file.c_str());
342 return LoadLibrary(plugin_file.c_str());
347 # if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3 348 const boost::filesystem::path full_path = boost::filesystem::absolute(plugin_file);
350 const boost::filesystem::path full_path = boost::filesystem::complete(plugin_file);
355 # if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3 356 return dlopen(full_path.string().c_str(), RTLD_LAZY | RTLD_GLOBAL);
358 return dlopen(full_path.file_string().c_str(), RTLD_LAZY | RTLD_GLOBAL);
363 void plugin::close_dynamic_library(
void *lib_handle)
381 void *plugin::get_library_symbol(
void *lib_handle,
const std::string& symbol)
384 return (
void*)GetProcAddress((HINSTANCE) lib_handle, symbol.c_str());
386 return dlsym(lib_handle, symbol.c_str());
395 config_type& cfg = get_plugin_config();
396 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
397 map_type::iterator itr = cfg.m_plugin_map.find(plugin_name);
398 if (itr == cfg.m_plugin_map.end()) {
405 cfg.m_plugin_map.insert(std::make_pair(plugin_name, plugin_data));
void open_file(const std::string &plugin_file)
exception thrown if we are unable to open a plugin
void grab_data(const plugin &p)
grabs a reference to another plug-in's shared library symbols
void * m_lib_handle
symbol library loaded from a shared object file
static void add_plugin_directory(const std::string &dir)
appends a directory to the plug-in search path
void release_data(void)
releases the plug-in's shared library symbols
static void reset_plugin_directories(void)
clears all directories from the plug-in search path
void * m_create_func
function used to create instances of the plug-in object
exception thrown if a plugin is missing a required symbol
static bool find_plugin_file(std::string &path_to_file, const std::string &name)
std::string m_plugin_name
the name of the plugin (must be unique per process)
exception thrown if a required directory is not found
void * m_destroy_func
function used to destroy instances of the plug-in object
std::string get_plugin_name(void) const
returns the name of the plugin that is currently open
static void check_cygwin_path(boost::filesystem::path &final_path, const std::string &path_string)
unsigned long m_references
number of references to this class
exception thrown if a plugin cannot be found
void open(const std::string &plugin_name)
static void add_static_entry_point(const std::string &plugin_name, void *create_func, void *destroy_func)
static void get_all_plugin_names(std::vector< std::string > &plugin_names)
returns a list of all Plugins found in all Plugin directories