plugin_tool.cpp
Go to the documentation of this file.
00001  /*
00002  * Copyright (c) 2012, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include <pluginlib/class_loader.h>
00031 #include <ros/console.h>
00032 #include <iostream>
00033 #include <vector>
00034 #include <string>
00035 #include <fstream>
00036 #include <sstream>
00037 #include <dlfcn.h>
00038 
00039 using std::cout;
00040 using std::endl;
00041 using std::vector;
00042 using std::string;
00043 
00044 vector<string>  g_cli_arguments;
00045 void*           g_class_loader_library_handle = NULL;
00046 
00047 //Handle CLI request
00048 void            processUserCommand();
00049 void            handleFindPluginRequest();
00050 void            handleListPluginsRequest();
00051 void            handleLoadPluginRequest();
00052 
00053 //Command line arguments
00054 vector<string>  getCLIArguments();
00055 void            setCLIArguments(int argc, char* argv[]);
00056 bool            verifyCLIArguments();
00057 
00058 string          baseClass(){return(getCLIArguments().at(1));}
00059 string          baseClassHeader(){return(getCLIArguments().at(2));}
00060 string          packageName(){return(getCLIArguments().at(3));}
00061 string          commandVerb(){return(getCLIArguments().at(4));}
00062 string          pluginName(){return(getCLIArguments().at(5));}
00063 
00064 //Typed Class Loader Interface (shared object)
00065 string          callCommandLine(const char* cmd);
00066 string          determineIncludePathsForBaseClassHeaderDependencies();
00067 void            generateAndLoadTypedPluginInterface();
00068 void            generateFile(string filename, string contents);
00069 string          generatedSharedLibrary(){return "libTypedPluginInterface.so";}
00070 string          generatedObjFile(){return "typedPluginInterface.o";}
00071 string          generatedCppFile(){return "typedPluginInterface.cpp";}
00072 string          getPluginlibSharedFolder();
00073 string          getTypedClassLoaderTemplate();
00074 string          getTypedClassLoaderTemplateWithBaseSet();
00075 vector<string>  parseToStringVector(std::string newline_delimited_str);
00076 string          stripNewlineCharacters(const std::string& s);
00077 string          templateCppFileWithoutExtension(){return "typedPluginInterface";}
00078 string          templateCppFile(){return templateCppFileWithoutExtension() + ".cpp";}
00079 string          templateCppFileAbsolutePath(){return getPluginlibSharedFolder() + "/" + templateCppFile();}
00080 
00081 
00082 int main(int argc, char* argv[])
00083 /*****************************************************************************/
00084 {
00085         cout << "plugin_tool - A command line tool for pluginlib testing" << endl;
00086         cout << "-------------------------------------------------------" << endl;
00087 
00088         setCLIArguments(argc, argv);
00089         if(!verifyCLIArguments())
00090         {
00091                 cout << "Error: Invalid arguments passed to plugin_tool." << endl;
00092                 exit(-1);
00093         }
00094 
00095         cout << "Base class = " << baseClass() << endl;
00096         cout << "Package name = " << packageName() << endl << endl;
00097 
00098         generateAndLoadTypedPluginInterface();
00099         processUserCommand();
00100 
00101    return 0;
00102 }
00103 
00104 std::string callCommandLine(const char* cmd)
00105 /***************************************************************************/
00106 {
00107         FILE* pipe = popen(cmd, "r");
00108         if (!pipe)
00109           return "ERROR";
00110         char buffer[128];
00111         std::string result = "";
00112         while(!feof(pipe))
00113         {
00114           if(fgets(buffer, 128, pipe) != NULL)
00115                   result += buffer;
00116         }
00117         pclose(pipe);
00118         return result;
00119 }
00120 
00121 string determineIncludePathsForBaseClassHeaderDependencies()
00122 /*****************************************************************************/
00123 {
00124    string cmd = "rospack cflags-only-I " + packageName();
00125         return(stripNewlineCharacters(callCommandLine(cmd.c_str())));
00126 }
00127 
00128 void generateAndLoadTypedPluginInterface()
00129 /*****************************************************************************/
00130 {
00131         cout << "Generating typed plugin interface cpp..." << endl;
00132         string code = getTypedClassLoaderTemplateWithBaseSet();
00133         cout << "***************************************************" << endl;
00134         cout << code << endl;
00135         cout << "***************************************************" << endl;
00136 
00137         cout << "Outputting to file " << templateCppFile() << "..." << endl;
00138         generateFile(generatedCppFile(), code);
00139 
00140         cout << "Building interface shared object..." << endl;
00141         string cmd1 = "g++ -fPIC -I" + determineIncludePathsForBaseClassHeaderDependencies() + " -c " + generatedCppFile();
00142         string cmd2 = "g++ -shared -o " + generatedSharedLibrary() + " " + generatedObjFile();
00143 
00144         cout << "Command 1 = " << cmd1 << endl;
00145         cout << "Command 2 = " << cmd2 << endl;
00146 
00147         if(-1 == system(cmd1.c_str()))
00148         {
00149                 cout << "Error: Failed to compile interface." << endl;
00150                 exit(-1);
00151         }
00152         else
00153         {
00154       cout << "Interface compiled to an object file, attempting to build..." << endl;
00155       if(-1 == system(cmd2.c_str()))
00156       {
00157          cout << "Error: Failed to build shared object." << endl;
00158          exit(-1);
00159       }
00160       else
00161          cout << "Build of shared object succeeded." << endl;
00162 
00163         }
00164 
00165         cout << "Loading shared object into memory." << endl;
00166         g_class_loader_library_handle = dlopen("libTypedPluginInterface.so", RTLD_LAZY);
00167         if(g_class_loader_library_handle)
00168                 cout << "Shared object successfully loaded into memory." << endl;
00169         else
00170         {
00171                 cout << "Error: Failed to load shared object into memory." << endl;
00172                 exit(-1);
00173         }
00174 }
00175 
00176 template <typename T> T getPluginFunction(const std::string& function_name)
00177 /*****************************************************************************/
00178 {
00179         void* ptr = dlsym(g_class_loader_library_handle, function_name.c_str());
00180         return((T)(ptr));
00181 }
00182 
00183 vector<string>  getCLIArguments()
00184 /*****************************************************************************/
00185 {
00186         return(g_cli_arguments);
00187 }
00188 
00189 void generateFile(string filename, string contents)
00190 /*****************************************************************************/
00191 {
00192         std::ofstream file;
00193         file.open(filename.c_str());
00194         file << contents;
00195         file.close();
00196 }
00197 
00198 std::string getPluginlibSharedFolder()
00199 /***************************************************************************/
00200 {
00201    vector<std::string> allVals = parseToStringVector(callCommandLine("catkin_find pluginlib --share"));
00202    assert(allVals.size() > 0);
00203    return(allVals.at(0));
00204 }
00205 
00206 string getTypedClassLoaderTemplate()
00207 /*****************************************************************************/
00208 {
00209         std::ifstream file;
00210    string path = getPluginlibSharedFolder() + "/typed_class_loader_template.cpp";
00211         file.open(path.c_str());
00212         if(!file)
00213         {
00214                 cout << "Error: Cannot find file " + path + " to generate class loader";
00215                 exit(-1);
00216         }
00217 
00218         string contents;
00219         while(!file.eof())
00220         {
00221                 char c;
00222                 file.get(c);
00223                 contents.push_back(c);
00224                 cout << c;
00225         }
00226 
00227         return contents;
00228 }
00229 
00230 string getTypedClassLoaderTemplateWithBaseSet()
00231 /*****************************************************************************/
00232 {
00233         string class_template = getTypedClassLoaderTemplate();
00234         string class_with_type_set;
00235         for(unsigned int c = 0; c < class_template.size(); c++)
00236         {
00237                 if(class_template.at(c) == '$')
00238                         class_with_type_set += baseClass();
00239                 else if(class_template.at(c) == '@')
00240                         class_with_type_set += "#include \"" + baseClassHeader() + "\"";
00241                 else
00242                         class_with_type_set.push_back(class_template.at(c));
00243         }
00244         return(class_with_type_set);
00245 }
00246 
00247 void handleFindPluginRequest()
00248 /*****************************************************************************/
00249 {
00250         //string whereIsPluginLocated(const string& package_name, const string& class_name)
00251         typedef std::string (*WhereIsFunc)(const string&, const string&);
00252         WhereIsFunc f = getPluginFunction<WhereIsFunc>("whereIsPluginLocated");
00253 
00254         cout << "Attempting to find plugin " << pluginName() << " exported from package " << packageName() << "..." << endl;
00255 
00256         if(f)
00257                 cout << "Plugin " << pluginName() << " is located in library " << f(packageName(), pluginName()) << endl;
00258         else
00259         {
00260                 cout << "Error: Could not find function 'whereIsPluginLocated' in shared object." << endl;
00261                 exit(-1);
00262         }
00263 }
00264 
00265 void handleListPluginsRequest()
00266 /*****************************************************************************/
00267 {
00268         //  std::vector<std::string> availablePlugins(const string& package_name)
00269         typedef std::vector<std::string> (*ListFunc)(const string&);
00270         ListFunc f = getPluginFunction<ListFunc>("availablePlugins");
00271 
00272         cout << "The following plugins are available in package " << packageName() << ":" << endl;
00273         if(f)
00274         {
00275 
00276                 std::vector<std::string> plugins = f(packageName());
00277                 for(unsigned int c = 0; c < plugins.size(); c++)
00278                         cout << plugins.at(c) << endl;
00279         }
00280         else
00281         {
00282                 cout << "Error: Could not find function 'availablePlugins' in shared object." << endl;
00283                 exit(-1);
00284         }
00285 }
00286 
00287 void handleLoadPluginRequest()
00288 /*****************************************************************************/
00289 {
00290         //  bool loadPlugin(const string& package_name, const string& class_name)
00291         typedef bool (*LoadPluginFunc)(const string&, const string&);
00292         LoadPluginFunc f = getPluginFunction<LoadPluginFunc>("loadPlugin");
00293         string plugin_name = getCLIArguments().at(4);
00294         cout << "Attempting to find plugin " << plugin_name << "..." << endl;
00295         if(f)
00296         {
00297                 if(f(packageName(), plugin_name))
00298                         cout << "Opened plugin successfully :)" << endl;
00299                 else
00300                 {
00301                         cout << "Error: Plugin did not open :(" << endl;
00302                         exit(-1);
00303                 }
00304         }
00305         else
00306         {
00307                 cout << "Error: Could not find function 'loadPlugin' in shared object." << endl;
00308                 exit(-1);
00309         }
00310 }
00311 
00312 vector<string> parseToStringVector(std::string newline_delimited_str)
00313 /***************************************************************************/
00314 {
00315    string next;
00316    vector<string> parse_result;
00317    for(unsigned int c = 0; c < newline_delimited_str.size(); c++)
00318    {
00319       char ch = newline_delimited_str.at(c);
00320       if(ch == '\n')
00321       {
00322        parse_result.push_back(next);
00323        next = "";
00324       }
00325       else
00326        next.push_back(ch);
00327    }
00328    return(parse_result);
00329 }
00330 
00331 void processUserCommand()
00332 /*****************************************************************************/
00333 {
00334         string verb = commandVerb();
00335 
00336         if (verb == "find")
00337                 handleFindPluginRequest();
00338         else if (verb == "list")
00339                 handleListPluginsRequest();
00340         else if(verb == "load")
00341                 handleLoadPluginRequest();
00342         else
00343                 cout << "Error: Unknown verb for plugin_tool, available verbs are 'load', 'list', and 'find'." << endl;
00344 }
00345 
00346 void setCLIArguments(int argc, char* argv[])
00347 /*****************************************************************************/
00348 {
00349         g_cli_arguments = vector<string>(argc);
00350         for(int c = 0; c < argc; c++)
00351                 g_cli_arguments.at(c) = string(argv[c]);
00352 }
00353 
00354 string stripNewlineCharacters(const std::string& s)
00355 /*****************************************************************************/
00356 {
00357    string stripped;
00358    for(unsigned int c = 0; c < s.size(); c++)
00359    {
00360       if(s.at(c) != '\n')
00361          stripped.push_back(s.at(c));
00362    }
00363    return stripped;
00364 }
00365 
00366 bool verifyCLIArguments()
00367 /*****************************************************************************/
00368 {
00369         vector<string> args = getCLIArguments();
00370 
00371         if(args.size() < 5)
00372         {
00373                 cout << "Not enough arguments. Usage: plugin_tool <BASE CLASS> <BASE_CLASS_HEADER> <PACKAGE_NAME> <find [class_name] | list | load [class_name]>";
00374                 return false;
00375         }
00376 
00377    for(size_t c = 0; c < args.size(); c++)
00378       cout << "Arg " << c << ": " << args.at(c) << endl;
00379 
00380         return(true);
00381 }


pluginlib
Author(s): Eitan Marder-Eppstein, Tully Foote, Dirk Thomas, Mirza Shah
autogenerated on Thu Jul 27 2017 02:19:34