All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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::recursive_mutex system_mtx;
69 std::vector<std::shared_ptr<System> > system_list;
70 std::string system_path;
71 std::string system_ignore;
72 
73 int find(const std::vector<std::shared_ptr<System> > &list, const std::string &filename)
74 {
75  for (size_t i=0; i<list.size(); i++)
76  {
77  if (list[i]->getFilename() == filename)
78  {
79  return static_cast<int>(i);
80  }
81  }
82 
83  return -1;
84 }
85 
86 #ifdef _WIN32
87 static std::string getPathToThisDll()
88 {
89  HMODULE hm = nullptr;
90  if (GetModuleHandleExA(
91  GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
92  GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
93  reinterpret_cast<LPCSTR>(&getPathToThisDll), &hm) == 0)
94  {
95  return {};
96  }
97 
98  char path[MAX_PATH];
99  if (GetModuleFileNameA(hm, path, sizeof(path)) == 0)
100  {
101  return {};
102  }
103 
104  std::string p{ path };
105  const auto bs_pos = p.rfind('\\');
106  if (bs_pos != std::string::npos)
107  {
108  p = p.substr(0, bs_pos);
109  }
110 
111  return p;
112 }
113 
114 #endif
115 
116 }
117 
118 bool System::setSystemsPath(const char *path, const char *ignore)
119 {
120  std::lock_guard<std::recursive_mutex> lock(system_mtx);
121 
122  if (system_list.size() == 0)
123  {
124  system_path="";
125  system_ignore="";
126 
127  if (path == 0 || path[0] == '\0')
128  {
129 #ifdef _WIN32
130  // under Windows, use the path to the current executable as fallback
131 
132  const size_t n=256;
133  char procpath[n];
134  std::string path_to_exe;
135  if (GetModuleFileNameA(NULL, procpath, n-1) > 0)
136  {
137  procpath[n-1]='\0';
138 
139  char *p=strrchr(procpath, '\\');
140  if (p != 0) *p='\0';
141 
142  path_to_exe=procpath;
143 
144  if (system_path.size() > 0) system_path+=";";
145 
146  system_path += path_to_exe;
147  }
148 
149  // another fallback is the path to the current library
150 
151  const auto path_to_this_dll = getPathToThisDll();
152  if (!path_to_this_dll.empty() && path_to_this_dll != path_to_exe)
153  {
154  if (system_path.size() > 0) system_path+=";";
155 
156  system_path += path_to_this_dll;
157  }
158 
159  // and possible sub-directories of the library
160 
161  HANDLE file_handle;
162  WIN32_FIND_DATAA file_info;
163 
164  file_handle=FindFirstFileA((path_to_this_dll+"\\*").c_str(), &file_info);
165 
166  if (file_handle != INVALID_HANDLE_VALUE)
167  {
168  do
169  {
170  if ((file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 && file_info.cFileName[0] != '.' )
171  {
172  system_path += ";" + path_to_this_dll + "\\" + file_info.cFileName;
173  }
174  }
175  while (FindNextFileA(file_handle, &file_info));
176 
177  FindClose(file_handle);
178  }
179 #else
180  // otherwise, use the absolute install path to the default transport layer
181 
182  system_path=GENTL_INSTALL_PATH;
183 #endif
184  }
185  else
186  {
187  system_path=path;
188  }
189 
190  if (ignore != 0)
191  {
192  system_ignore=ignore;
193  }
194 
195  return true;
196  }
197 
198  return false;
199 }
200 
201 std::vector<std::shared_ptr<System> > System::getSystems()
202 {
203  std::lock_guard<std::recursive_mutex> lock(system_mtx);
204  std::vector<std::shared_ptr<System> > ret;
205 
206  // ensure that system_path is defined
207 
208  if (system_path.size() == 0)
209  {
210  const char *env=0;
211  if (sizeof(size_t) == 8)
212  {
213  env="GENICAM_GENTL64_PATH";
214  }
215  else
216  {
217  env="GENICAM_GENTL32_PATH";
218  }
219 
220  setSystemsPath(std::getenv(env), 0);
221  }
222 
223  // get list of all available transport layer libraries
224 
225  std::vector<std::string> name=getAvailableGenTLs(system_path.c_str());
226  std::ostringstream info;
227 
228  // create list of systems according to the list, using either existing
229  // systems or instantiating new ones
230 
231  for (size_t i=0; i<name.size(); i++)
232  {
233  int k=find(system_list, name[i]);
234 
235  if (system_ignore.size() > 0)
236  {
237  // skipping if name equals ignore
238 
239  if (name[i].size() >= system_ignore.size() &&
240  name[i].substr(name[i].size()-system_ignore.size()) == system_ignore)
241  {
242  continue;
243  }
244  }
245 
246  if (k >= 0)
247  {
248  ret.push_back(system_list[static_cast<size_t>(k)]);
249  }
250  else
251  {
252  try
253  {
254  System *p=new System(name[i]);
255  ret.push_back(std::shared_ptr<System>(p));
256  }
257  catch (const std::exception &ex)
258  {
259  // ignore transport layers that cannot be used, but collect reason
260  // for failure
261 
262  info << ex.what() << std::endl;
263  }
264  }
265  }
266 
267  // remember returned list for reusing existing systems on the next call
268 
269  system_list=ret;
270 
271  // throw exception if no transport layers are available
272 
273  if (ret.size() == 0)
274  {
275  info << "No transport layers found in path: " << system_path;
276  throw GenTLException(info.str());
277  }
278 
279  return ret;
280 }
281 
283 {
284  std::lock_guard<std::recursive_mutex> lock(system_mtx);
285 
286  // clear all interfaces explicitly as part of ENUM-WORKAROUND
287  for (size_t i=0; i<system_list.size(); i++)
288  {
289  system_list[i]->clearInterfaces();
290  }
291 
292  system_list.clear();
293 }
294 
295 const std::string &System::getFilename() const
296 {
297  return filename;
298 }
299 
301 {
302  std::lock_guard<std::recursive_mutex> lock(mtx);
303 
304  if (n_open == 0)
305  {
306  if (gentl->TLOpen(&tl) != GenTL::GC_ERR_SUCCESS)
307  {
308  throw GenTLException("System::open()", gentl);
309  }
310  }
311 
312  n_open++;
313 }
314 
316 {
317  std::lock_guard<std::recursive_mutex> lock(mtx);
318 
319  if (n_open > 0)
320  {
321  n_open--;
322 
323  if (n_open == 0)
324  {
325  gentl->TLClose(tl);
326  tl=0;
327 
328  nodemap=0;
329  cport=0;
330  }
331  }
332 }
333 
334 namespace
335 {
336 
337 int find(const std::vector<std::shared_ptr<Interface> > &list, const std::string &id)
338 {
339  for (size_t i=0; i<list.size(); i++)
340  {
341  if (list[i]->getID() == id)
342  {
343  return static_cast<int>(i);
344  }
345  }
346 
347  return -1;
348 }
349 
350 }
351 
352 std::vector<std::shared_ptr<Interface> > System::getInterfaces()
353 {
354  std::lock_guard<std::recursive_mutex> lock(mtx);
355  std::vector<std::shared_ptr<Interface> > ret=ilist;
356 
357  // ENUM-WORKAROUND: Interfaces are only enumerated once and kept open as a
358  // (temporary) workaround for a bug in the Baumer GenTL layer 2.1.0 for GEV
359  // that is used by default. The bug causes memory and CPU time to
360  // increase on every call of TLUpdateInterfaceList().
361 
362  if (tl != 0 && ilist.size() == 0)
363  {
364  // get list of previously requested interfaces that are still in use
365 
366  std::vector<std::shared_ptr<Interface> > current;
367 
368 /*
369  for (size_t i=0; i<ilist.size(); i++)
370  {
371  std::shared_ptr<Interface> p=ilist[i].lock();
372  if (p)
373  {
374  current.push_back(p);
375  }
376  }
377 */
378 
379  // update available interfaces
380 
381  if (gentl->TLUpdateInterfaceList(tl, 0, 10) != GenTL::GC_ERR_SUCCESS)
382  {
383  throw GenTLException("System::getInterfaces()", gentl);
384  }
385 
386  // create list of interfaces, using either existing interfaces or
387  // instantiating new ones
388 
389  uint32_t n=0;
390  if (gentl->TLGetNumInterfaces(tl, &n) != GenTL::GC_ERR_SUCCESS)
391  {
392  throw GenTLException("System::getInterfaces()", gentl);
393  }
394 
395  for (uint32_t i=0; i<n; i++)
396  {
397  char tmp[256]="";
398  size_t size=sizeof(tmp);
399 
400  if (gentl->TLGetInterfaceID(tl, i, tmp, &size) != GenTL::GC_ERR_SUCCESS)
401  {
402  throw GenTLException("System::getInterfaces()", gentl);
403  }
404 
405  int k=find(current, tmp);
406 
407  if (k >= 0)
408  {
409  ret.push_back(current[static_cast<size_t>(k)]);
410  }
411  else
412  {
413  ret.push_back(std::shared_ptr<Interface>(new Interface(shared_from_this(), gentl, tmp)));
414  }
415  }
416 
417  // update internal list of interfaces for reusage on next call
418 
419  ilist.clear();
420  for (size_t i=0; i<ret.size(); i++)
421  {
422  ilist.push_back(ret[i]);
423  }
424 
425  // open interfaces to avoid re-enumeration as part of ENUM-WORKAROUND
426 
427  for (size_t i=0; i<ret.size(); i++)
428  {
429  ret[i]->open();
430  }
431  }
432 
433  return ret;
434 }
435 
436 namespace
437 {
438 
439 std::string cTLGetInfo(GenTL::TL_HANDLE tl, const std::shared_ptr<const GenTLWrapper> &gentl,
440  GenTL::TL_INFO_CMD info)
441 {
442  std::string ret;
443 
445  char tmp[1024]="";
446  size_t tmp_size=sizeof(tmp);
448 
449  if (tl != 0)
450  {
451  err=gentl->TLGetInfo(tl, info, &type, tmp, &tmp_size);
452  }
453  else
454  {
455  err=gentl->GCGetInfo(info, &type, tmp, &tmp_size);
456  }
457 
459  {
460  for (size_t i=0; i<tmp_size && tmp[i] != '\0'; i++)
461  {
462  ret.push_back(tmp[i]);
463  }
464  }
465 
466  return ret;
467 }
468 
469 }
470 
471 std::string System::getID()
472 {
473  std::lock_guard<std::recursive_mutex> lock(mtx);
474  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_ID);
475 }
476 
477 std::string System::getVendor()
478 {
479  std::lock_guard<std::recursive_mutex> lock(mtx);
480  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_VENDOR);
481 }
482 
483 std::string System::getModel()
484 {
485  std::lock_guard<std::recursive_mutex> lock(mtx);
486  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_MODEL);
487 }
488 
489 std::string System::getVersion()
490 {
491  std::lock_guard<std::recursive_mutex> lock(mtx);
492  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_VERSION);
493 }
494 
495 std::string System::getTLType()
496 {
497  std::lock_guard<std::recursive_mutex> lock(mtx);
498  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_TLTYPE);
499 }
500 
501 std::string System::getName()
502 {
503  std::lock_guard<std::recursive_mutex> lock(mtx);
504  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_NAME);
505 }
506 
507 std::string System::getPathname()
508 {
509  std::lock_guard<std::recursive_mutex> lock(mtx);
510  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_PATHNAME);
511 }
512 
514 {
515  std::lock_guard<std::recursive_mutex> lock(mtx);
516  return cTLGetInfo(tl, gentl, GenTL::TL_INFO_DISPLAYNAME);
517 }
518 
520 {
521  std::lock_guard<std::recursive_mutex> lock(mtx);
522  bool ret=true;
523 
525  int32_t v;
526  size_t size=sizeof(v);
528 
529  if (tl != 0)
530  {
531  err=gentl->TLGetInfo(tl, GenTL::TL_INFO_CHAR_ENCODING, &type, &v, &size);
532  }
533  else
534  {
535  err=gentl->GCGetInfo(GenTL::TL_INFO_CHAR_ENCODING, &type, &v, &size);
536  }
537 
538  if (err == GenTL::GC_ERR_SUCCESS && type == GenTL::INFO_DATATYPE_INT32 &&
540  {
541  ret=false;
542  }
543 
544  return ret;
545 }
546 
548 {
549  std::lock_guard<std::recursive_mutex> lock(mtx);
550  uint32_t ret=0;
551 
553  size_t size=sizeof(ret);
554 
555  if (tl != 0)
556  {
557  gentl->TLGetInfo(tl, GenTL::TL_INFO_GENTL_VER_MAJOR, &type, &ret, &size);
558  }
559  else
560  {
561  gentl->GCGetInfo(GenTL::TL_INFO_GENTL_VER_MAJOR, &type, &ret, &size);
562  }
563 
564  return static_cast<int>(ret);
565 }
566 
568 {
569  std::lock_guard<std::recursive_mutex> lock(mtx);
570  uint32_t ret=0;
571 
573  size_t size=sizeof(ret);
574 
575  if (tl != 0)
576  {
577  gentl->TLGetInfo(tl, GenTL::TL_INFO_GENTL_VER_MINOR, &type, &ret, &size);
578  }
579  else
580  {
581  gentl->GCGetInfo(GenTL::TL_INFO_GENTL_VER_MINOR, &type, &ret, &size);
582  }
583 
584  return static_cast<int>(ret);
585 }
586 
587 std::shared_ptr<GenApi::CNodeMapRef> System::getNodeMap()
588 {
589  std::lock_guard<std::recursive_mutex> lock(mtx);
590  if (tl != 0 && !nodemap)
591  {
592  cport=std::shared_ptr<CPort>(new CPort(gentl, &tl));
593  nodemap=allocNodeMap(gentl, tl, cport.get());
594  }
595 
596  return nodemap;
597 }
598 
599 void *System::getHandle() const
600 {
601  return tl;
602 }
603 
605 {
606  // close and clear all interfaces as part of ENUM-WORKAROUND
607  for (size_t i=0; i<ilist.size(); i++)
608  {
609  ilist[i]->close();
610  }
611 
612  ilist.clear();
613 }
614 
615 System::System(const std::string &_filename)
616 {
617  filename=_filename;
618 
619  gentl=std::shared_ptr<const GenTLWrapper>(new GenTLWrapper(filename));
620 
621  if (gentl->GCInitLib() != GenTL::GC_ERR_SUCCESS)
622  {
623  throw GenTLException("System::System()", gentl);
624  }
625 
626  n_open=0;
627  tl=0;
628 }
629 
630 }
rcg::getAvailableGenTLs
std::vector< std::string > getAvailableGenTLs(const char *paths)
The function uses the given list files of paths that is separated by colons or semicolons,...
Definition: gentl_wrapper_linux.cc:50
TL_INFO_ID
@ TL_INFO_ID
Definition: GenTL_v1_6.h:274
INFO_DATATYPE
int32_t INFO_DATATYPE
Definition: GenTL_v1_6.h:261
INFO_DATATYPE_STRING
@ INFO_DATATYPE_STRING
Definition: GenTL_v1_6.h:244
rcg::System::getNodeMap
std::shared_ptr< GenApi::CNodeMapRef > getNodeMap()
Returns the node map of this object.
Definition: system.cc:587
rcg::System::getMinorVersion
int getMinorVersion()
Returns the minor version number.
Definition: system.cc:567
TL_INFO_VERSION
@ TL_INFO_VERSION
Definition: GenTL_v1_6.h:277
rcg::System::System
System(const std::string &_filename)
Definition: system.cc:615
rcg::System::close
void close()
Closes the system.
Definition: system.cc:315
rcg::System::nodemap
std::shared_ptr< GenApi::CNodeMapRef > nodemap
Definition: system.h:268
TL_CHAR_ENCODING_ASCII
@ TL_CHAR_ENCODING_ASCII
Definition: GenTL_v1_6.h:266
rcg::System::getVendor
std::string getVendor()
Returns the vendor name of the GenTL provider.
Definition: system.cc:477
rcg::System::getVersion
std::string getVersion()
Returns the version of the GenTL provider.
Definition: system.cc:489
TL_INFO_GENTL_VER_MAJOR
@ TL_INFO_GENTL_VER_MAJOR
Definition: GenTL_v1_6.h:283
TL_INFO_VENDOR
@ TL_INFO_VENDOR
Definition: GenTL_v1_6.h:275
rcg::System
The system class encapsulates a Genicam transport layer.
Definition: system.h:58
rcg::System::getHandle
void * getHandle() const
Get internal handle of open transport layer.
Definition: system.cc:599
rcg::System::getInterfaces
std::vector< std::shared_ptr< Interface > > getInterfaces()
Returns the currently available interfaces.
Definition: system.cc:352
rcg::System::tl
void * tl
Definition: system.h:265
TL_INFO_GENTL_VER_MINOR
@ TL_INFO_GENTL_VER_MINOR
Definition: GenTL_v1_6.h:284
TL_INFO_TLTYPE
@ TL_INFO_TLTYPE
Definition: GenTL_v1_6.h:278
rcg::System::~System
~System()
Definition: system.cc:55
GC_ERROR
int32_t GC_ERROR
Definition: GenTL_v1_6.h:185
rcg
Definition: buffer.cc:47
rcg::System::getModel
std::string getModel()
Returns the model of the GenTL provider.
Definition: system.cc:483
rcg::System::open
void open()
Opens the system for working with it.
Definition: system.cc:300
TL_INFO_CMD
int32_t TL_INFO_CMD
Definition: GenTL_v1_6.h:287
rcg::System::cport
std::shared_ptr< CPort > cport
Definition: system.h:267
rcg::System::mtx
std::recursive_mutex mtx
Definition: system.h:262
rcg::GenTLWrapper
Wrapper for dynamically loaded GenICam transport layers.
Definition: gentl_wrapper.h:62
rcg::CPort
This is the port definition that connects GenAPI to GenTL.
Definition: cport.h:52
TL_INFO_CHAR_ENCODING
@ TL_INFO_CHAR_ENCODING
Definition: GenTL_v1_6.h:282
rcg::System::getFilename
const std::string & getFilename() const
Get file name from which this system was created.
Definition: system.cc:295
GC_ERR_SUCCESS
@ GC_ERR_SUCCESS
Definition: GenTL_v1_6.h:158
rcg::System::getName
std::string getName()
Returns the file name of the GenTL provider.
Definition: system.cc:501
rcg::System::clearSystems
static void clearSystems()
Clears the internal list of systems.
Definition: system.cc:282
rcg::allocNodeMap
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:156
rcg::System::filename
std::string filename
Definition: system.h:259
rcg::System::getTLType
std::string getTLType()
Returns the transport layer type of the GenTL provider.
Definition: system.cc:495
interface.h
rcg::Interface
The interface class encapsulates a Genicam interface.
Definition: interface.h:54
rcg::System::getMajorVersion
int getMajorVersion()
Returns the major version number.
Definition: system.cc:547
rcg::System::n_open
int n_open
Definition: system.h:264
TL_HANDLE
void * TL_HANDLE
Definition: GenTL_v1_6.h:222
rcg::System::getPathname
std::string getPathname()
Returns the full path name of the GenTL provider.
Definition: system.cc:507
rcg::System::gentl
std::shared_ptr< const GenTLWrapper > gentl
Definition: system.h:260
TL_INFO_NAME
@ TL_INFO_NAME
Definition: GenTL_v1_6.h:279
system.h
rcg::System::clearInterfaces
void clearInterfaces()
Definition: system.cc:604
rcg::System::setSystemsPath
static bool setSystemsPath(const char *path, const char *ignore)
Set the path for finding GenTL producers on the file system and the name of a producer that should be...
Definition: system.cc:118
rcg::System::getID
std::string getID()
Returns the ID of the GenTL provider.
Definition: system.cc:471
std::ostringstream::str
std::string str()
INFO_DATATYPE_INT32
@ INFO_DATATYPE_INT32
Definition: GenTL_v1_6.h:248
std::ostringstream
Definition: Portability.hh:42
rcg::System::getDisplayName
std::string getDisplayName()
Returns the display name of the GenTL provider.
Definition: system.cc:513
TL_INFO_MODEL
@ TL_INFO_MODEL
Definition: GenTL_v1_6.h:276
cport.h
exception.h
rcg::System::ilist
std::vector< std::shared_ptr< Interface > > ilist
Definition: system.h:271
rcg::System::getSystems
static std::vector< std::shared_ptr< System > > getSystems()
This function creates systems for all producers that can be found.
Definition: system.cc:201
gentl_wrapper.h
TL_INFO_DISPLAYNAME
@ TL_INFO_DISPLAYNAME
Definition: GenTL_v1_6.h:281
TL_INFO_PATHNAME
@ TL_INFO_PATHNAME
Definition: GenTL_v1_6.h:280
rcg::GenTLException
Definition: exception.h:47
rcg::System::isCharEncodingASCII
bool isCharEncodingASCII()
Returns the character encoding.
Definition: system.cc:519


rc_genicam_api
Author(s): Heiko Hirschmueller
autogenerated on Wed Dec 4 2024 03:10:12