system.cc
Go to the documentation of this file.
1 /*
2  * This file is part of the rc_genicam_api package.
3  *
4  * Copyright (c) 2017 Roboception GmbH
5  * All rights reserved
6  *
7  * Author: Heiko Hirschmueller
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the copyright holder nor the names of its contributors
20  * may be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include "system.h"
37 
38 #include "gentl_wrapper.h"
39 #include "exception.h"
40 #include "interface.h"
41 #include "cport.h"
42 
43 #include <iostream>
44 
45 #ifdef _WIN32
46 #include <Windows.h>
47 #include <cstring>
48 #undef min
49 #undef max
50 #endif
51 
52 namespace rcg
53 {
54 
56 {
57  if (n_open > 0 && tl != 0)
58  {
59  gentl->TLClose(tl);
60  }
61 
62  gentl->GCCloseLib();
63 }
64 
65 namespace
66 {
67 
68 std::mutex system_mtx;
69 std::vector<std::shared_ptr<System> > slist;
70 
71 int find(const std::vector<std::shared_ptr<System> > &list, const std::string &filename)
72 {
73  for (size_t i=0; i<list.size(); i++)
74  {
75  if (list[i]->getFilename() == filename)
76  {
77  return static_cast<int>(i);
78  }
79  }
80 
81  return -1;
82 }
83 
84 #ifdef _WIN32
85 static std::string getPathToThisDll()
86 {
87  HMODULE hm = nullptr;
88  if (GetModuleHandleEx(
89  GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
90  GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
91  reinterpret_cast<LPCSTR>(&getPathToThisDll), &hm) == 0)
92  {
93  return {};
94  }
95 
96  char path[MAX_PATH];
97  if (GetModuleFileName(hm, path, sizeof(path)) == 0)
98  {
99  return {};
100  }
101 
102  std::string p{ path };
103  const auto bs_pos = p.rfind('\\');
104  if (bs_pos != std::string::npos)
105  {
106  p = p.substr(0, bs_pos);
107  }
108 
109  return p;
110 }
111 
112 #endif
113 
114 }
115 
116 std::vector<std::shared_ptr<System> > System::getSystems()
117 {
118  std::lock_guard<std::mutex> lock(system_mtx);
119  std::vector<std::shared_ptr<System> > ret;
120 
121  // get list of all available transport layer libraries
122 
123  const char *env=0;
124  if (sizeof(size_t) == 8)
125  {
126  env="GENICAM_GENTL64_PATH";
127  }
128  else
129  {
130  env="GENICAM_GENTL32_PATH";
131  }
132 
133  std::string path;
134 
135  const char *envpath=std::getenv(env);
136  if (envpath != 0)
137  {
138  path=envpath;
139  }
140 
141  if (path.size() == 0)
142  {
143 #ifdef _WIN32
144  // under Windows, use the path to the current executable as fallback
145 
146  const size_t n=256;
147  char procpath[n];
148  std::string path_to_exe;
149  if (GetModuleFileName(NULL, procpath, n-1) > 0)
150  {
151  procpath[n-1]='\0';
152 
153  char *p=strrchr(procpath, '\\');
154  if (p != 0) *p='\0';
155 
156  path_to_exe=procpath;
157  path+=";" + path_to_exe;
158  }
159 
160  const auto path_to_this_dll = getPathToThisDll();
161  if (!path_to_this_dll.empty() && path_to_this_dll != path_to_exe)
162  {
163  path += ";" + path_to_this_dll;
164  }
165 #else
166  // otherwise, use the absolute install path to the default transport layer
167 
168  path=GENTL_INSTALL_PATH;
169 #endif
170  }
171 
172  std::vector<std::string> name=getAvailableGenTLs(path.c_str());
173 
174  // create list of systems according to the list, using either existing
175  // systems or instantiating new ones
176 
177  for (size_t i=0; i<name.size(); i++)
178  {
179  int k=find(slist, name[i]);
180 
181  if (k >= 0)
182  {
183  ret.push_back(slist[static_cast<size_t>(k)]);
184  }
185  else
186  {
187  try
188  {
189  System *p=new System(name[i]);
190  ret.push_back(std::shared_ptr<System>(p));
191  }
192  catch (const std::exception &)
193  {
194  // ignore transport layers that cannot be used
195  }
196  }
197  }
198 
199  // remember returned list for reusing existing systems on the next call
200 
201  slist=ret;
202 
203  // throw exception if no transport layers are available
204 
205  if (ret.size() == 0)
206  {
207  throw GenTLException(std::string("No transport layers found in path ")+path);
208  }
209 
210  return ret;
211 }
212 
214 {
215  std::lock_guard<std::mutex> lock(system_mtx);
216 
217  // clear all interfaces explicitly as part of ENUM-WORKAROUND
218  for (size_t i=0; i<slist.size(); i++)
219  {
220  slist[i]->clearInterfaces();
221  }
222 
223  slist.clear();
224 }
225 
226 const std::string &System::getFilename() const
227 {
228  return filename;
229 }
230 
232 {
233  std::lock_guard<std::recursive_mutex> lock(mtx);
234 
235  if (n_open == 0)
236  {
237  if (gentl->TLOpen(&tl) != GenTL::GC_ERR_SUCCESS)
238  {
239  throw GenTLException("System::open()", gentl);
240  }
241  }
242 
243  n_open++;
244 }
245 
247 {
248  std::lock_guard<std::recursive_mutex> lock(mtx);
249 
250  if (n_open > 0)
251  {
252  n_open--;
253  }
254 
255  if (n_open == 0)
256  {
257  gentl->TLClose(tl);
258  tl=0;
259 
260  nodemap=0;
261  cport=0;
262  }
263 }
264 
265 namespace
266 {
267 
268 int find(const std::vector<std::shared_ptr<Interface> > &list, const std::string &id)
269 {
270  for (size_t i=0; i<list.size(); i++)
271  {
272  if (list[i]->getID() == id)
273  {
274  return static_cast<int>(i);
275  }
276  }
277 
278  return -1;
279 }
280 
281 }
282 
283 std::vector<std::shared_ptr<Interface> > System::getInterfaces()
284 {
285  std::lock_guard<std::recursive_mutex> lock(mtx);
286  std::vector<std::shared_ptr<Interface> > ret=ilist;
287 
288  // ENUM-WORKAROUND: Interfaces are only enumerated once and kept open as a
289  // (temporary) workaround for a bug in the Baumer GenTL layer 2.1.0 for GEV
290  // that is used by default. The bug causes memory and CPU time to
291  // increase on every call of TLUpdateInterfaceList().
292 
293  if (tl != 0 && ilist.size() == 0)
294  {
295  // get list of previously requested interfaces that are still in use
296 
297  std::vector<std::shared_ptr<Interface> > current;
298 
299 /*
300  for (size_t i=0; i<ilist.size(); i++)
301  {
302  std::shared_ptr<Interface> p=ilist[i].lock();
303  if (p)
304  {
305  current.push_back(p);
306  }
307  }
308 */
309 
310  // update available interfaces
311 
312  if (gentl->TLUpdateInterfaceList(tl, 0, 10) != GenTL::GC_ERR_SUCCESS)
313  {
314  throw GenTLException("System::getInterfaces()", gentl);
315  }
316 
317  // create list of interfaces, using either existing interfaces or
318  // instantiating new ones
319 
320  uint32_t n=0;
321  if (gentl->TLGetNumInterfaces(tl, &n) != GenTL::GC_ERR_SUCCESS)
322  {
323  throw GenTLException("System::getInterfaces()", gentl);
324  }
325 
326  for (uint32_t i=0; i<n; i++)
327  {
328  char tmp[256]="";
329  size_t size=sizeof(tmp);
330 
331  if (gentl->TLGetInterfaceID(tl, i, tmp, &size) != GenTL::GC_ERR_SUCCESS)
332  {
333  throw GenTLException("System::getInterfaces()", gentl);
334  }
335 
336  int k=find(current, tmp);
337 
338  if (k >= 0)
339  {
340  ret.push_back(current[static_cast<size_t>(k)]);
341  }
342  else
343  {
344  ret.push_back(std::shared_ptr<Interface>(new Interface(shared_from_this(), gentl, tmp)));
345  }
346  }
347 
348  // update internal list of interfaces for reusage on next call
349 
350  ilist.clear();
351  for (size_t i=0; i<ret.size(); i++)
352  {
353  ilist.push_back(ret[i]);
354  }
355 
356  // open interfaces to avoid re-enumeration as part of ENUM-WORKAROUND
357 
358  for (size_t i=0; i<ret.size(); i++)
359  {
360  ret[i]->open();
361  }
362  }
363 
364  return ret;
365 }
366 
367 namespace
368 {
369 
370 std::string cTLGetInfo(GenTL::TL_HANDLE tl, const std::shared_ptr<const GenTLWrapper> &gentl,
371  GenTL::TL_INFO_CMD info)
372 {
373  std::string ret;
374 
376  char tmp[1024]="";
377  size_t tmp_size=sizeof(tmp);
379 
380  if (tl != 0)
381  {
382  err=gentl->TLGetInfo(tl, info, &type, tmp, &tmp_size);
383  }
384  else
385  {
386  err=gentl->GCGetInfo(info, &type, tmp, &tmp_size);
387  }
388 
390  {
391  for (size_t i=0; i<tmp_size && tmp[i] != '\0'; i++)
392  {
393  ret.push_back(tmp[i]);
394  }
395  }
396 
397  return ret;
398 }
399 
400 }
401 
402 std::string System::getID()
403 {
404  std::lock_guard<std::recursive_mutex> lock(mtx);
405  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_ID);
406 }
407 
408 std::string System::getVendor()
409 {
410  std::lock_guard<std::recursive_mutex> lock(mtx);
411  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_VENDOR);
412 }
413 
414 std::string System::getModel()
415 {
416  std::lock_guard<std::recursive_mutex> lock(mtx);
417  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_MODEL);
418 }
419 
420 std::string System::getVersion()
421 {
422  std::lock_guard<std::recursive_mutex> lock(mtx);
423  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_VERSION);
424 }
425 
426 std::string System::getTLType()
427 {
428  std::lock_guard<std::recursive_mutex> lock(mtx);
429  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_TLTYPE);
430 }
431 
432 std::string System::getName()
433 {
434  std::lock_guard<std::recursive_mutex> lock(mtx);
435  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_NAME);
436 }
437 
438 std::string System::getPathname()
439 {
440  std::lock_guard<std::recursive_mutex> lock(mtx);
441  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_PATHNAME);
442 }
443 
445 {
446  std::lock_guard<std::recursive_mutex> lock(mtx);
447  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_DISPLAYNAME);
448 }
449 
451 {
452  std::lock_guard<std::recursive_mutex> lock(mtx);
453  bool ret=true;
454 
456  int32_t v;
457  size_t size=sizeof(v);
459 
460  if (tl != 0)
461  {
462  err=gentl->TLGetInfo(tl, GenTL::TL_INFO_CHAR_ENCODING, &type, &v, &size);
463  }
464  else
465  {
466  err=gentl->GCGetInfo(GenTL::TL_INFO_CHAR_ENCODING, &type, &v, &size);
467  }
468 
469  if (err == GenTL::GC_ERR_SUCCESS && type == GenTL::INFO_DATATYPE_INT32 &&
471  {
472  ret=false;
473  }
474 
475  return ret;
476 }
477 
479 {
480  std::lock_guard<std::recursive_mutex> lock(mtx);
481  uint32_t ret=0;
482 
484  size_t size=sizeof(ret);
485 
486  if (tl != 0)
487  {
488  gentl->TLGetInfo(tl, GenTL::TL_INFO_GENTL_VER_MAJOR, &type, &ret, &size);
489  }
490  else
491  {
492  gentl->GCGetInfo(GenTL::TL_INFO_GENTL_VER_MAJOR, &type, &ret, &size);
493  }
494 
495  return static_cast<int>(ret);
496 }
497 
499 {
500  std::lock_guard<std::recursive_mutex> lock(mtx);
501  uint32_t ret=0;
502 
504  size_t size=sizeof(ret);
505 
506  if (tl != 0)
507  {
508  gentl->TLGetInfo(tl, GenTL::TL_INFO_GENTL_VER_MINOR, &type, &ret, &size);
509  }
510  else
511  {
512  gentl->GCGetInfo(GenTL::TL_INFO_GENTL_VER_MINOR, &type, &ret, &size);
513  }
514 
515  return static_cast<int>(ret);
516 }
517 
518 std::shared_ptr<GenApi::CNodeMapRef> System::getNodeMap()
519 {
520  std::lock_guard<std::recursive_mutex> lock(mtx);
521  if (tl != 0 && !nodemap)
522  {
523  cport=std::shared_ptr<CPort>(new CPort(gentl, &tl));
524  nodemap=allocNodeMap(gentl, tl, cport.get());
525  }
526 
527  return nodemap;
528 }
529 
530 void *System::getHandle() const
531 {
532  return tl;
533 }
534 
536 {
537  // close and clear all interfaces as part of ENUM-WORKAROUND
538  for (size_t i=0; i<ilist.size(); i++)
539  {
540  ilist[i]->close();
541  }
542 
543  ilist.clear();
544 }
545 
546 System::System(const std::string &_filename)
547 {
548  filename=_filename;
549 
550  gentl=std::shared_ptr<const GenTLWrapper>(new GenTLWrapper(filename));
551 
552  if (gentl->GCInitLib() != GenTL::GC_ERR_SUCCESS)
553  {
554  throw GenTLException("System::System()", gentl);
555  }
556 
557  n_open=0;
558  tl=0;
559 }
560 
561 }
System(const std::string &_filename)
Definition: system.cc:546
std::string getDisplayName()
Returns the display name of the GenTL provider.
Definition: system.cc:444
std::shared_ptr< GenApi::CNodeMapRef > nodemap
Definition: system.h:243
const std::string & getFilename() const
Get file name from which this system was created.
Definition: system.cc:226
This is the port definition that connects GenAPI to GenTL.
Definition: cport.h:52
void * tl
Definition: system.h:240
int32_t TL_INFO_CMD
Definition: GenTL_v1_5.h:284
static std::vector< std::shared_ptr< System > > getSystems()
Returns a list of systems (i.e.
Definition: system.cc:116
void * getHandle() const
Get internal handle of open transport layer.
Definition: system.cc:530
std::shared_ptr< CPort > cport
Definition: system.h:242
std::vector< std::shared_ptr< Interface > > getInterfaces()
Returns the currently available interfaces.
Definition: system.cc:283
void close()
Closes the system.
Definition: system.cc:246
The system class encapsulates a Genicam transport layer.
Definition: system.h:58
std::shared_ptr< const GenTLWrapper > gentl
Definition: system.h:235
int32_t GC_ERROR
Definition: GenTL_v1_5.h:181
static void clearSystems()
Clears the internal list of systems.
Definition: system.cc:213
int n_open
Definition: system.h:239
std::string getVendor()
Returns the vendor name of the GenTL provider.
Definition: system.cc:408
void * TL_HANDLE
Definition: GenTL_v1_5.h:218
int getMinorVersion()
Returns the minor version number.
Definition: system.cc:498
void clearInterfaces()
Definition: system.cc:535
std::recursive_mutex mtx
Definition: system.h:237
void open()
Opens the system for working with it.
Definition: system.cc:231
std::shared_ptr< GenApi::CNodeMapRef > getNodeMap()
Returns the node map of this object.
Definition: system.cc:518
std::string getName()
Returns the file name of the GenTL provider.
Definition: system.cc:432
std::vector< std::string > getAvailableGenTLs(const char *paths)
The function uses the given list files of paths that is separated by colons or semicolons, depending on the used operating system, and returns all files with the suffix .cti.
Wrapper for dynamically loaded GenICam transport layers.
Definition: gentl_wrapper.h:62
std::shared_ptr< GenApi::CNodeMapRef > allocNodeMap(std::shared_ptr< const GenTLWrapper > gentl, void *port, CPort *cport, const char *xml)
Convenience function that returns a GenICam node map from the given port.
Definition: cport.cc:133
bool isCharEncodingASCII()
Returns the character encoding.
Definition: system.cc:450
Definition: buffer.cc:47
std::string getVersion()
Returns the version of the GenTL provider.
Definition: system.cc:420
std::string getModel()
Returns the model of the GenTL provider.
Definition: system.cc:414
std::string getPathname()
Returns the full path name of the GenTL provider.
Definition: system.cc:438
std::string filename
Definition: system.h:234
std::string getTLType()
Returns the transport layer type of the GenTL provider.
Definition: system.cc:426
int32_t INFO_DATATYPE
Definition: GenTL_v1_5.h:258
int getMajorVersion()
Returns the major version number.
Definition: system.cc:478
The interface class encapsulates a Genicam interface.
Definition: interface.h:54
std::vector< std::shared_ptr< Interface > > ilist
Definition: system.h:246
std::string getID()
Returns the ID of the GenTL provider.
Definition: system.cc:402


rc_genicam_api
Author(s): Heiko Hirschmueller
autogenerated on Wed Mar 17 2021 02:48:41