plugin_tool.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Willow Garage, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <dlfcn.h>
32 #include <ros/console.h>
33 #include <iostream>
34 #include <vector>
35 #include <string>
36 #include <fstream>
37 #include <sstream>
38 
39 using std::cout;
40 using std::endl;
41 using std::vector;
42 using std::string;
43 
44 vector<string> g_cli_arguments;
46 
47 // Handle CLI request
48 void processUserCommand();
52 
53 // Command line arguments
54 vector<string> getCLIArguments();
55 void setCLIArguments(int argc, char * argv[]);
56 bool verifyCLIArguments();
57 
58 string baseClass() {return getCLIArguments().at(1);}
59 string baseClassHeader() {return getCLIArguments().at(2);}
60 string packageName() {return getCLIArguments().at(3);}
61 string commandVerb() {return getCLIArguments().at(4);}
62 string pluginName() {return getCLIArguments().at(5);}
63 
64 // Typed Class Loader Interface (shared object)
65 string callCommandLine(const char * cmd);
68 void generateFile(string filename, string contents);
69 string generatedSharedLibrary() {return "libTypedPluginInterface.so";}
70 string generatedObjFile() {return "typedPluginInterface.o";}
71 string generatedCppFile() {return "typedPluginInterface.cpp";}
75 vector<string> parseToStringVector(std::string newline_delimited_str);
76 string stripNewlineCharacters(const std::string & s);
77 string templateCppFileWithoutExtension() {return "typedPluginInterface";}
78 string templateCppFile() {return templateCppFileWithoutExtension() + ".cpp";}
80 
81 
82 int main(int argc, char * argv[])
83 /*****************************************************************************/
84 {
85  cout << "plugin_tool - A command line tool for pluginlib testing" << endl;
86  cout << "-------------------------------------------------------" << endl;
87 
88  setCLIArguments(argc, argv);
89  if (!verifyCLIArguments()) {
90  cout << "Error: Invalid arguments passed to plugin_tool." << endl;
91  exit(-1);
92  }
93 
94  cout << "Base class = " << baseClass() << endl;
95  cout << "Package name = " << packageName() << endl << endl;
96 
99 
100  return 0;
101 }
102 
103 std::string callCommandLine(const char * cmd)
104 /***************************************************************************/
105 {
106  FILE * pipe = popen(cmd, "r");
107  if (!pipe) {
108  return "ERROR";
109  }
110  char buffer[128];
111  std::string result = "";
112  while (!feof(pipe)) {
113  if (fgets(buffer, 128, pipe) != NULL) {
114  result += buffer;
115  }
116  }
117  pclose(pipe);
118  return result;
119 }
120 
122 /*****************************************************************************/
123 {
124  string cmd = "rospack cflags-only-I " + packageName();
125  return stripNewlineCharacters(callCommandLine(cmd.c_str()));
126 }
127 
129 /*****************************************************************************/
130 {
131  cout << "Generating typed plugin interface cpp..." << endl;
133  cout << "***************************************************" << endl;
134  cout << code << endl;
135  cout << "***************************************************" << endl;
136 
137  cout << "Outputting to file " << templateCppFile() << "..." << endl;
139 
140  cout << "Building interface shared object..." << endl;
141  string cmd1 = "g++ -fPIC -I" + determineIncludePathsForBaseClassHeaderDependencies() + \
142  " -c " + generatedCppFile();
143  string cmd2 = "g++ -shared -o " + generatedSharedLibrary() + " " + generatedObjFile();
144 
145  cout << "Command 1 = " << cmd1 << endl;
146  cout << "Command 2 = " << cmd2 << endl;
147 
148  if (-1 == system(cmd1.c_str())) {
149  cout << "Error: Failed to compile interface." << endl;
150  exit(-1);
151  } else {
152  cout << "Interface compiled to an object file, attempting to build..." << endl;
153  if (-1 == system(cmd2.c_str())) {
154  cout << "Error: Failed to build shared object." << endl;
155  exit(-1);
156  } else {
157  cout << "Build of shared object succeeded." << endl;
158  }
159  }
160 
161  cout << "Loading shared object into memory." << endl;
162  g_class_loader_library_handle = dlopen("libTypedPluginInterface.so", RTLD_LAZY);
164  cout << "Shared object successfully loaded into memory." << endl;
165  } else {
166  cout << "Error: Failed to load shared object into memory." << endl;
167  exit(-1);
168  }
169 }
170 
171 template<typename T>
172 T getPluginFunction(const std::string & function_name)
173 /*****************************************************************************/
174 {
175  void * ptr = dlsym(g_class_loader_library_handle, function_name.c_str());
176  return (T)(ptr);
177 }
178 
179 vector<string> getCLIArguments()
180 /*****************************************************************************/
181 {
182  return g_cli_arguments;
183 }
184 
185 void generateFile(string filename, string contents)
186 /*****************************************************************************/
187 {
188  std::ofstream file;
189  file.open(filename.c_str());
190  file << contents;
191  file.close();
192 }
193 
195 /***************************************************************************/
196 {
197  vector<std::string> allVals = parseToStringVector(
198  callCommandLine("catkin_find pluginlib --share"));
199  assert(allVals.size() > 0);
200  return allVals.at(0);
201 }
202 
204 /*****************************************************************************/
205 {
206  std::ifstream file;
207  string path = getPluginlibSharedFolder() + "/typed_class_loader_template.cpp";
208  file.open(path.c_str());
209  if (!file) {
210  cout << "Error: Cannot find file " + path + " to generate class loader";
211  exit(-1);
212  }
213 
214  string contents;
215  while (!file.eof()) {
216  char c;
217  file.get(c);
218  contents.push_back(c);
219  cout << c;
220  }
221 
222  return contents;
223 }
224 
226 /*****************************************************************************/
227 {
228  string class_template = getTypedClassLoaderTemplate();
229  string class_with_type_set;
230  for (unsigned int c = 0; c < class_template.size(); c++) {
231  if ('$' == class_template.at(c)) {
232  class_with_type_set += baseClass();
233  } else if ('@' == class_template.at(c)) {
234  class_with_type_set += "#include \"" + baseClassHeader() + "\"";
235  } else {
236  class_with_type_set.push_back(class_template.at(c));
237  }
238  }
239  return class_with_type_set;
240 }
241 
243 /*****************************************************************************/
244 {
245  // string whereIsPluginLocated(const string& package_name, const string& class_name)
246  typedef std::string (* WhereIsFunc)(const string &, const string &);
247  WhereIsFunc f = getPluginFunction<WhereIsFunc>("whereIsPluginLocated");
248 
249  cout << "Attempting to find plugin " << pluginName() << " exported from package " << \
250  packageName() << "..." << endl;
251 
252  if (f) {
253  cout << "Plugin " << pluginName() << " is located in library " << \
254  f(packageName(), pluginName()) << endl;
255  } else {
256  cout << "Error: Could not find function 'whereIsPluginLocated' in shared object." << endl;
257  exit(-1);
258  }
259 }
260 
262 /*****************************************************************************/
263 {
264  // std::vector<std::string> availablePlugins(const string& package_name)
265  typedef std::vector<std::string>(*ListFunc)(const string &);
266  ListFunc f = getPluginFunction<ListFunc>("availablePlugins");
267 
268  cout << "The following plugins are available in package " << packageName() << ":" << endl;
269  if (f) {
270  std::vector<std::string> plugins = f(packageName());
271  for (unsigned int c = 0; c < plugins.size(); c++) {
272  cout << plugins.at(c) << endl;
273  }
274  } else {
275  cout << "Error: Could not find function 'availablePlugins' in shared object." << endl;
276  exit(-1);
277  }
278 }
279 
281 /*****************************************************************************/
282 {
283  // bool loadPlugin(const string& package_name, const string& class_name)
284  typedef bool (* LoadPluginFunc)(const string &, const string &);
285  LoadPluginFunc f = getPluginFunction<LoadPluginFunc>("loadPlugin");
286  string plugin_name = getCLIArguments().at(4);
287  cout << "Attempting to find plugin " << plugin_name << "..." << endl;
288  if (f) {
289  if (f(packageName(), plugin_name)) {
290  cout << "Opened plugin successfully :)" << endl;
291  } else {
292  cout << "Error: Plugin did not open :(" << endl;
293  exit(-1);
294  }
295  } else {
296  cout << "Error: Could not find function 'loadPlugin' in shared object." << endl;
297  exit(-1);
298  }
299 }
300 
301 vector<string> parseToStringVector(std::string newline_delimited_str)
302 /***************************************************************************/
303 {
304  string next;
305  vector<string> parse_result;
306  for (unsigned int c = 0; c < newline_delimited_str.size(); c++) {
307  char ch = newline_delimited_str.at(c);
308  if ('\n' == ch) {
309  parse_result.push_back(next);
310  next = "";
311  } else {
312  next.push_back(ch);
313  }
314  }
315  return parse_result;
316 }
317 
319 /*****************************************************************************/
320 {
321  string verb = commandVerb();
322 
323  if ("find" == verb) {
325  } else if ("list" == verb) {
327  } else if ("load" == verb) {
329  } else {
330  cout << "Error: Unknown verb for plugin_tool, available verbs are" <<
331  "'load', 'list', and 'find'." << endl;
332  }
333 }
334 
335 void setCLIArguments(int argc, char * argv[])
336 /*****************************************************************************/
337 {
338  g_cli_arguments = vector<string>(argc);
339  for (int c = 0; c < argc; c++) {
340  g_cli_arguments.at(c) = string(argv[c]);
341  }
342 }
343 
344 string stripNewlineCharacters(const std::string & s)
345 /*****************************************************************************/
346 {
347  string stripped;
348  for (unsigned int c = 0; c < s.size(); c++) {
349  if (s.at(c) != '\n') {
350  stripped.push_back(s.at(c));
351  }
352  }
353  return stripped;
354 }
355 
357 /*****************************************************************************/
358 {
359  vector<string> args = getCLIArguments();
360 
361  if (args.size() < 5) {
362  cout << "Not enough arguments. Usage: plugin_tool <BASE CLASS> <BASE_CLASS_HEADER> " << \
363  "<PACKAGE_NAME> <find [class_name] | list | load [class_name]>";
364  return false;
365  }
366 
367  for (size_t c = 0; c < args.size(); c++) {
368  cout << "Arg " << c << ": " << args.at(c) << endl;
369  }
370 
371  return true;
372 }
void processUserCommand()
vector< string > parseToStringVector(std::string newline_delimited_str)
string pluginName()
Definition: plugin_tool.cpp:62
f
string generatedCppFile()
Definition: plugin_tool.cpp:71
string cmd
string stripNewlineCharacters(const std::string &s)
string commandVerb()
Definition: plugin_tool.cpp:61
string generatedSharedLibrary()
Definition: plugin_tool.cpp:69
void handleLoadPluginRequest()
string getTypedClassLoaderTemplate()
string getPluginlibSharedFolder()
string templateCppFileWithoutExtension()
Definition: plugin_tool.cpp:77
vector< string > g_cli_arguments
Definition: plugin_tool.cpp:44
T getPluginFunction(const std::string &function_name)
string determineIncludePathsForBaseClassHeaderDependencies()
bool verifyCLIArguments()
void * g_class_loader_library_handle
Definition: plugin_tool.cpp:45
vector< string > getCLIArguments()
void setCLIArguments(int argc, char *argv[])
string baseClass()
Definition: plugin_tool.cpp:58
string generatedObjFile()
Definition: plugin_tool.cpp:70
string getTypedClassLoaderTemplateWithBaseSet()
void generateFile(string filename, string contents)
string callCommandLine(const char *cmd)
string packageName()
Definition: plugin_tool.cpp:60
int main(int argc, char *argv[])
Definition: plugin_tool.cpp:82
string templateCppFileAbsolutePath()
Definition: plugin_tool.cpp:79
string baseClassHeader()
Definition: plugin_tool.cpp:59
string templateCppFile()
Definition: plugin_tool.cpp:78
void handleFindPluginRequest()
void generateAndLoadTypedPluginInterface()
void handleListPluginsRequest()


pluginlib
Author(s): Eitan Marder-Eppstein, Tully Foote, Dirk Thomas, Mirza Shah
autogenerated on Sat Jun 8 2019 18:02:10