cpluginsvc.py
Go to the documentation of this file.
1 ## cpluginsvc is a ctypes-based wrapper for the C-exposed API of GaudiPluginService
2 __doc__ = '''
3 cpluginsvc is a ctypes-based wrapper for the C-API of the GaudiPluginService.
4 
5 e.g.:
6 
7 >>> from GaudiPluginService import cpluginsvc
8 >>> for _,f in cpluginsvc.factories().items():
9 ... try:
10 ... f.load()
11 ... except Exception:
12 ... print ("** could not load [%s] for factory [%s]" % (f.library, f.name))
13 ... continue
14 ... print f
15 ... for k,v in f.properties.iteritems():
16 ... print ("\t%s: %s" % (k,v))
17 '''
18 
19 import ctypes
20 import ctypes.util
21 
22 __all__ = (
23  "Registry",
24  "registry",
25  "factories",
26  "Factory",
27  "Property",
28  )
29 
30 _libname = None
32  if _libname:
33  return _libname
34  import platform
35  name = platform.system()
36 
37  fname = {
38  'Darwin': "libGaudiPluginService.so", # or .dylib ? FIXME
39  'Windows': "libGaudiPluginService.dll",
40  'Linux': "libGaudiPluginService.so",
41  }[name]
42  return fname
43 
44 _libname = _get_filename()
45 _lib = ctypes.cdll.LoadLibrary(_libname)
46 
47 class Registry(ctypes.Structure):
48  '''Registry holds the list of factories known by the gaudi PluginService.
49  '''
50  _fields_ = [("_registry", ctypes.c_void_p)]
51 
52  @property
53  def factories(self):
54  facts = {}
55  n = _lib.cgaudi_pluginsvc_get_factory_size(self)
56  for i in range(n):
57  f = _lib.cgaudi_pluginsvc_get_factory_at(self, i)
58  facts[f.name] = f
59  return facts
60  pass
61 
62 _instance = None
63 def registry():
64  '''registry returns the singleton-like instance of the plugin service.'''
65 
66  global _instance
67  if _instance:
68  return _instance
69  _instance = _lib.cgaudi_pluginsvc_instance()
70  return _instance
71 
72 def factories():
73  '''
74  factories returns the list of components factory informations known to the plugin service
75  '''
76  return registry().factories
77 
78 class Factory(ctypes.Structure):
79  """
80  Factory holds informations about a component's factory:
81  - its name
82  - the library hosting that component
83  - the type of component (algorithm, service, tool, ...)
84  - the return type of this factory
85  - the C++ class name of that component
86  - the properties which may decorate that component.
87  """
88  _fields_ = [
89  ("_registry", Registry),
90  ("_id", ctypes.c_char_p),
91  ]
92 
93  @property
94  def name(self):
95  return self._id
96 
97  @property
98  def library(self):
99  return _lib.cgaudi_factory_get_library(self)
100 
101  @property
102  def type(self):
103  return _lib.cgaudi_factory_get_type(self)
104 
105  @property
106  def rtype(self):
107  return _lib.cgaudi_factory_get_rtype(self)
108 
109  @property
110  def classname(self):
111  return _lib.cgaudi_factory_get_classname(self)
112 
113  @property
114  def properties(self):
115  props = {}
116  nprops = _lib.cgaudi_factory_get_property_size(self)
117  for i in range(nprops):
118  prop = _lib.cgaudi_factory_get_property_at(self, i)
119  props[prop.key] = prop.value
120  return props
121 
122  def load(self):
123  '''load the C++ library hosting this factory
124  '''
125  return ctypes.cdll.LoadLibrary(self.library)
126 
127  def __repr__(self):
128  return "<Factory id=%s library=%s type=%s rtype=%s class=%s props=%d>" % (
129  self._id,
130  self.library,
131  self.type,
132  self.rtype,
133  self.classname,
134  len(self.properties),
135  )
136  pass
137 
138 class Property(ctypes.Structure):
139  '''
140  Property is a pair (key, value) optionally decorating a factory.
141  It is used to attach additional informations about a factory.
142  '''
143  _fields_ = [
144  ("_registry", Registry),
145  ("_id", ctypes.c_char_p),
146  ("_key", ctypes.c_char_p),
147  ]
148 
149  @property
150  def key(self):
151  return _lib.cgaudi_property_get_key(self)
152 
153  @property
154  def value(self):
155  return _lib.cgaudi_property_get_value(self)
156 
157  pass
158 
159 _functions_list = [
160  ("cgaudi_pluginsvc_instance",
161  [],
162  Registry,
163  ),
164 
165  ("cgaudi_pluginsvc_get_factory_size",
166  [Registry],
167  ctypes.c_int,
168  ),
169 
170  ("cgaudi_pluginsvc_get_factory_at",
171  [Registry, ctypes.c_int],
172  Factory,
173  ),
174 
175  ("cgaudi_factory_get_library",
176  [Factory],
177  ctypes.c_char_p,
178  ),
179 
180  ("cgaudi_factory_get_type",
181  [Factory],
182  ctypes.c_char_p,
183  ),
184 
185  ("cgaudi_factory_get_rtype",
186  [Factory],
187  ctypes.c_char_p,
188  ),
189 
190  ("cgaudi_factory_get_classname",
191  [Factory],
192  ctypes.c_char_p,
193  ),
194 
195  ("cgaudi_factory_get_property_size",
196  [Factory],
197  ctypes.c_int,
198  ),
199 
200  ("cgaudi_factory_get_property_at",
201  [Factory, ctypes.c_int],
202  Property,
203  ),
204 
205  ("cgaudi_property_get_key",
206  [Property],
207  ctypes.c_char_p,
208  ),
209 
210  ("cgaudi_property_get_value",
211  [Property],
212  ctypes.c_char_p,
213  )
214 ]
215 
216 for f in _functions_list:
217  n = f[0]
218  func = getattr(_lib, n)
219  func.argtypes = f[1]
220  func.restype = f[2]
221  if len(f) == 4: func.errcheck = f[3]
222  pass
223 
224 
225 if __name__ == "__main__":
226  print ("instance: %s" % registry())
227  print ("factories: %d" % len(factories()))
228  for _,f in factories().items():
229  try:
230  f.load()
231  except Exception:
232  print ("** could not load [%s] for factory [%s]" % (f.library, f.name))
233  continue
234  print f
235  for k,v in f.properties.items():
236  print ("\t%s: %s" % (k,v))
237 
238 ## EOF
decltype(auto) range(Args &&...args)
Zips multiple containers together to form a single range.