introspection.cpp
Go to the documentation of this file.
1 //=================================================================================================
2 // Copyright (c) 2011, Johannes Meyer, TU Darmstadt
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 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 // * Neither the name of the Flight Systems and Automatic Control group,
13 // TU Darmstadt, nor the names of its contributors may be used to
14 // endorse or promote products derived from this software without
15 // specific prior written permission.
16 
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //=================================================================================================
28 
29 #include <introspection/field.h>
30 #include <introspection/type.h>
33 
34 #include <dlfcn.h>
35 
36 #define BOOST_FILESYSTEM_VERSION 3
37 #include <boost/filesystem.hpp>
38 
39 namespace cpp_introspection {
40 
47 
48  PackagePtr package(const std::string& pkg)
49  {
50  if (!g_packages.count(pkg)) return PackagePtr();
51  return g_packages[pkg].lock();
52  }
53 
54  const V_Package &packages() {
55  return g_repository;
56  }
57 
58  MessagePtr messageByDataType(const std::string& data_type, const std::string& package)
59  {
60  if (!package.empty()) return messageByDataType(package + "/" + data_type);
61  if (data_type == "Header") return g_messages_by_name[ros::message_traits::datatype<std_msgs::Header>()].lock();
62  if (!g_messages_by_name.count(data_type)) return MessagePtr();
63  return g_messages_by_name[data_type].lock();
64  }
65 
66  MessagePtr messageByMD5Sum(const std::string& md5sum)
67  {
68  if (!g_messages_by_md5sum.count(md5sum)) return MessagePtr();
69  return g_messages_by_md5sum[md5sum].lock();
70  }
71 
72  MessagePtr messageByTypeId(const std::type_info &type_info) {
73  if (!g_messages_by_typeid.count(&type_info)) return MessagePtr();
74  return g_messages_by_typeid[&type_info].lock();
75  }
76 
78  {
79  if (g_packages.count(package->getName())) return g_packages[package->getName()].lock();
80  g_repository.push_back(package);
81  g_packages[package->getName()] = package;
82  return package;
83  }
84 
85  std::vector<std::string> Package::getMessages() const
86  {
87  std::vector<std::string> messages;
88  for(std::vector<MessagePtr>::const_iterator it = messages_.begin(); it != messages_.end(); ++it)
89  messages.push_back((*it)->getName());
90 
91  return messages;
92  }
93 
94  MessagePtr Package::message(const std::string& message) const
95  {
96  return messageByDataType(std::string(getName()) + "/" + message);
97  }
98 
100  {
101  if (g_messages_by_name.count(message->getDataType())) return g_messages_by_name[message->getDataType()].lock();
102  messages_.push_back(message);
103  g_messages_by_name[message->getDataType()] = message;
104  g_messages_by_md5sum[message->getMD5Sum()] = message;
105  g_messages_by_typeid[&(message->getTypeId())] = message;
106  return message;
107  }
108 
109  MessagePtr expand(const MessagePtr& message, const std::string &separator, const std::string &prefix)
110  {
111  return MessagePtr(new ExpandedMessage(message, separator, prefix));
112  }
113 
114  void ExpandedMessage::expand(const MessagePtr &message, const std::string& prefix) {
115  for(Message::const_iterator i = message->begin(); i != message->end(); i++) {
116  FieldPtr field = *i;
117 
118  for(std::size_t j = 0; j < field->size(); j++) {
119  std::string field_name = (!prefix.empty() ? prefix + separator_ : "") + field->getName();
120  if (field->isContainer()) field_name += boost::lexical_cast<std::string>(j);
121 
122  if (field->isMessage()) {
123  MessagePtr expanded(field->expand(j));
124  if (!expanded) {
125  ROS_WARN("Expansion of %s failed: Could not expand field %s with unknown type %s", getDataType(), field->getName(), field->getDataType());
126  continue;
127  }
128  expand(expanded, field_name);
129  } else {
130  FieldPtr expanded(new ExpandedField(*field, field_name, j));
131  fields_.push_back(expanded);
132  fields_by_name_[field_name] = expanded;
133  field_names_.push_back(expanded->getName());
134  }
135  }
136  }
137  }
138 
139  V_string Message::getFields(bool expand, const std::string& separator, const std::string& prefix) const
140  {
142  return getFields(fields, expand, separator, prefix);
143  }
144 
145  V_string& Message::getFields(V_string& fields, bool expand, const std::string& separator, const std::string& prefix) const
146  {
147  for(const_iterator it = begin(); it != end(); ++it) {
148  FieldPtr field = *it;
149  std::string base(prefix + field->getName());
150 
151  for (std::size_t index = 0; index < field->size(); ++index) {
152  std::string name(base);
153  if (field->isArray()) name = name + boost::lexical_cast<std::string>(index);
154 
155  if (expand && field->isMessage()) {
156  MessagePtr expanded = field->expand(index);
157  if (!expanded) {
158  ROS_WARN("Expansion of %s failed: Could not expand field %s with unknown type %s", getDataType(), field->getName(), field->getDataType());
159  continue;
160  }
161  expanded->getFields(fields, expand, separator, name + separator);
162 
163  } else {
164  fields.push_back(name);
165  }
166  }
167  }
168 
169  return fields;
170  }
171 
173  {
174  V_string types;
175  return getTypes(types, expand);
176  }
177 
179  {
180  for(const_iterator it = begin(); it != end(); ++it) {
181  FieldPtr field = *it;
182 
183  for (std::size_t index = 0; index < field->size(); ++index) {
184  if (expand && field->isMessage()) {
185  MessagePtr expanded = field->expand(index);
186  if (!expanded) {
187  ROS_WARN("Expansion of %s failed: Could not expand field %s with unknown type %s", getDataType(), field->getName(), field->getDataType());
188  continue;
189  }
190  expanded->getTypes(types, expand);
191 
192  } else {
193  types.push_back(field->isArray() ? field->getValueType() : field->getDataType());
194  }
195  }
196  }
197 
198  return types;
199  }
200 
201  std::vector<boost::any> Message::getValues(bool expand) const
202  {
203  std::vector<boost::any> values;
204  return getValues(values, expand);
205  }
206 
207  std::vector<boost::any>& Message::getValues(std::vector<boost::any>& values, bool expand) const
208  {
209  if (!hasInstance()) return values;
210 
211  for(const_iterator it = begin(); it != end(); ++it) {
212  FieldPtr field = *it;
213 
214  for (std::size_t index = 0; index < field->size(); ++index) {
215  if (expand && field->isMessage()) {
216  MessagePtr expanded = field->expand(index);
217  if (!expanded) {
218  ROS_WARN("Expansion of %s failed: Could not expand field %s with unknown type %s", getDataType(), field->getName(), field->getDataType());
219  continue;
220  }
221  expanded->getValues(values, expand);
222 
223  } else {
224  values.push_back(field->get(index));
225  }
226  }
227  }
228 
229  return values;
230  }
231 
232  MessagePtr Field::expand(std::size_t i) const {
233  if (!isMessage()) return MessagePtr();
234  return messageByTypeId(this->getTypeId());
235  }
236 
237  PackagePtr loadPackage(const std::string &package_name)
238  {
239  PackagePtr p = package(package_name);
240  if (p) return p;
241  return load("libintrospection_" + package_name + ".so");
242  }
243 
244  using namespace boost::filesystem;
245  PackagePtr load(const std::string& package_or_library_or_path)
246  {
247  path path(package_or_library_or_path);
248  if (is_directory(path)) {
249  ROS_DEBUG_STREAM_NAMED(ROS_PACKAGE_NAME, "Searching directory " << path << "...");
250  for(directory_iterator entry(path); entry != directory_iterator(); ++entry) {
251  ROS_DEBUG_STREAM_NAMED(ROS_PACKAGE_NAME, " " << *entry << "...");
252  if (is_regular_file(entry->path())) load(entry->path().string());
253  }
254 
255  return PackagePtr();
256  }
257 
258  if (path.extension() != ".so") {
259  loadPackage(package_or_library_or_path);
260  return PackagePtr();
261  }
262  ROS_DEBUG_STREAM_NAMED(ROS_PACKAGE_NAME, "Loading " << path << "...");
263 
264  if (std::find(g_loaded_libraries.begin(), g_loaded_libraries.end(), path.filename()) != g_loaded_libraries.end()) {
265  ROS_WARN_STREAM_NAMED(ROS_PACKAGE_NAME, "library " << path << " already loaded");
266  return PackagePtr();
267  }
268 
269  void *library = dlopen(path.string().c_str(), RTLD_NOW | RTLD_GLOBAL);
270  const char *error = dlerror();
271  if (error || !library) {
272  ROS_ERROR("%s", error);
273  return PackagePtr();
274  }
275 
276  typedef PackagePtr (*LoadFunction)();
277  LoadFunction load_fcn = (LoadFunction) dlsym(library, "cpp_introspection_load_package");
278  error = dlerror();
279  if (error || !load_fcn) {
280  ROS_WARN_NAMED(ROS_PACKAGE_NAME, "%s", error);
281  dlclose(library);
282  return PackagePtr();
283  }
284  PackagePtr package __attribute__((unused)) = (*load_fcn)();
285 
286  ROS_INFO_STREAM_NAMED(ROS_PACKAGE_NAME, "Successfully loaded cpp_introspection library " << path);
287  g_loaded_libraries.push_back(path.filename().string());
288 
289 // for(Package::const_iterator it = package->begin(); it != package->end(); ++it) {
290 // ROS_INFO_STREAM_NAMED(ROS_PACKAGE_NAME, "Package " << package->getName() << " contains message " << (*it)->getName() << ":");
291 // V_string types = (*it)->getTypes();
292 // V_string names = (*it)->getFields();
293 // for(V_string::const_iterator it_type = types.begin(), it_name = names.begin(); it_type != types.end() && it_name != names.end(); ++it_type, ++it_name) {
294 // ROS_INFO(" %s %s", it_type->c_str(), it_name->c_str());
295 // }
296 // }
297 
298  return package;
299  }
300 
301 } // namespace cpp_introspection
std::vector< std::string > V_string
Definition: forwards.h:74
MessagePtr messageByMD5Sum(const std::string &md5sum)
static M_TypeInfo_Message g_messages_by_typeid
#define ROS_DEBUG_STREAM_NAMED(name, args)
#define ROS_WARN_NAMED(name,...)
V_string getFields(bool expand=false, const std::string &separator=".", const std::string &prefix=std::string()) const
std::vector< boost::any > getValues(bool expand=false) const
void expand(const MessagePtr &message, const std::string &prefix)
PackagePtr load(const std::string &package_or_library_or_path)
static M_Message g_messages_by_md5sum
#define ROS_INFO_STREAM_NAMED(name, args)
MessagePtr expand(const MessagePtr &message, const std::string &separator=".", const std::string &prefix="")
#define ROS_WARN(...)
const V_Package & packages()
virtual MessagePtr expand(std::size_t i=0) const
boost::shared_ptr< Package const > PackagePtr
Definition: forwards.h:44
std::map< const std::type_info *, MessageWPtr, CompareTypeInfo > M_TypeInfo_Message
Definition: forwards.h:67
MessagePtr messageByTypeId(const std::type_info &type_info)
V_Field::const_iterator const_iterator
Definition: message.h:101
std::vector< PackagePtr > V_Package
Definition: forwards.h:55
const_iterator begin() const
Definition: package.h:53
PackagePtr package(const std::string &pkg)
static V_Package g_repository
const_iterator end() const
Definition: package.h:54
virtual const V_Message & fields() const
Definition: package.h:48
static M_Message g_messages_by_name
static PackagePtr add(const PackagePtr &package)
PackagePtr loadPackage(const std::string &package_name)
virtual const char * getName() const =0
boost::shared_ptr< Message const > MessagePtr
Definition: forwards.h:48
MessagePtr message(const std::string &message) const
static M_Package g_packages
std::map< std::string, MessageWPtr > M_Message
Definition: forwards.h:62
V_string getTypes(bool expand=false) const
#define ROS_ERROR(...)
MessagePtr messageByDataType(const std::string &data_type, const std::string &package=std::string())
static V_string g_loaded_libraries
std::map< std::string, PackageWPtr > M_Package
Definition: forwards.h:61
std::vector< std::string > getMessages() const
#define ROS_WARN_STREAM_NAMED(name, args)


cpp_introspection
Author(s): Johannes Meyer
autogenerated on Mon Jun 10 2019 12:56:17