XBotInterface  2.4.1
XBotInterface provides a generic API to model and control a robot.
SoLib.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2017 IIT-ADVR
3  * Author: Giuseppe Rigano
4  * email: giuseppe.rigano@iit.it
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>
18 */
19 
20 
21 #ifndef __SO_LIB_H__
22 #define __SO_LIB_H__
23 
24 #include <map>
25 #include <string>
26 #include <iostream>
27 
28 #include <dlfcn.h>
29 #include <XBotInterface/RtLog.hpp>
30 
31 #define REGISTER_SO_LIB_(class_name, base_class) \
32 extern "C" base_class* create_instance() \
33 { \
34  return new class_name(); \
35 }\
36 \
37 extern "C" void destroy_instance( base_class* instance ) \
38 { \
39  delete instance; \
40 }\
41 
42 
43 
44 using XBot::Logger;
45 
46 namespace
47 {
48 
49 
50 class SoLib
51 {
52 
53 public:
54 
55  template <class T>
56  static std::shared_ptr<T> getFactory ( const std::string& path_to_so, const std::string& lib_name ) {
57  char *error;
58  void* lib_handle;
59  lib_handle = dlopen ( path_to_so.c_str(), RTLD_NOW );
60  if ( !lib_handle ) {
61  XBot::Logger::error() << lib_name <<" so library NOT found! \n" << dlerror() << XBot::Logger::endl();
62  } else {
63  Logger::success() << lib_name << " so library found! " << Logger::endl();
64  handles[lib_name] = lib_handle;
65 
66  T* ( *create ) ();
67  create = ( T* ( * ) () ) dlsym ( lib_handle, "create_instance" );
68  if ( ( error = dlerror() ) != NULL ) {
69  XBot::Logger::error() << " in loading library " << lib_name << ": \n" << error << XBot::Logger::endl();
70  return nullptr;
71  }
72 
73  T* instance = ( T* ) create();
74  if ( instance != nullptr ) {
75  return std::shared_ptr<T> ( instance );
76  }
77 
78  XBot::Logger::error() << " in loading library " << lib_name << ": obtained pointer is null" << XBot::Logger::endl();
79  }
80 
81  return nullptr;
82 
83  }
84 
85  static void unloadLib ( const std::string& file_name ) {
86  dlclose ( handles[file_name] );
87  Logger::info() << file_name <<" so library unloaded! " << Logger::endl();
88  }
89 
90  template <class T, typename... Args>
91  static std::shared_ptr<T> getFactoryWithArgs ( const std::string& path_to_so, const std::string& lib_name, Args... args ) {
92  char *error;
93  void* lib_handle;
94  lib_handle = dlopen ( path_to_so.c_str(), RTLD_NOW );
95  if ( !lib_handle ) {
96  XBot::Logger::error() << lib_name <<" so library NOT found! \n" << dlerror() << XBot::Logger::endl();
97  } else {
98  Logger::success() << lib_name << " so library found! " << Logger::endl();
99  handles[lib_name] = lib_handle;
100 
101  T* ( *create ) ( Args... args );
102  create = ( T* ( * ) ( Args... args ) ) dlsym ( lib_handle, "create_instance" );
103  if ( ( error = dlerror() ) != NULL ) {
104  XBot::Logger::error() << " in loading library " << lib_name << ": \n" << error << XBot::Logger::endl();
105  return nullptr;
106  }
107 
108  T* instance = ( T* ) create ( args... );
109  if ( instance != nullptr ) {
110  return std::shared_ptr<T> ( instance );
111  }
112 
113  XBot::Logger::error() << " in loading library " << lib_name << ": obtained pointer is null" << XBot::Logger::endl();
114  }
115 
116  return nullptr;
117 
118  }
119 
120 private:
121 
122  SoLib() = delete;
123 
124  static std::map<std::string, void*> handles;
125 
126  static bool computeAbsolutePath ( const std::string& input_path,
127  const std::string& middle_path,
128  std::string& absolute_path ) {
129  // if not an absolute path
130  if ( ! ( input_path.at ( 0 ) == '/' ) ) {
131  // if you are working with the Robotology Superbuild
132  const char* env_p = std::getenv ( "XBOT_ROOT" );
133  // check the env, otherwise error
134  if ( env_p ) {
135  std::string current_path ( env_p );
136  // default relative path when working with the superbuild
137  current_path += middle_path;
138  current_path += input_path;
139  absolute_path = current_path;
140  return true;
141  } else {
142  std::cerr << "ERROR in " << __func__ << " : the input path " << input_path << " is neither an absolute path nor related with the robotology superbuild. Download it!" << std::endl;
143  return false;
144  }
145  }
146  // already an absolute path
147  absolute_path = input_path;
148  return true;
149  }
150 
151 
152 };
153 
154 std::map<std::string, void*> SoLib::handles;
155 
156 }
157 
158 #endif
XBot::Logger::endl
static Endl & endl()
Closes the message and prints to screen.
Definition: RtLog.cpp:107
XBot::Logger::error
static std::ostream & error(Logger::Severity s=Logger::Severity::HIGH)
Logs an error message (in red, with bold [ERROR] header).
Definition: RtLog.cpp:41
XBot::Logger
Definition: RtLog.hpp:80
XBot::Utils::computeAbsolutePath
std::string computeAbsolutePath(const std::string &input_path)
Computes the absolute path corresponging to a given path relative to the $XBOT_ROOT environment varia...
Definition: Utils.h:439
RtLog.hpp