0001-Added-a-plugin-system-in-src-rsc-plugins-.-h-cpp.patch
src/CMakeLists.txt | ||
---|---|---|
31 | 31 |
"rsc/misc/*.cpp" |
32 | 32 |
"rsc/runtime/*.cpp" |
33 | 33 |
"rsc/patterns/*.cpp" |
34 |
"rsc/threading/*.cpp") |
|
34 |
"rsc/threading/*.cpp" |
|
35 |
"rsc/plugins/*.cpp") |
|
35 | 36 |
SET(SOURCES ${SOURCES} |
36 | 37 |
rsc/debug/DebugTools.cpp |
37 | 38 |
rsc/subprocess/Subprocess.cpp |
... | ... | |
45 | 46 |
"rsc/runtime/*.h" |
46 | 47 |
"rsc/patterns/*.h" |
47 | 48 |
"rsc/patterns/detail/*.h" |
48 |
"rsc/threading/*.h") |
|
49 |
"rsc/threading/*.h" |
|
50 |
"rsc/plugins/*.h") |
|
49 | 51 |
SET(HEADERS ${HEADERS} |
50 | 52 |
rsc/debug/DebugTools.h |
51 | 53 |
rsc/subprocess/Subprocess.h |
... | ... | |
80 | 82 |
ENDIF() |
81 | 83 | |
82 | 84 |
ADD_LIBRARY(${RSC_NAME} SHARED ${SOURCES} ${HEADERS}) |
83 |
TARGET_LINK_LIBRARIES(${RSC_NAME} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) |
|
85 |
TARGET_LINK_LIBRARIES(${RSC_NAME} ${Boost_LIBRARIES} |
|
86 |
${CMAKE_THREAD_LIBS_INIT} |
|
87 |
dl) |
|
84 | 88 |
SET_TARGET_PROPERTIES(${RSC_NAME} |
85 | 89 |
PROPERTIES |
86 | 90 |
VERSION ${SO_VERSION}) |
src/rsc/plugins/Configurator.cpp | ||
---|---|---|
1 |
/* ============================================================ |
|
2 |
* |
|
3 |
* This file is part of the RSB project. |
|
4 |
* |
|
5 |
* Copyright (C) 2012 Jan Moringen <jmoringe@techfak.uni-bielefeld.de> |
|
6 |
* |
|
7 |
* This file may be licensed under the terms of the |
|
8 |
* GNU Lesser General Public License Version 3 (the ``LGPL''), |
|
9 |
* or (at your option) any later version. |
|
10 |
* |
|
11 |
* Software distributed under the License is distributed |
|
12 |
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
|
13 |
* express or implied. See the LGPL for the specific language |
|
14 |
* governing rights and limitations. |
|
15 |
* |
|
16 |
* You should have received a copy of the LGPL along with this |
|
17 |
* program. If not, go to http://www.gnu.org/licenses/lgpl.html |
|
18 |
* or write to the Free Software Foundation, Inc., |
|
19 |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
20 |
* |
|
21 |
* The development of this software was supported by: |
|
22 |
* CoR-Lab, Research Institute for Cognition and Robotics |
|
23 |
* Bielefeld University |
|
24 |
* |
|
25 |
* ============================================================ */ |
|
26 | ||
27 |
#include "Configurator.h" |
|
28 | ||
29 |
#include <boost/format.hpp> |
|
30 | ||
31 |
#include <boost/tokenizer.hpp> |
|
32 | ||
33 |
#include "../runtime/ContainerIO.h" |
|
34 | ||
35 |
#include "../logging/LoggerFactory.h" |
|
36 | ||
37 |
using namespace std; |
|
38 | ||
39 |
using namespace boost; |
|
40 |
using namespace boost::filesystem; |
|
41 | ||
42 |
namespace rsc { |
|
43 |
namespace plugins { |
|
44 | ||
45 |
Configurator::Configurator(const vector<path>& defaultPath) |
|
46 |
: logger(logging::LoggerFactory::getInstance() |
|
47 |
.getLogger("rsc.plugins.Configurator")), |
|
48 |
manager(Manager::getInstance()), |
|
49 |
pathSet(false), |
|
50 |
defaultPath(defaultPath) { |
|
51 |
} |
|
52 | ||
53 |
Configurator::~Configurator() { |
|
54 |
// If a searchpath has not been set via configuration options, use |
|
55 |
// the default. |
|
56 |
if (!this->pathSet) { |
|
57 |
RSCINFO(this->logger, "No searchpath configured; using default: " |
|
58 |
<< this->defaultPath); |
|
59 |
addDefaultPath(); |
|
60 |
} |
|
61 | ||
62 |
// Load all requested plugins. |
|
63 |
for (vector<string>::const_iterator it = this->load.begin(); |
|
64 |
it != this->load.end(); ++it) { |
|
65 |
string name = *it; |
|
66 |
try { |
|
67 |
this->manager.getPlugin(name)->load(); |
|
68 |
} catch (const std::exception& e) { |
|
69 |
throw runtime_error(str(format("Failed to load plugin `%1%' as requested via configuration: %2%") |
|
70 |
% name |
|
71 |
% e.what())); |
|
72 |
} |
|
73 |
} |
|
74 |
} |
|
75 | ||
76 |
void Configurator::handleOption(const vector<string>& key, |
|
77 |
const string& value) { |
|
78 |
RSCDEBUG(this->logger, "Processing option " << key << " = `" << value << "'"); |
|
79 | ||
80 |
// Ignore other options. |
|
81 |
if (!((key.size() == 3) |
|
82 |
&& (key[0] == "plugins") |
|
83 |
&& (key[1] == "cpp"))) { |
|
84 |
return; |
|
85 |
} |
|
86 | ||
87 |
// Process plugins.cpp.{path,load} options. |
|
88 |
if (key[2] == "path") { |
|
89 |
// Split value at ":" tokens. Each substring is a searchpath |
|
90 |
// entry. |
|
91 |
vector<string> paths = splitValue(value); |
|
92 | ||
93 |
// Add all specified paths. The empty string, produced by "::" |
|
94 |
// means that the default searchpath should be spliced in. |
|
95 |
for (vector<string>::const_iterator it = paths.begin(); |
|
96 |
it != paths.end(); ++it) { |
|
97 |
string path = *it; |
|
98 |
try { |
|
99 |
if (path.empty()) { |
|
100 |
path = "<default path>"; // for exception message |
|
101 |
addDefaultPath(); |
|
102 |
} else { |
|
103 |
this->manager.addPath(path); |
|
104 |
} |
|
105 |
} catch (const std::exception& e) { |
|
106 |
throw runtime_error(str(format("Failed to add path `%1%' as requested via configuration: %2%") |
|
107 |
% path |
|
108 |
% e.what())); |
|
109 |
} |
|
110 |
} |
|
111 | ||
112 |
this->pathSet = true; |
|
113 |
} else if (key[2] == "load") { |
|
114 |
vector<string> temp = splitValue(value); |
|
115 |
copy(temp.begin(), temp.end(), back_inserter(this->load)); |
|
116 |
} else { |
|
117 |
throw invalid_argument(str(format("Invalid option key `%1%'; plugin related option keys are `path' and `load'.") |
|
118 |
% key)); |
|
119 |
} |
|
120 |
} |
|
121 | ||
122 |
void Configurator::addDefaultPath() { |
|
123 |
for (vector<path>::const_iterator it = this->defaultPath.begin(); |
|
124 |
it != this->defaultPath.end(); ++it) { |
|
125 |
this->manager.addPath(*it); |
|
126 |
} |
|
127 |
} |
|
128 | ||
129 |
vector<string> Configurator::splitValue(const string& value) const { |
|
130 |
vector<string> result; |
|
131 |
boost::escaped_list_separator<char> sep('\\', ':'); |
|
132 |
boost::tokenizer< boost::escaped_list_separator<char> > tok(value, sep); |
|
133 |
copy(tok.begin(), tok.end(), back_inserter(result)); |
|
134 |
return result; |
|
135 |
} |
|
136 | ||
137 |
} |
|
138 |
} |
src/rsc/plugins/Configurator.h | ||
---|---|---|
1 |
/* ============================================================ |
|
2 |
* |
|
3 |
* This file is part of the RSB project. |
|
4 |
* |
|
5 |
* Copyright (C) 2012 Jan Moringen <jmoringe@techfak.uni-bielefeld.de> |
|
6 |
* |
|
7 |
* This file may be licensed under the terms of the |
|
8 |
* GNU Lesser General Public License Version 3 (the ``LGPL''), |
|
9 |
* or (at your option) any later version. |
|
10 |
* |
|
11 |
* Software distributed under the License is distributed |
|
12 |
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
|
13 |
* express or implied. See the LGPL for the specific language |
|
14 |
* governing rights and limitations. |
|
15 |
* |
|
16 |
* You should have received a copy of the LGPL along with this |
|
17 |
* program. If not, go to http://www.gnu.org/licenses/lgpl.html |
|
18 |
* or write to the Free Software Foundation, Inc., |
|
19 |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
20 |
* |
|
21 |
* The development of this software was supported by: |
|
22 |
* CoR-Lab, Research Institute for Cognition and Robotics |
|
23 |
* Bielefeld University |
|
24 |
* |
|
25 |
* ============================================================ */ |
|
26 | ||
27 |
#pragma once |
|
28 | ||
29 |
#include <string> |
|
30 |
#include <vector> |
|
31 | ||
32 |
#include "../config/OptionHandler.h" |
|
33 |
#include "../logging/Logger.h" |
|
34 | ||
35 |
#include "Manager.h" |
|
36 | ||
37 |
#include <rsc/rscexports.h> |
|
38 | ||
39 |
namespace rsc { |
|
40 |
namespace plugins { |
|
41 | ||
42 |
/** |
|
43 |
* Instances of this class can be used to configure the #Manager based |
|
44 |
* on configuration options. |
|
45 |
* |
|
46 |
* Note that the configuration may be performed when the object is |
|
47 |
* destructed. |
|
48 |
* |
|
49 |
* @author jmoringe |
|
50 |
*/ |
|
51 |
class RSC_EXPORT Configurator : public config::OptionHandler { |
|
52 |
public: |
|
53 |
/** |
|
54 |
* Constructs a @c Configurator with default plugin search path @a |
|
55 |
* defaultPath. |
|
56 |
* |
|
57 |
* @param defaultPath A #vector of #boost::filesystem::path |
|
58 |
* objects which should be installed as plugin |
|
59 |
* search path in case no plugin search path is |
|
60 |
* configured. |
|
61 |
*/ |
|
62 |
Configurator(const std::vector<boost::filesystem::path>& defaultPath); |
|
63 |
virtual ~Configurator(); |
|
64 | ||
65 |
private: |
|
66 |
logging::LoggerPtr logger; |
|
67 | ||
68 |
Manager& manager; |
|
69 | ||
70 |
bool pathSet; |
|
71 |
std::vector<boost::filesystem::path> defaultPath; |
|
72 |
std::vector<std::string> load; |
|
73 | ||
74 |
void handleOption(const std::vector<std::string>& key, |
|
75 |
const std::string& value); |
|
76 | ||
77 |
void addDefaultPath(); |
|
78 | ||
79 |
std::vector<std::string> splitValue(const std::string& value) const; |
|
80 |
}; |
|
81 | ||
82 |
} |
|
83 |
} |
src/rsc/plugins/Manager.cpp | ||
---|---|---|
1 |
/* ============================================================ |
|
2 |
* |
|
3 |
* This file is part of the RSB project. |
|
4 |
* |
|
5 |
* Copyright (C) 2012 Jan Moringen <jmoringe@techfak.uni-bielefeld.de> |
|
6 |
* |
|
7 |
* This file may be licensed under the terms of the |
|
8 |
* GNU Lesser General Public License Version 3 (the ``LGPL''), |
|
9 |
* or (at your option) any later version. |
|
10 |
* |
|
11 |
* Software distributed under the License is distributed |
|
12 |
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
|
13 |
* express or implied. See the LGPL for the specific language |
|
14 |
* governing rights and limitations. |
|
15 |
* |
|
16 |
* You should have received a copy of the LGPL along with this |
|
17 |
* program. If not, go to http://www.gnu.org/licenses/lgpl.html |
|
18 |
* or write to the Free Software Foundation, Inc., |
|
19 |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
20 |
* |
|
21 |
* The development of this software was supported by: |
|
22 |
* CoR-Lab, Research Institute for Cognition and Robotics |
|
23 |
* Bielefeld University |
|
24 |
* |
|
25 |
* ============================================================ */ |
|
26 | ||
27 |
#include "Manager.h" |
|
28 | ||
29 |
#include <stdexcept> |
|
30 |
#include <algorithm> |
|
31 | ||
32 |
#include <boost/filesystem/operations.hpp> |
|
33 |
#include <boost/regex.hpp> |
|
34 |
#include <boost/format.hpp> |
|
35 | ||
36 |
#include "../runtime/NoSuchObject.h" |
|
37 |
#include "../logging/LoggerFactory.h" |
|
38 | ||
39 |
using namespace std; |
|
40 | ||
41 |
using namespace boost; |
|
42 |
using namespace boost::filesystem; |
|
43 | ||
44 |
namespace rsc { |
|
45 |
namespace plugins { |
|
46 | ||
47 |
Manager::Manager() |
|
48 |
: logger(logging::LoggerFactory::getInstance() |
|
49 |
.getLogger("rsc.plugins.Manager")) { |
|
50 |
} |
|
51 | ||
52 |
Manager::~Manager() { |
|
53 |
} |
|
54 | ||
55 |
vector<path> Manager::getPath() const { |
|
56 |
return this->path; |
|
57 |
} |
|
58 | ||
59 |
void Manager::addPath(const boost::filesystem::path& path) { |
|
60 |
// Ignore duplicates. |
|
61 |
if (find(this->path.begin(), this->path.end(), path) |
|
62 |
!= this->path.end()) { |
|
63 |
return; |
|
64 |
} |
|
65 | ||
66 |
// Search specified directory for plugins. |
|
67 |
RSCINFO(this->logger, "Adding path `" << path << "'"); |
|
68 |
for (directory_iterator it = directory_iterator(path); |
|
69 |
it != directory_iterator(); ++it) { |
|
70 |
if (!is_regular_file(it->path())) { |
|
71 |
continue; |
|
72 |
} |
|
73 | ||
74 |
// Extract the plugin name from the library name. |
|
75 |
string name = it->path().stem(); |
|
76 |
// Strip leading "lib" |
|
77 |
if (name.substr(0, 3) == "lib") { |
|
78 |
name = name.substr(3); |
|
79 |
} |
|
80 |
// Strip trailing ".so*" |
|
81 |
for (unsigned int i = 0; i <= 2; ++i) { |
|
82 |
if (name.substr(name.size() - (3 + i)).substr(0, 3) == ".so") { |
|
83 |
name = name.substr(0, name.size() - (3 + i)); |
|
84 |
break; |
|
85 |
} |
|
86 |
} |
|
87 |
boost::filesystem::path library = it->path(); |
|
88 | ||
89 |
// If there is not yet an entry for the given name, add a new |
|
90 |
// plugin entry. Otherwise, ignore the plugin. This logic |
|
91 |
// implements precedence of searchpath entries. |
|
92 |
RSCINFO(this->logger, "Found plugin `" |
|
93 |
<< name << "' [" << library << "]"); |
|
94 |
if (this->plugins.find(name) == this->plugins.end()) { |
|
95 |
this->plugins[name] = Plugin::create(name, library.native_file_string()); |
|
96 |
} |
|
97 |
} |
|
98 |
this->path.push_back(path); |
|
99 |
} |
|
100 | ||
101 |
set<PluginPtr> Manager::getPlugins() const { |
|
102 |
set<PluginPtr> result; |
|
103 | ||
104 |
for (PluginMap::const_iterator it = this->plugins.begin(); |
|
105 |
it != this->plugins.end(); ++it) { |
|
106 |
result.insert(it->second); |
|
107 |
} |
|
108 |
return result; |
|
109 |
} |
|
110 | ||
111 |
PluginPtr Manager::getPlugin(const string& name) const { |
|
112 |
PluginMap::const_iterator it; |
|
113 |
if ((it = this->plugins.find(name)) == this->plugins.end()) { |
|
114 |
throw runtime::NoSuchObject(name); |
|
115 |
} |
|
116 |
return it->second; |
|
117 |
} |
|
118 | ||
119 |
} |
|
120 |
} |
src/rsc/plugins/Manager.h | ||
---|---|---|
1 |
/* ============================================================ |
|
2 |
* |
|
3 |
* This file is part of the RSB project. |
|
4 |
* |
|
5 |
* Copyright (C) 2012 Jan Moringen <jmoringe@techfak.uni-bielefeld.de> |
|
6 |
* |
|
7 |
* This file may be licensed under the terms of the |
|
8 |
* GNU Lesser General Public License Version 3 (the ``LGPL''), |
|
9 |
* or (at your option) any later version. |
|
10 |
* |
|
11 |
* Software distributed under the License is distributed |
|
12 |
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
|
13 |
* express or implied. See the LGPL for the specific language |
|
14 |
* governing rights and limitations. |
|
15 |
* |
|
16 |
* You should have received a copy of the LGPL along with this |
|
17 |
* program. If not, go to http://www.gnu.org/licenses/lgpl.html |
|
18 |
* or write to the Free Software Foundation, Inc., |
|
19 |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
20 |
* |
|
21 |
* The development of this software was supported by: |
|
22 |
* CoR-Lab, Research Institute for Cognition and Robotics |
|
23 |
* Bielefeld University |
|
24 |
* |
|
25 |
* ============================================================ */ |
|
26 | ||
27 |
#pragma once |
|
28 | ||
29 |
#include <vector> |
|
30 |
#include <set> |
|
31 |
#include <map> |
|
32 | ||
33 |
#include <boost/filesystem/path.hpp> |
|
34 | ||
35 |
#include "../patterns/Singleton.h" |
|
36 | ||
37 |
#include "../logging/Logger.h" |
|
38 | ||
39 |
#include "Plugin.h" |
|
40 | ||
41 |
#include "rsc/rscexports.h" |
|
42 | ||
43 |
namespace rsc { |
|
44 |
namespace plugins { |
|
45 | ||
46 |
/** |
|
47 |
* The singleton instance of this class manages plugin search path |
|
48 |
* entries and plugins. |
|
49 |
* |
|
50 |
* Plugins can be retrieved as #Plugin objects, loaded and unloaded. |
|
51 |
* |
|
52 |
* @author jmoringe |
|
53 |
*/ |
|
54 |
class RSC_EXPORT Manager : public patterns::Singleton<Manager> { |
|
55 |
public: |
|
56 |
virtual ~Manager(); |
|
57 | ||
58 |
/** |
|
59 |
* Returns the current plugin search path. |
|
60 |
* |
|
61 |
* @return A #std::vector of #boost::filesystem::path objects. |
|
62 |
*/ |
|
63 |
std::vector<boost::filesystem::path> getPath() const; |
|
64 | ||
65 |
/** |
|
66 |
* Adds @a path to the list of search path entries. |
|
67 |
* |
|
68 |
* @param path A #boost::filesystem::path designating a directory |
|
69 |
* which should be searched for plugins. |
|
70 |
* @throw exception If @a path does not exist or is otherwise |
|
71 |
* inaccessible. |
|
72 |
*/ |
|
73 |
void addPath(const boost::filesystem::path& path); |
|
74 | ||
75 |
/** |
|
76 |
* Returns the set of known plugins. |
|
77 |
* |
|
78 |
* @return A copy of the set of known plugins. |
|
79 |
*/ |
|
80 |
std::set<PluginPtr> getPlugins() const; |
|
81 | ||
82 |
/** |
|
83 |
* Return the plugin designated by @a name. |
|
84 |
* |
|
85 |
* @param name The name of the plugin which should be returned. |
|
86 |
* @return The requested plugin. |
|
87 |
* @throw NoSuchObject If @a name does not designate a plugin. |
|
88 |
*/ |
|
89 |
PluginPtr getPlugin(const std::string& name) const; |
|
90 |
private: |
|
91 |
friend class patterns::Singleton<Manager>; |
|
92 | ||
93 |
typedef std::vector<boost::filesystem::path> PathList; |
|
94 |
typedef std::map<std::string, PluginPtr> PluginMap; |
|
95 | ||
96 |
logging::LoggerPtr logger; |
|
97 | ||
98 |
PathList path; |
|
99 |
PluginMap plugins; |
|
100 | ||
101 |
Manager(); |
|
102 |
}; |
|
103 | ||
104 |
} |
|
105 |
} |
src/rsc/plugins/Plugin.cpp | ||
---|---|---|
1 |
/* ============================================================ |
|
2 |
* |
|
3 |
* This file is part of the RSB project. |
|
4 |
* |
|
5 |
* Copyright (C) 2012 Jan Moringen <jmoringe@techfak.uni-bielefeld.de> |
|
6 |
* |
|
7 |
* This file may be licensed under the terms of the |
|
8 |
* GNU Lesser General Public License Version 3 (the ``LGPL''), |
|
9 |
* or (at your option) any later version. |
|
10 |
* |
|
11 |
* Software distributed under the License is distributed |
|
12 |
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
|
13 |
* express or implied. See the LGPL for the specific language |
|
14 |
* governing rights and limitations. |
|
15 |
* |
|
16 |
* You should have received a copy of the LGPL along with this |
|
17 |
* program. If not, go to http://www.gnu.org/licenses/lgpl.html |
|
18 |
* or write to the Free Software Foundation, Inc., |
|
19 |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
20 |
* |
|
21 |
* The development of this software was supported by: |
|
22 |
* CoR-Lab, Research Institute for Cognition and Robotics |
|
23 |
* Bielefeld University |
|
24 |
* |
|
25 |
* ============================================================ */ |
|
26 | ||
27 |
#include "Plugin.h" |
|
28 | ||
29 |
#include <errno.h> |
|
30 |
#include <string.h> |
|
31 |
#include <dlfcn.h> |
|
32 | ||
33 |
#include <stdexcept> |
|
34 | ||
35 |
#include <boost/format.hpp> |
|
36 | ||
37 |
#include "../logging/Logger.h" |
|
38 |
#include "../logging/LoggerFactory.h" |
|
39 | ||
40 |
using namespace std; |
|
41 | ||
42 |
using namespace boost; |
|
43 | ||
44 |
namespace rsc { |
|
45 |
namespace plugins { |
|
46 | ||
47 |
const std::string PLUGIN_INIT_SYMBOL = "rsc_plugin_init"; |
|
48 |
const std::string PLUGIN_SHUTDOWN_SYMBOL = "rsc_plugin_shutdown"; |
|
49 | ||
50 |
class Impl { |
|
51 |
public: |
|
52 |
Impl(const std::string& name, |
|
53 |
const std::string& library) |
|
54 |
: logger(logging::LoggerFactory::getInstance() |
|
55 |
.getLogger(str((format("rsc.plugins.Plugin[%1%]") |
|
56 |
% name)))), |
|
57 |
name(name), library(library), |
|
58 |
handle(NULL) { |
|
59 |
} |
|
60 | ||
61 |
const string& getName() const { |
|
62 |
return this->name; |
|
63 |
} |
|
64 | ||
65 |
void load() { |
|
66 |
RSCINFO(this->logger, "Trying to load library `" << this->library << "'"); |
|
67 | ||
68 |
// Load the library containing the plugin. |
|
69 |
if (!(this->handle = dlopen(this->library.c_str(), RTLD_NOW))) { |
|
70 |
char buffer[4096]; |
|
71 |
const char* result = strerror_r(errno, buffer, 4096); |
|
72 |
throw runtime_error(str(format("Failed to load plugin `%1%' from shared object `%2%': %3%.") |
|
73 |
% this->name |
|
74 |
% this->library |
|
75 |
% (result ? result : "<unknown error>"))); |
|
76 |
} |
|
77 | ||
78 |
// Lookup init and shutdown functions in the plugin library. |
|
79 |
this->init |
|
80 |
= reinterpret_cast<InitFunction>(resolveSymbol(PLUGIN_INIT_SYMBOL)); |
|
81 |
this->shutdown |
|
82 |
= reinterpret_cast<ShutdownFunction>(resolveSymbol(PLUGIN_SHUTDOWN_SYMBOL)); |
|
83 | ||
84 |
// Initialize the plugin. |
|
85 |
RSCINFO(this->logger, "Initializing"); |
|
86 |
try { |
|
87 |
this->init(); |
|
88 |
} catch (const std::exception& e) { |
|
89 |
throw runtime_error(str(format("Plugin `%1%' failed to initialize: %2%") |
|
90 |
% this->name |
|
91 |
% e.what())); |
|
92 |
} catch (...) { |
|
93 |
throw runtime_error(str(format("Plugin `%1%' failed to initialize due to unknown error.") |
|
94 |
% this->name)); |
|
95 |
} |
|
96 |
} |
|
97 | ||
98 |
void unload() { |
|
99 |
// Shut the plugin down. |
|
100 |
RSCINFO(this->logger, "Shutting down"); |
|
101 |
try { |
|
102 |
this->shutdown(); |
|
103 |
} catch (const std::exception& e) { |
|
104 |
throw runtime_error(str(format("Plugin `%1%' failed to shutdown: %2%") |
|
105 |
% this->name |
|
106 |
% e.what())); |
|
107 |
} catch (...) { |
|
108 |
throw runtime_error(str(format("Plugin `%1%' failed to shutdown due to unknown error.") |
|
109 |
% this->name)); |
|
110 |
} |
|
111 |
} |
|
112 |
private: |
|
113 |
typedef void (*InitFunction)(); |
|
114 |
typedef void (*ShutdownFunction)(); |
|
115 | ||
116 |
rsc::logging::LoggerPtr logger; |
|
117 | ||
118 |
string name; |
|
119 |
string library; |
|
120 | ||
121 |
void* handle; |
|
122 |
InitFunction init; |
|
123 |
ShutdownFunction shutdown; |
|
124 | ||
125 |
void* resolveSymbol(const string& name) { |
|
126 |
RSCINFO(this->logger, "Resolving symbol `" |
|
127 |
<< name |
|
128 |
<< "' in library `" << this->library << "'"); |
|
129 | ||
130 |
assert(this->handle); |
|
131 | ||
132 |
void *address; |
|
133 |
if (!(address = dlsym(this->handle, name.c_str()))) { |
|
134 |
char buffer[4096]; |
|
135 |
const char* result = strerror_r(errno, buffer, 4096); |
|
136 |
throw runtime_error(str(format("Plugin `%1%' failed to define function `%2%': %3%") |
|
137 |
% this->name |
|
138 |
% name |
|
139 |
% (result ? result : "<unknown error>"))); |
|
140 |
} |
|
141 |
return address; |
|
142 |
} |
|
143 |
}; |
|
144 | ||
145 |
Plugin::Plugin(Impl* impl) |
|
146 |
: impl(impl) { |
|
147 |
} |
|
148 | ||
149 |
Plugin::~Plugin() { |
|
150 |
} |
|
151 | ||
152 |
const string& Plugin::getName() const { |
|
153 |
return this->impl->getName(); |
|
154 |
} |
|
155 | ||
156 |
void Plugin::load() { |
|
157 |
this->impl->load(); |
|
158 |
} |
|
159 | ||
160 |
PluginPtr Plugin::create(const std::string& name, const std::string& library) { |
|
161 |
return PluginPtr(new Plugin(new Impl(name, library))); |
|
162 |
} |
|
163 | ||
164 |
} |
|
165 |
} |
src/rsc/plugins/Plugin.h | ||
---|---|---|
1 |
/* ============================================================ |
|
2 |
* |
|
3 |
* This file is part of the RSB project. |
|
4 |
* |
|
5 |
* Copyright (C) 2012 Jan Moringen <jmoringe@techfak.uni-bielefeld.de> |
|
6 |
* |
|
7 |
* This file may be licensed under the terms of the |
|
8 |
* GNU Lesser General Public License Version 3 (the ``LGPL''), |
|
9 |
* or (at your option) any later version. |
|
10 |
* |
|
11 |
* Software distributed under the License is distributed |
|
12 |
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
|
13 |
* express or implied. See the LGPL for the specific language |
|
14 |
* governing rights and limitations. |
|
15 |
* |
|
16 |
* You should have received a copy of the LGPL along with this |
|
17 |
* program. If not, go to http://www.gnu.org/licenses/lgpl.html |
|
18 |
* or write to the Free Software Foundation, Inc., |
|
19 |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
20 |
* |
|
21 |
* The development of this software was supported by: |
|
22 |
* CoR-Lab, Research Institute for Cognition and Robotics |
|
23 |
* Bielefeld University |
|
24 |
* |
|
25 |
* ============================================================ */ |
|
26 | ||
27 |
#pragma once |
|
28 | ||
29 |
#include <string> |
|
30 | ||
31 |
#include <boost/noncopyable.hpp> |
|
32 |
#include <boost/scoped_ptr.hpp> |
|
33 |
#include <boost/shared_ptr.hpp> |
|
34 | ||
35 |
#include "rsc/rscexports.h" |
|
36 | ||
37 |
namespace rsc { |
|
38 |
namespace plugins { |
|
39 | ||
40 |
extern const std::string PLUGIN_INIT_SYMBOL; |
|
41 |
extern const std::string PLUGIN_SHUTDOWN_SYMBOL; |
|
42 | ||
43 |
class Impl; |
|
44 | ||
45 |
/** |
|
46 |
* Instances of this class represent pieces of RSB-related |
|
47 |
* functionality which can be loaded into a program at runtime. |
|
48 |
* |
|
49 |
* @author jmoringe |
|
50 |
*/ |
|
51 |
class RSC_EXPORT Plugin : boost::noncopyable { |
|
52 |
public: |
|
53 |
virtual ~Plugin(); |
|
54 | ||
55 |
/** |
|
56 |
* Returns the name of the plugin. |
|
57 |
* |
|
58 |
* @return The name of the plugin. |
|
59 |
*/ |
|
60 |
const std::string& getName() const; |
|
61 | ||
62 |
/** |
|
63 |
* Tries to load the functionality of the plugin into the current |
|
64 |
* process. |
|
65 |
* |
|
66 |
* @throw runtime_error If the plugin cannot be loaded for some |
|
67 |
* reason. |
|
68 |
*/ |
|
69 |
void load(); |
|
70 | ||
71 |
/** |
|
72 |
* Tries to unload the functionality of the plugin. |
|
73 |
* |
|
74 |
* @throw runtime_error If the plugin cannot be unloaded for some |
|
75 |
* reason. |
|
76 |
*/ |
|
77 |
void unload(); |
|
78 |
private: |
|
79 |
friend class Manager; |
|
80 | ||
81 |
boost::scoped_ptr<Impl> impl; |
|
82 | ||
83 |
Plugin(Impl* impl); |
|
84 | ||
85 |
static boost::shared_ptr<Plugin> create(const std::string& name, |
|
86 |
const std::string& library); |
|
87 |
}; |
|
88 | ||
89 |
typedef boost::shared_ptr<Plugin> PluginPtr; |
|
90 | ||
91 |
} |
|
92 |
} |
src/rsc/plugins/Provider.h | ||
---|---|---|
1 |
/* ============================================================ |
|
2 |
* |
|
3 |
* This file is part of the RSB project. |
|
4 |
* |
|
5 |
* Copyright (C) 2012 Jan Moringen <jmoringe@techfak.uni-bielefeld.de> |
|
6 |
* |
|
7 |
* This file may be licensed under the terms of the |
|
8 |
* GNU Lesser General Public License Version 3 (the ``LGPL''), |
|
9 |
* or (at your option) any later version. |
|
10 |
* |
|
11 |
* Software distributed under the License is distributed |
|
12 |
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
|
13 |
* express or implied. See the LGPL for the specific language |
|
14 |
* governing rights and limitations. |
|
15 |
* |
|
16 |
* You should have received a copy of the LGPL along with this |
|
17 |
* program. If not, go to http://www.gnu.org/licenses/lgpl.html |
|
18 |
* or write to the Free Software Foundation, Inc., |
|
19 |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
20 |
* |
|
21 |
* The development of this software was supported by: |
|
22 |
* CoR-Lab, Research Institute for Cognition and Robotics |
|
23 |
* Bielefeld University |
|
24 |
* |
|
25 |
* ============================================================ */ |
|
26 | ||
27 |
#pragma once |
|
28 | ||
29 |
#include <string> |
|
30 | ||
31 |
#define RSC_PLUGIN_INIT_SYMBOL rsc_plugin_init |
|
32 |
#define RSC_PLUGIN_SHUTDOWN_SYMBOL rsc_plugin_shutdown |
|
0 |
- |