Logo ROOT   6.14/05
Reference Guide
Utility.cxx
Go to the documentation of this file.
1 // @(#)root/pyroot:$Id$
2 // Author: Wim Lavrijsen, Apr 2004
3 
4 // Bindings
5 #include "PyROOT.h"
6 #include "PyStrings.h"
7 #include "Utility.h"
8 #include "ObjectProxy.h"
9 #include "MethodProxy.h"
10 #include "TFunctionHolder.h"
11 #include "TCustomPyTypes.h"
12 #include "TemplateProxy.h"
13 #include "RootWrapper.h"
14 #include "PyCallable.h"
15 
16 // ROOT
17 #include "TApplication.h"
18 #include "TROOT.h"
19 #include "TSystem.h"
20 #include "TObject.h"
21 #include "TClassEdit.h"
22 #include "TClassRef.h"
23 #include "TCollection.h"
24 #include "TDataType.h"
25 #include "TFunction.h"
26 #include "TFunctionTemplate.h"
27 #include "TMethod.h"
28 #include "TMethodArg.h"
29 #include "TError.h"
30 #include "TInterpreter.h"
31 
32 // Standard
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <algorithm>
37 #include <list>
38 #include <mutex>
39 #include <sstream>
40 #include <utility>
41 
42 
43 //- data _____________________________________________________________________
46 
47 typedef std::map< std::string, std::string > TC2POperatorMapping_t;
49 
50 namespace {
51 
52  using namespace PyROOT::Utility;
53 
54  struct InitOperatorMapping_t {
55  public:
56  InitOperatorMapping_t() {
57  // Initialize the global map of operator names C++ -> python.
58 
59  // gC2POperatorMapping[ "[]" ] = "__setitem__"; // depends on return type
60  // gC2POperatorMapping[ "+" ] = "__add__"; // depends on # of args (see __pos__)
61  // gC2POperatorMapping[ "-" ] = "__sub__"; // id. (eq. __neg__)
62  // gC2POperatorMapping[ "*" ] = "__mul__"; // double meaning in C++
63 
64  gC2POperatorMapping[ "[]" ] = "__getitem__";
65  gC2POperatorMapping[ "()" ] = "__call__";
67  gC2POperatorMapping[ "%" ] = "__mod__";
68  gC2POperatorMapping[ "**" ] = "__pow__";
69  gC2POperatorMapping[ "<<" ] = "__lshift__";
70  gC2POperatorMapping[ ">>" ] = "__rshift__";
71  gC2POperatorMapping[ "&" ] = "__and__";
72  gC2POperatorMapping[ "|" ] = "__or__";
73  gC2POperatorMapping[ "^" ] = "__xor__";
74  gC2POperatorMapping[ "~" ] = "__inv__";
75  gC2POperatorMapping[ "+=" ] = "__iadd__";
76  gC2POperatorMapping[ "-=" ] = "__isub__";
77  gC2POperatorMapping[ "*=" ] = "__imul__";
79  gC2POperatorMapping[ "%=" ] = "__imod__";
80  gC2POperatorMapping[ "**=" ] = "__ipow__";
81  gC2POperatorMapping[ "<<=" ] = "__ilshift__";
82  gC2POperatorMapping[ ">>=" ] = "__irshift__";
83  gC2POperatorMapping[ "&=" ] = "__iand__";
84  gC2POperatorMapping[ "|=" ] = "__ior__";
85  gC2POperatorMapping[ "^=" ] = "__ixor__";
86  gC2POperatorMapping[ "==" ] = "__eq__";
87  gC2POperatorMapping[ "!=" ] = "__ne__";
88  gC2POperatorMapping[ ">" ] = "__gt__";
89  gC2POperatorMapping[ "<" ] = "__lt__";
90  gC2POperatorMapping[ ">=" ] = "__ge__";
91  gC2POperatorMapping[ "<=" ] = "__le__";
92 
93  // the following type mappings are "exact"
94  gC2POperatorMapping[ "const char*" ] = "__str__";
95  gC2POperatorMapping[ "char*" ] = "__str__";
96  gC2POperatorMapping[ "const char *" ] = gC2POperatorMapping[ "const char*" ];
97  gC2POperatorMapping[ "char *" ] = gC2POperatorMapping[ "char*" ];
98  gC2POperatorMapping[ "int" ] = "__int__";
100  gC2POperatorMapping[ "double" ] = "__float__";
101 
102  // the following type mappings are "okay"; the assumption is that they
103  // are not mixed up with the ones above or between themselves (and if
104  // they are, that it is done consistently)
105  gC2POperatorMapping[ "short" ] = "__int__";
106  gC2POperatorMapping[ "unsigned short" ] = "__int__";
107  gC2POperatorMapping[ "unsigned int" ] = PYROOT__long__;
108  gC2POperatorMapping[ "unsigned long" ] = PYROOT__long__;
109  gC2POperatorMapping[ "long long" ] = PYROOT__long__;
110  gC2POperatorMapping[ "unsigned long long" ] = PYROOT__long__;
111  gC2POperatorMapping[ "float" ] = "__float__";
112 
113  gC2POperatorMapping[ "->" ] = "__follow__"; // not an actual python operator
114  gC2POperatorMapping[ "=" ] = "__assign__"; // id.
115 
116 #if PY_VERSION_HEX < 0x03000000
117  gC2POperatorMapping[ "bool" ] = "__nonzero__";
118 #else
119  gC2POperatorMapping[ "bool" ] = "__bool__";
120 #endif
121  }
122  } initOperatorMapping_;
123 
124  std::once_flag sOperatorTemplateFlag;
125  void InitOperatorTemplate() {
126  gROOT->ProcessLine(
127  "namespace _pyroot_internal { template<class C1, class C2>"
128  " bool is_equal(const C1& c1, const C2& c2){ return (bool)(c1 == c2); } }" );
129  gROOT->ProcessLine(
130  "namespace _pyroot_internal { template<class C1, class C2>"
131  " bool is_not_equal(const C1& c1, const C2& c2){ return (bool)(c1 != c2); } }" );
132  }
133 
134  inline void RemoveConst( std::string& cleanName ) {
135  std::string::size_type spos = std::string::npos;
136  while ( ( spos = cleanName.find( "const" ) ) != std::string::npos ) {
137  cleanName.swap( cleanName.erase( spos, 5 ) );
138  }
139  }
140 
141 } // unnamed namespace
142 
143 
144 //- public functions ---------------------------------------------------------
146 {
147 // Convert <pybject> to C++ unsigned long, with bounds checking, allow int -> ulong.
148  ULong_t ul = PyLong_AsUnsignedLong( pyobject );
149  if ( PyErr_Occurred() && PyInt_Check( pyobject ) ) {
150  PyErr_Clear();
151  Long_t i = PyInt_AS_LONG( pyobject );
152  if ( 0 <= i ) {
153  ul = (ULong_t)i;
154  } else {
155  PyErr_SetString( PyExc_ValueError,
156  "can\'t convert negative value to unsigned long" );
157  }
158  }
159 
160  return ul;
161 }
162 
163 ////////////////////////////////////////////////////////////////////////////////
164 /// Convert <pyobject> to C++ unsigned long long, with bounds checking.
165 
167 {
168  ULong64_t ull = PyLong_AsUnsignedLongLong( pyobject );
169  if ( PyErr_Occurred() && PyInt_Check( pyobject ) ) {
170  PyErr_Clear();
171  Long_t i = PyInt_AS_LONG( pyobject );
172  if ( 0 <= i ) {
173  ull = (ULong64_t)i;
174  } else {
175  PyErr_SetString( PyExc_ValueError,
176  "can\'t convert negative value to unsigned long long" );
177  }
178  }
179 
180  return ull;
181 }
182 
183 ////////////////////////////////////////////////////////////////////////////////
184 /// Add the given function to the class under name 'label'.
185 
187  PyObject* pyclass, const char* label, PyCFunction cfunc, int flags )
188 {
189 // use list for clean-up (.so's are unloaded only at interpreter shutdown)
190  static std::list< PyMethodDef > s_pymeths;
191 
192  s_pymeths.push_back( PyMethodDef() );
193  PyMethodDef* pdef = &s_pymeths.back();
194  pdef->ml_name = const_cast< char* >( label );
195  pdef->ml_meth = cfunc;
196  pdef->ml_flags = flags;
197  pdef->ml_doc = NULL;
198 
199  PyObject* func = PyCFunction_New( pdef, NULL );
200  PyObject* method = TCustomInstanceMethod_New( func, NULL, pyclass );
201  Bool_t isOk = PyObject_SetAttrString( pyclass, pdef->ml_name, method ) == 0;
202  Py_DECREF( method );
203  Py_DECREF( func );
204 
205  if ( PyErr_Occurred() )
206  return kFALSE;
207 
208  if ( ! isOk ) {
209  PyErr_Format( PyExc_TypeError, "could not add method %s", label );
210  return kFALSE;
211  }
212 
213  return kTRUE;
214 }
215 
216 ////////////////////////////////////////////////////////////////////////////////
217 /// Add the given function to the class under name 'label'.
218 
219 Bool_t PyROOT::Utility::AddToClass( PyObject* pyclass, const char* label, const char* func )
220 {
221  PyObject* pyfunc = PyObject_GetAttrString( pyclass, const_cast< char* >( func ) );
222  if ( ! pyfunc )
223  return kFALSE;
224 
225  Bool_t isOk = PyObject_SetAttrString( pyclass, const_cast< char* >( label ), pyfunc ) == 0;
226 
227  Py_DECREF( pyfunc );
228  return isOk;
229 }
230 
231 ////////////////////////////////////////////////////////////////////////////////
232 /// Add the given function to the class under name 'label'.
233 
234 Bool_t PyROOT::Utility::AddToClass( PyObject* pyclass, const char* label, PyCallable* pyfunc )
235 {
236  MethodProxy* method =
237  (MethodProxy*)PyObject_GetAttrString( pyclass, const_cast< char* >( label ) );
238 
239  if ( ! method || ! MethodProxy_Check( method ) ) {
240  // not adding to existing MethodProxy; add callable directly to the class
241  if ( PyErr_Occurred() )
242  PyErr_Clear();
243  Py_XDECREF( (PyObject*)method );
244  method = MethodProxy_New( label, pyfunc );
245  Bool_t isOk = PyObject_SetAttrString(
246  pyclass, const_cast< char* >( label ), (PyObject*)method ) == 0;
247  Py_DECREF( method );
248  return isOk;
249  }
250 
251  method->AddMethod( pyfunc );
252 
253  Py_DECREF( method );
254  return kTRUE;
255 }
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 /// Helper to add base class methods to the derived class one (this covers the
259 /// 'using' cases, which the dictionary does not provide).
260 
261 Bool_t PyROOT::Utility::AddUsingToClass( PyObject* pyclass, const char* method )
262 {
263  MethodProxy* derivedMethod =
264  (MethodProxy*)PyObject_GetAttrString( pyclass, const_cast< char* >( method ) );
265  if ( ! MethodProxy_Check( derivedMethod ) ) {
266  Py_XDECREF( derivedMethod );
267  return kFALSE;
268  }
269 
270  PyObject* mro = PyObject_GetAttr( pyclass, PyStrings::gMRO );
271  if ( ! mro || ! PyTuple_Check( mro ) ) {
272  Py_XDECREF( mro );
273  Py_DECREF( derivedMethod );
274  return kFALSE;
275  }
276 
277  MethodProxy* baseMethod = 0;
278  for ( int i = 1; i < PyTuple_GET_SIZE( mro ); ++i ) {
279  baseMethod = (MethodProxy*)PyObject_GetAttrString(
280  PyTuple_GET_ITEM( mro, i ), const_cast< char* >( method ) );
281 
282  if ( ! baseMethod ) {
283  PyErr_Clear();
284  continue;
285  }
286 
287  if ( MethodProxy_Check( baseMethod ) )
288  break;
289 
290  Py_DECREF( baseMethod );
291  baseMethod = 0;
292  }
293 
294  Py_DECREF( mro );
295 
296  if ( ! MethodProxy_Check( baseMethod ) ) {
297  Py_XDECREF( baseMethod );
298  Py_DECREF( derivedMethod );
299  return kFALSE;
300  }
301 
302  derivedMethod->AddMethod( baseMethod );
303 
304  Py_DECREF( baseMethod );
305  Py_DECREF( derivedMethod );
306 
307  return kTRUE;
308 }
309 
310 ////////////////////////////////////////////////////////////////////////////////
311 /// Install the named operator (op) into the left object's class if such a function
312 /// exists as a global overload; a label must be given if the operator is not in
313 /// gC2POperatorMapping (i.e. if it is ambiguous at the member level).
314 
316  PyObject* left, PyObject* right, const char* op, const char* label, const char* alt )
317 {
318 // this should be a given, nevertheless ...
319  if ( ! ObjectProxy_Check( left ) )
320  return kFALSE;
321 
322 // retrieve the class names to match the signature of any found global functions
323  std::string rcname = ClassName( right );
324  std::string lcname = ClassName( left );
325  PyObject* pyclass = PyObject_GetAttr( left, PyStrings::gClass );
326 
327  Bool_t result = AddBinaryOperator( pyclass, lcname, rcname, op, label, alt );
328 
329  Py_DECREF( pyclass );
330  return result;
331 }
332 
333 ////////////////////////////////////////////////////////////////////////////////
334 /// Install binary operator op in pyclass, working on two instances of pyclass.
335 
337  PyObject* pyclass, const char* op, const char* label, const char* alt )
338 {
339  PyObject* pyname = PyObject_GetAttr( pyclass, PyStrings::gCppName );
340  if ( ! pyname ) pyname = PyObject_GetAttr( pyclass, PyStrings::gName );
341  std::string cname = Cppyy::ResolveName( PyROOT_PyUnicode_AsString( pyname ) );
342  Py_DECREF( pyname ); pyname = 0;
343 
344  return AddBinaryOperator( pyclass, cname, cname, op, label, alt );
345 }
346 
347 ////////////////////////////////////////////////////////////////////////////////
348 /// Helper to find a function with matching signature in 'funcs'.
349 
350 static inline Cppyy::TCppMethod_t FindAndAddOperator( const std::string& lcname, const std::string& rcname,
351  const char* op, TClass* klass = 0 ) {
352  std::string opname = "operator";
353  opname += op;
354  std::string proto = lcname + ", " + rcname;
355 
356 // case of global namespace
357  if ( ! klass )
358  return (Cppyy::TCppMethod_t)gROOT->GetGlobalFunctionWithPrototype( opname.c_str(), proto.c_str() );
359 
360 // case of specific namespace
361  return (Cppyy::TCppMethod_t)klass->GetMethodWithPrototype( opname.c_str(), proto.c_str() );
362 }
363 
364 Bool_t PyROOT::Utility::AddBinaryOperator( PyObject* pyclass, const std::string& lcname,
365  const std::string& rcname, const char* op, const char* label, const char* alt )
366 {
367 // Find a global function with a matching signature and install the result on pyclass;
368 // in addition, __gnu_cxx, std::__1, and _pyroot_internal are searched pro-actively (as
369 // there's AFAICS no way to unearth using information).
370 
371 // This function can be called too early when setting up some of the ROOT core classes,
372 // which in turn can trigger the creation of a (default) TApplication. Wait with looking
373 // for binary operators '!=' and '==' (which are set early in Pythonize.cxx) until fully
374 // initialized. Other operators are expected to have entered from user code.
375  if ( !gApplication && (strcmp( op, "==" ) == 0 || strcmp( op, "!=" ) == 0) )
376  return kFALSE;
377 
378 // For GNU on clang, search the internal __gnu_cxx namespace for binary operators (is
379 // typically the case for STL iterators operator==/!=.
380  static TClassRef gnucxx( "__gnu_cxx" );
381  static bool gnucxx_exists = (bool)gnucxx.GetClass();
382 
383 // Same for clang on Mac. TODO: find proper pre-processor magic to only use those specific
384 // namespaces that are actually around; although to be sure, this isn't expensive.
385  static TClassRef std__1( "std::__1" );
386  static bool std__1_exists = (bool)std__1.GetClass();
387 
388 // One more, mostly for Mac, but again not sure whether this is not a general issue. Some
389 // operators are declared as friends only in classes, so then they're not found in the
390 // global namespace. That's why there's this little helper.
391  std::call_once( sOperatorTemplateFlag, InitOperatorTemplate );
392  static TClassRef _pr_int( "_pyroot_internal" );
393 
394  PyCallable* pyfunc = 0;
395  if ( gnucxx_exists ) {
396  Cppyy::TCppMethod_t func = FindAndAddOperator( lcname, rcname, op, gnucxx.GetClass() );
397  if ( func ) pyfunc = new TFunctionHolder( Cppyy::GetScope( "__gnu_cxx" ), func );
398  }
399 
400  if ( ! pyfunc && std__1_exists ) {
401  Cppyy::TCppMethod_t func = FindAndAddOperator( lcname, rcname, op, std__1.GetClass() );
402  if ( func ) pyfunc = new TFunctionHolder( Cppyy::GetScope( "std::__1" ), func );
403  }
404 
405  if ( ! pyfunc ) {
406  std::string::size_type pos = lcname.substr(0, lcname.find('<')).rfind( "::" );
407  if ( pos != std::string::npos ) {
408  TClass* lcscope = TClass::GetClass( lcname.substr( 0, pos ).c_str() );
409  if ( lcscope ) {
410  Cppyy::TCppMethod_t func = FindAndAddOperator( lcname, rcname, op, lcscope );
411  if ( func ) pyfunc = new TFunctionHolder( Cppyy::GetScope( lcname.substr( 0, pos ) ), func );
412  }
413  }
414  }
415 
416  if ( ! pyfunc ) {
417  Cppyy::TCppMethod_t func = FindAndAddOperator( lcname, rcname, op );
418  if ( func ) pyfunc = new TFunctionHolder( Cppyy::gGlobalScope, func );
419  }
420 
421  if ( ! pyfunc && _pr_int.GetClass() &&
422  lcname.find( "iterator" ) != std::string::npos &&
423  rcname.find( "iterator" ) != std::string::npos ) {
424  // TODO: gets called too often; make sure it's purely lazy calls only; also try to
425  // find a better notion for which classes (other than iterators) this is supposed to
426  // work; right now it fails for cases where None is passed
427  std::stringstream fname;
428  if ( strncmp( op, "==", 2 ) == 0 ) { fname << "is_equal<"; }
429  else if ( strncmp( op, "!=", 2 ) == 0 ) { fname << "is_not_equal<"; }
430  else { fname << "not_implemented<"; }
431  fname << lcname << ", " << rcname << ">";
432  Cppyy::TCppMethod_t func = (Cppyy::TCppMethod_t)_pr_int->GetMethodAny( fname.str().c_str() );
433  if ( func ) pyfunc = new TFunctionHolder( Cppyy::GetScope( "_pyroot_internal" ), func );
434  }
435 
436 // last chance: there could be a non-instantiated templated method
437  TClass* lc = TClass::GetClass( lcname.c_str() );
438  if ( lc && strcmp(op, "==") != 0 && strcmp(op, "!=") != 0 ) {
439  std::string opname = "operator"; opname += op;
440  gInterpreter->LoadFunctionTemplates(lc);
441  gInterpreter->GetFunctionTemplate(lc->GetClassInfo(), opname.c_str());
442  TFunctionTemplate*f = lc->GetFunctionTemplate(opname.c_str());
443  Cppyy::TCppMethod_t func =
444  (Cppyy::TCppMethod_t)lc->GetMethodWithPrototype( opname.c_str(), rcname.c_str() );
445  if ( func && f ) pyfunc = new TMethodHolder( Cppyy::GetScope( lcname ), func );
446  }
447 
448  if ( pyfunc ) { // found a matching overload; add to class
449  Bool_t ok = AddToClass( pyclass, label, pyfunc );
450  if ( ok && alt )
451  return AddToClass( pyclass, alt, label );
452  }
453 
454  return kFALSE;
455 }
456 
457 ////////////////////////////////////////////////////////////////////////////////
458 /// Helper to construct the "< type, type, ... >" part of a templated name (either
459 /// for a class as in MakeRootTemplateClass in RootModule.cxx) or for method lookup
460 /// (as in TemplatedMemberHook, below).
461 
463 {
464  if ( pyname )
466  else
467  pyname = PyROOT_PyUnicode_FromString( "" );
469 
470  Py_ssize_t nArgs = PyTuple_GET_SIZE( args );
471  for ( int i = argoff; i < nArgs; ++i ) {
472  // add type as string to name
473  PyObject* tn = PyTuple_GET_ITEM( args, i );
474  if ( PyROOT_PyUnicode_Check( tn ) ) {
475  PyROOT_PyUnicode_Append( &pyname, tn );
476  } else if (PyObject_HasAttr( tn, PyStrings::gName ) ) {
477  // __cppname__ provides a better name for C++ classes (namespaces)
478  PyObject* tpName;
479  if ( PyObject_HasAttr( tn, PyStrings::gCppName ) ) {
480  tpName = PyObject_GetAttr( tn, PyStrings::gCppName );
481  } else {
482  tpName = PyObject_GetAttr( tn, PyStrings::gName );
483  }
484  // special case for strings
485  if ( strcmp( PyROOT_PyUnicode_AsString( tpName ), "str" ) == 0 ) {
486  Py_DECREF( tpName );
487  tpName = PyROOT_PyUnicode_FromString( "std::string" );
488  }
489  PyROOT_PyUnicode_AppendAndDel( &pyname, tpName );
490  } else if ( PyInt_Check( tn ) || PyLong_Check( tn ) || PyFloat_Check( tn ) ) {
491  // last ditch attempt, works for things like int values; since this is a
492  // source of errors otherwise, it is limited to specific types and not
493  // generally used (str(obj) can print anything ...)
494  PyObject* pystr = PyObject_Str( tn );
495  PyROOT_PyUnicode_AppendAndDel( &pyname, pystr );
496  } else {
497  Py_DECREF( pyname );
498  PyErr_SetString( PyExc_SyntaxError, "could not get __cppname__ from provided template argument. Is it a str, class, type or int?" );
499  return 0;
500  }
501 
502  // add a comma, as needed
503  if ( i != nArgs - 1 )
505  }
506 
507 // close template name; prevent '>>', which should be '> >'
508  if ( PyROOT_PyUnicode_AsString( pyname )[ PyROOT_PyUnicode_GetSize( pyname ) - 1 ] == '>' )
510  else
512 
513  return pyname;
514 }
515 
516 ////////////////////////////////////////////////////////////////////////////////
517 /// Initialize a proxy class for use by python, and add it to the ROOT module.
518 
519 Bool_t PyROOT::Utility::InitProxy( PyObject* module, PyTypeObject* pytype, const char* name )
520 {
521 // finalize proxy type
522  if ( PyType_Ready( pytype ) < 0 )
523  return kFALSE;
524 
525 // add proxy type to the given (ROOT) module
526  Py_INCREF( pytype ); // PyModule_AddObject steals reference
527  if ( PyModule_AddObject( module, (char*)name, (PyObject*)pytype ) < 0 ) {
528  Py_DECREF( pytype );
529  return kFALSE;
530  }
531 
532 // declare success
533  return kTRUE;
534 }
535 
536 ////////////////////////////////////////////////////////////////////////////////
537 /// Retrieve a linear buffer pointer from the given pyobject.
538 
539 int PyROOT::Utility::GetBuffer( PyObject* pyobject, char tc, int size, void*& buf, Bool_t check )
540 {
541 // special case: don't handle character strings here (yes, they're buffers, but not quite)
542  if ( PyBytes_Check( pyobject ) )
543  return 0;
544 
545 // attempt to retrieve pointer to buffer interface
546  PyBufferProcs* bufprocs = Py_TYPE(pyobject)->tp_as_buffer;
547 
548  PySequenceMethods* seqmeths = Py_TYPE(pyobject)->tp_as_sequence;
549  if ( seqmeths != 0 && bufprocs != 0
550 #if PY_VERSION_HEX < 0x03000000
551  && bufprocs->bf_getwritebuffer != 0
552  && (*(bufprocs->bf_getsegcount))( pyobject, 0 ) == 1
553 #else
554  && bufprocs->bf_getbuffer != 0
555 #endif
556  ) {
557 
558  // get the buffer
559 #if PY_VERSION_HEX < 0x03000000
560  Py_ssize_t buflen = (*(bufprocs->bf_getwritebuffer))( pyobject, 0, &buf );
561 #else
562  Py_buffer bufinfo;
563  (*(bufprocs->bf_getbuffer))( pyobject, &bufinfo, PyBUF_WRITABLE );
564  buf = (char*)bufinfo.buf;
565  Py_ssize_t buflen = bufinfo.len;
566 #if PY_VERSION_HEX < 0x03010000
567  PyBuffer_Release( pyobject, &bufinfo );
568 #else
569  PyBuffer_Release( &bufinfo );
570 #endif
571 #endif
572 
573  if ( buf && check == kTRUE ) {
574  // determine buffer compatibility (use "buf" as a status flag)
575  PyObject* pytc = PyObject_GetAttr( pyobject, PyStrings::gTypeCode );
576  if ( pytc != 0 ) { // for array objects
577  if ( PyROOT_PyUnicode_AsString( pytc )[0] != tc )
578  buf = 0; // no match
579  Py_DECREF( pytc );
580  } else if ( seqmeths->sq_length &&
581  (int)(buflen / (*(seqmeths->sq_length))( pyobject )) == size ) {
582  // this is a gamble ... may or may not be ok, but that's for the user
583  PyErr_Clear();
584  } else if ( buflen == size ) {
585  // also a gamble, but at least 1 item will fit into the buffer, so very likely ok ...
586  PyErr_Clear();
587  } else {
588  buf = 0; // not compatible
589 
590  // clarify error message
591  PyObject* pytype = 0, *pyvalue = 0, *pytrace = 0;
592  PyErr_Fetch( &pytype, &pyvalue, &pytrace );
594  (char*)"%s and given element size (%ld) do not match needed (%d)",
595  PyROOT_PyUnicode_AsString( pyvalue ),
596  seqmeths->sq_length ? (Long_t)(buflen / (*(seqmeths->sq_length))( pyobject )) : (Long_t)buflen,
597  size );
598  Py_DECREF( pyvalue );
599  PyErr_Restore( pytype, pyvalue2, pytrace );
600  }
601  }
602 
603  return buflen;
604  }
605 
606  return 0;
607 }
608 
609 ////////////////////////////////////////////////////////////////////////////////
610 /// Map the given C++ operator name on the python equivalent.
611 
612 std::string PyROOT::Utility::MapOperatorName( const std::string& name, Bool_t bTakesParams )
613 {
614  if ( 8 < name.size() && name.substr( 0, 8 ) == "operator" ) {
615  std::string op = name.substr( 8, std::string::npos );
616 
617  // stripping ...
618  std::string::size_type start = 0, end = op.size();
619  while ( start < end && isspace( op[ start ] ) ) ++start;
620  while ( start < end && isspace( op[ end-1 ] ) ) --end;
621  op = TClassEdit::ResolveTypedef( op.substr( start, end - start ).c_str(), true );
622 
623  // map C++ operator to python equivalent, or made up name if no equivalent exists
624  TC2POperatorMapping_t::iterator pop = gC2POperatorMapping.find( op );
625  if ( pop != gC2POperatorMapping.end() ) {
626  return pop->second;
627 
628  } else if ( op == "*" ) {
629  // dereference v.s. multiplication of two instances
630  return bTakesParams ? "__mul__" : "__deref__";
631 
632  } else if ( op == "+" ) {
633  // unary positive v.s. addition of two instances
634  return bTakesParams ? "__add__" : "__pos__";
635 
636  } else if ( op == "-" ) {
637  // unary negative v.s. subtraction of two instances
638  return bTakesParams ? "__sub__" : "__neg__";
639 
640  } else if ( op == "++" ) {
641  // prefix v.s. postfix increment
642  return bTakesParams ? "__postinc__" : "__preinc__";
643 
644  } else if ( op == "--" ) {
645  // prefix v.s. postfix decrement
646  return bTakesParams ? "__postdec__" : "__predec__";
647  }
648 
649  }
650 
651 // might get here, as not all operator methods are handled (new, delete, etc.)
652  return name;
653 }
654 
655 ////////////////////////////////////////////////////////////////////////////////
656 /// Break down the compound of a fully qualified type name.
657 
658 const std::string PyROOT::Utility::Compound( const std::string& name )
659 {
660  std::string cleanName = name;
661  RemoveConst( cleanName );
662 
663  std::string compound = "";
664  for ( int ipos = (int)cleanName.size()-1; 0 <= ipos; --ipos ) {
665  char c = cleanName[ipos];
666  if ( isspace( c ) ) continue;
667  if ( isalnum( c ) || c == '_' || c == '>' ) break;
668 
669  compound = c + compound;
670  }
671 
672 // for arrays (TODO: deal with the actual size)
673  if ( compound == "]" )
674  return "[]";
675 
676  return compound;
677 }
678 
679 ////////////////////////////////////////////////////////////////////////////////
680 /// Extract size from an array type, if available.
681 
683 {
684  std::string cleanName = name;
685  RemoveConst( cleanName );
686 
687  if ( cleanName[cleanName.size()-1] == ']' ) {
688  std::string::size_type idx = cleanName.rfind( '[' );
689  if ( idx != std::string::npos ) {
690  const std::string asize = cleanName.substr( idx+1, cleanName.size()-2 );
691  return strtoul( asize.c_str(), NULL, 0 );
692  }
693  }
694 
695  return -1;
696 }
697 
698 ////////////////////////////////////////////////////////////////////////////////
699 /// Retrieve the class name from the given python object (which may be just an
700 /// instance of the class).
701 
702 const std::string PyROOT::Utility::ClassName( PyObject* pyobj )
703 {
704  std::string clname = "<unknown>";
705  PyObject* pyclass = PyObject_GetAttr( pyobj, PyStrings::gClass );
706  if ( pyclass != 0 ) {
707  PyObject* pyname = PyObject_GetAttr( pyclass, PyStrings::gCppName );
708 
709  if ( pyname != 0 ) {
710  clname = PyROOT_PyUnicode_AsString( pyname );
711  Py_DECREF( pyname );
712  } else {
713  pyname = PyObject_GetAttr( pyclass, PyStrings::gName );
714  if ( pyname != 0 ) {
715  clname = PyROOT_PyUnicode_AsString( pyname );
716  Py_DECREF( pyname );
717  } else {
718  PyErr_Clear();
719  }
720  }
721  Py_DECREF( pyclass );
722  } else {
723  PyErr_Clear();
724  }
725 
726  return clname;
727 }
728 
729 ////////////////////////////////////////////////////////////////////////////////
730 /// Translate CINT error/warning into python equivalent.
731 
732 void PyROOT::Utility::ErrMsgCallback( char* /* msg */ )
733 {
734 // TODO (Cling): this function is probably not going to be used anymore and
735 // may need removing at some point for cleanup
736 
737 /* Commented out for Cling ---
738 
739 // ignore the "*** Interpreter error recovered ***" message
740  if ( strstr( msg, "error recovered" ) )
741  return;
742 
743 // ignore CINT-style FILE/LINE messages
744  if ( strstr( msg, "FILE:" ) )
745  return;
746 
747 // get file name and line number
748  char* errFile = (char*)G__stripfilename( G__get_ifile()->name );
749  int errLine = G__get_ifile()->line_number;
750 
751 // ignore ROOT-style FILE/LINE messages
752  char buf[256];
753  snprintf( buf, 256, "%s:%d:", errFile, errLine );
754  if ( strstr( msg, buf ) )
755  return;
756 
757 // strip newline, if any
758  int len = strlen( msg );
759  if ( msg[ len-1 ] == '\n' )
760  msg[ len-1 ] = '\0';
761 
762 // concatenate message if already in error processing mode (e.g. if multiple CINT errors)
763  if ( PyErr_Occurred() ) {
764  PyObject *etype, *value, *trace;
765  PyErr_Fetch( &etype, &value, &trace ); // clears current exception
766 
767  // need to be sure that error can be added; otherwise leave earlier error in place
768  if ( PyROOT_PyUnicode_Check( value ) ) {
769  if ( ! PyErr_GivenExceptionMatches( etype, PyExc_IndexError ) )
770  PyROOT_PyUnicode_AppendAndDel( &value, PyROOT_PyUnicode_FromString( (char*)"\n " ) );
771  PyROOT_PyUnicode_AppendAndDel( &value, PyROOT_PyUnicode_FromString( msg ) );
772  }
773 
774  PyErr_Restore( etype, value, trace );
775  return;
776  }
777 
778 // else, translate known errors and warnings, or simply accept the default
779  char* format = (char*)"(file \"%s\", line %d) %s";
780  char* p = 0;
781  if ( ( p = strstr( msg, "Syntax Error:" ) ) )
782  PyErr_Format( PyExc_SyntaxError, format, errFile, errLine, p+14 );
783  else if ( ( p = strstr( msg, "Error: Array" ) ) )
784  PyErr_Format( PyExc_IndexError, format, errFile, errLine, p+12 );
785  else if ( ( p = strstr( msg, "Error:" ) ) )
786  PyErr_Format( PyExc_RuntimeError, format, errFile, errLine, p+7 );
787  else if ( ( p = strstr( msg, "Exception:" ) ) )
788  PyErr_Format( PyExc_RuntimeError, format, errFile, errLine, p+11 );
789  else if ( ( p = strstr( msg, "Limitation:" ) ) )
790  PyErr_Format( PyExc_NotImplementedError, format, errFile, errLine, p+12 );
791  else if ( ( p = strstr( msg, "Internal Error: malloc" ) ) )
792  PyErr_Format( PyExc_MemoryError, format, errFile, errLine, p+23 );
793  else if ( ( p = strstr( msg, "Internal Error:" ) ) )
794  PyErr_Format( PyExc_SystemError, format, errFile, errLine, p+16 );
795  else if ( ( p = strstr( msg, "Warning:" ) ) )
796 // either printout or raise exception, depending on user settings
797  PyErr_WarnExplicit( NULL, p+9, errFile, errLine, (char*)"CINT", NULL );
798  else if ( ( p = strstr( msg, "Note:" ) ) )
799  fprintf( stdout, "Note: (file \"%s\", line %d) %s\n", errFile, errLine, p+6 );
800  else // unknown: printing it to screen is the safest action
801  fprintf( stdout, "Message: (file \"%s\", line %d) %s\n", errFile, errLine, msg );
802 
803  --- Commented out for Cling */
804 }
805 
806 ////////////////////////////////////////////////////////////////////////////////
807 /// Translate ROOT error/warning to python.
808 
809 void PyROOT::Utility::ErrMsgHandler( int level, Bool_t abort, const char* location, const char* msg )
810 {
811 // initialization from gEnv (the default handler will return w/o msg b/c level too low)
812  if ( gErrorIgnoreLevel == kUnset )
813  ::DefaultErrorHandler( kUnset - 1, kFALSE, "", "" );
814 
815  if ( level < gErrorIgnoreLevel )
816  return;
817 
818 // turn warnings into python warnings
819  if (level >= kError)
820  ::DefaultErrorHandler( level, abort, location, msg );
821  else if ( level >= kWarning ) {
822  static const char* emptyString = "";
823  if (!location) location = emptyString;
824  // This warning might be triggered while holding the ROOT lock, while
825  // some othe rtherad is holding the GIL and waiting for the ROOT lock.
826  // That will trigger a deadlock.
827  // So if ROOT is in MT mode, use ROOT's error handler that doesn't take
828  // the GIL.
829  if (!gGlobalMutex) {
830  // either printout or raise exception, depending on user settings
831  PyErr_WarnExplicit( NULL, (char*)msg, (char*)location, 0, (char*)"ROOT", NULL );
832  } else {
833  ::DefaultErrorHandler( level, abort, location, msg );
834  }
835  }
836  else
837  ::DefaultErrorHandler( level, abort, location, msg );
838 }
839 
840 
841 ////////////////////////////////////////////////////////////////////////////////
842 /// Compile a function on the fly and return a function pointer for use on C-APIs.
843 /// The callback should take a (void*)pyfunc and the (Long_t)user as well as the
844 /// rest of the declare signature. It should also live in namespace PyROOT
845 
847  const char* retType, const std::vector<std::string>& signature, const char* callback )
848 {
849  static Long_t s_fid = 0;
850 
851  if ( ! PyCallable_Check( pyfunc ) )
852  return 0;
853 
854 // keep alive (TODO: manage this intelligently)
855  Py_INCREF( pyfunc );
856 
857  Long_t fid = s_fid++;
858 
859 // basic function name part
860  std::ostringstream funcName;
861  funcName << "pyrootGenFun" << fid;
862 
863 // build-up a signature
864  std::ostringstream sigDecl, argsig;
865  std::vector<std::string>::size_type nargs = signature.size();
866  for ( std::vector<std::string>::size_type i = 0; i < nargs; ++i ) {
867  sigDecl << signature[i] << " a" << i;
868  argsig << ", a" << i;
869  if ( i != nargs-1 ) sigDecl << ", ";
870  }
871 
872 // create full definition
873  std::ostringstream declCode;
874  declCode << "namespace PyROOT { "
875  << retType << " " << callback << "(void*, Long_t, " << sigDecl.str() << "); }\n"
876  << retType << " " << funcName.str() << "(" << sigDecl.str()
877  << ") { void* v0 = (void*)" << (void*)pyfunc << "; "
878  << "return PyROOT::" << callback << "(v0, " << user << argsig.str() << "); }";
879 
880 // body compilation
881  gInterpreter->LoadText( declCode.str().c_str() );
882 
883 // func-ptr retrieval code
884  std::ostringstream fptrCode;
885  fptrCode << "void* pyrootPtrVar" << fid << " = (void*)" << funcName.str()
886  << "; pyrootPtrVar" << fid << ";";
887 
888 // retrieve function pointer
889  void* fptr = (void*)gInterpreter->ProcessLineSynch( fptrCode.str().c_str() );
890  if ( fptr == 0 )
891  PyErr_SetString( PyExc_SyntaxError, "could not generate C++ callback wrapper" );
892 
893  return fptr;
894 }
895 
896 ////////////////////////////////////////////////////////////////////////////////
897 /// Re-acquire the GIL before calling PyErr_Occurred() in case it has been
898 /// released; note that the p2.2 code assumes that there are no callbacks in
899 /// C++ to python (or at least none returning errors).
900 
902 {
903 #if PY_VERSION_HEX >= 0x02030000
904  PyGILState_STATE gstate = PyGILState_Ensure();
905  PyObject* e = PyErr_Occurred();
906  PyGILState_Release( gstate );
907 #else
908  if ( PyThreadState_GET() )
909  return PyErr_Occurred();
910  PyObject* e = 0;
911 #endif
912 
913  return e;
914 }
915 
916 ////////////////////////////////////////////////////////////////////////////////
917 
918 namespace {
919  static int (*sOldInputHook)() = NULL;
920  static PyThreadState* sInputHookEventThreadState = NULL;
921 
922  static int EventInputHook()
923  {
924  // This method is supposed to be called from CPython's command line and
925  // drives the GUI.
926  PyEval_RestoreThread( sInputHookEventThreadState );
928  PyEval_SaveThread();
929 
930  if ( sOldInputHook ) return sOldInputHook();
931  return 0;
932  }
933 
934 } // unnamed namespace
935 
937 {
938 // Install the method hook for sending events to the GUI
939  if ( PyOS_InputHook && PyOS_InputHook != &EventInputHook )
940  sOldInputHook = PyOS_InputHook;
941 
942  sInputHookEventThreadState = PyThreadState_Get();
943 
944  PyOS_InputHook = (int (*)())&EventInputHook;
945  Py_INCREF( Py_None );
946  return Py_None;
947 }
948 
950 {
951 // Remove event hook, if it was installed
952  PyOS_InputHook = sOldInputHook;
953  sInputHookEventThreadState = NULL;
954 
955  Py_INCREF( Py_None );
956  return Py_None;
957 }
Bool_t InitProxy(PyObject *module, PyTypeObject *pytype, const char *name)
Initialize a proxy class for use by python, and add it to the ROOT module.
Definition: Utility.cxx:519
Bool_t AddBinaryOperator(PyObject *left, PyObject *right, const char *op, const char *label, const char *alt_label=NULL)
Install the named operator (op) into the left object&#39;s class if such a function exists as a global ov...
Definition: Utility.cxx:315
#define PyROOT_PyUnicode_FromString
Definition: PyROOT.h:71
PyDictEntry *(* dict_lookup_func)(PyDictObject *, PyObject *, Long_t)
Definition: PyROOT.h:43
#define pyname
Definition: TMCParticle.cxx:19
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:424
R__EXTERN Int_t gErrorIgnoreLevel
Definition: TError.h:105
PyObject * TCustomInstanceMethod_New(PyObject *func, PyObject *self, PyObject *pyclass)
#define PYROOT__long__
Definition: PyROOT.h:89
Dictionary for function template This class describes one single function template.
void DefaultErrorHandler(int level, Bool_t abort, const char *location, const char *msg)
The default error handler function.
Definition: TError.cxx:125
PyObject * RemoveGUIEventInputHook()
Definition: Utility.cxx:949
MethodProxy * MethodProxy_New(const std::string &name, std::vector< PyCallable * > &methods)
Definition: MethodProxy.h:75
#define gROOT
Definition: TROOT.h:410
R__EXTERN dict_lookup_func gDictLookupOrg
Definition: Utility.h:15
#define f(i)
Definition: RSha256.hxx:104
PyObject * BuildTemplateName(PyObject *pyname, PyObject *args, int argoff)
Helper to construct the "< type, type, ... >" part of a templated name (either for a class as in Make...
Definition: Utility.cxx:462
bool Bool_t
Definition: RtypesCore.h:59
#define gInterpreter
Definition: TInterpreter.h:527
R__EXTERN TApplication * gApplication
Definition: TApplication.h:165
R__EXTERN Bool_t gDictLookupActive
Definition: Utility.h:18
TClass * GetClass() const
Definition: TClassRef.h:71
#define PyROOT_PyUnicode_FromFormat
Definition: PyROOT.h:70
#define PyROOT_PyUnicode_Append
Definition: PyROOT.h:73
std::string ResolveName(const std::string &cppitem_name)
Definition: Cppyy.cxx:166
std::string MapOperatorName(const std::string &name, Bool_t bTakesParames)
Map the given C++ operator name on the python equivalent.
Definition: Utility.cxx:612
#define PyROOT_PyUnicode_GetSize
Definition: PyROOT.h:69
#define PYROOT__idiv__
Definition: PyROOT.h:90
R__EXTERN PyObject * gMRO
Definition: PyStrings.h:32
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
ClassInfo_t * GetClassInfo() const
Definition: TClass.h:400
const std::string ClassName(PyObject *pyobj)
Retrieve the class name from the given python object (which may be just an instance of the class)...
Definition: Utility.cxx:702
#define PyROOT_PyUnicode_AsString
Definition: PyROOT.h:66
#define PyBytes_Check
Definition: PyROOT.h:52
PyObject * PyErr_Occurred_WithGIL()
Re-acquire the GIL before calling PyErr_Occurred() in case it has been released; note that the p2...
Definition: Utility.cxx:901
std::map< std::string, std::string > TC2POperatorMapping_t
Definition: Utility.cxx:47
static TC2POperatorMapping_t gC2POperatorMapping
Definition: Utility.cxx:48
R__EXTERN TVirtualMutex * gGlobalMutex
Definition: TVirtualMutex.h:29
ULong_t PyLongOrInt_AsULong(PyObject *pyobject)
Definition: Utility.cxx:145
void ErrMsgHandler(int level, Bool_t abort, const char *location, const char *msg)
Translate ROOT error/warning to python.
Definition: Utility.cxx:809
const Int_t kUnset
Definition: TError.h:35
ptrdiff_t TCppMethod_t
Definition: Cppyy.h:15
Bool_t ObjectProxy_Check(T *object)
Definition: ObjectProxy.h:91
R__EXTERN PyObject * gClass
Definition: PyStrings.h:18
TCppScope_t gGlobalScope
Definition: Cppyy.cxx:63
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
ULong64_t PyLongOrInt_AsULong64(PyObject *pyobject)
Convert <pyobject> to C++ unsigned long long, with bounds checking.
Definition: Utility.cxx:166
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
const Int_t kWarning
Definition: TError.h:38
#define PYROOT__div__
Definition: PyROOT.h:91
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
#define PyROOT_PyUnicode_AppendAndDel
Definition: PyROOT.h:74
PyObject * InstallGUIEventInputHook()
Definition: Utility.cxx:936
TCppScope_t GetScope(const std::string &scope_name)
Definition: Cppyy.cxx:176
R__EXTERN PyObject * gName
Definition: PyStrings.h:33
void AddMethod(PyCallable *pc)
Fill in the data of a freshly created method proxy.
R__EXTERN PyObject * gTypeCode
Definition: PyStrings.h:36
unsigned long long ULong64_t
Definition: RtypesCore.h:70
unsigned long ULong_t
Definition: RtypesCore.h:51
Bool_t AddToClass(PyObject *pyclass, const char *label, PyCFunction cfunc, int flags=METH_VARARGS)
Add the given function to the class under name &#39;label&#39;.
Definition: Utility.cxx:186
#define PyROOT_PyUnicode_Check
Definition: PyROOT.h:64
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2887
Bool_t AddUsingToClass(PyObject *pyclass, const char *method)
Helper to add base class methods to the derived class one (this covers the &#39;using&#39; cases...
Definition: Utility.cxx:261
R__EXTERN PyObject * gCppName
Definition: PyStrings.h:34
TFunctionTemplate * GetFunctionTemplate(const char *name)
Definition: TClass.cxx:3478
TClassRef is used to implement a permanent reference to a TClass object.
Definition: TClassRef.h:29
#define Py_TYPE(ob)
Definition: PyROOT.h:151
int Py_ssize_t
Definition: PyROOT.h:156
int GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, Bool_t check=kTRUE)
Retrieve a linear buffer pointer from the given pyobject.
Definition: Utility.cxx:539
const Int_t kError
Definition: TError.h:39
void * CreateWrapperMethod(PyObject *pyfunc, Long_t user, const char *retType, const std::vector< std::string > &signature, const char *callback)
Compile a function on the fly and return a function pointer for use on C-APIs.
Definition: Utility.cxx:846
Bool_t MethodProxy_Check(T *object)
Definition: MethodProxy.h:63
const char * proto
Definition: civetweb.c:15049
#define c(i)
Definition: RSha256.hxx:101
Py_ssize_t ArraySize(const std::string &name)
Extract size from an array type, if available.
Definition: Utility.cxx:682
void ErrMsgCallback(char *msg)
Translate CINT error/warning into python equivalent.
Definition: Utility.cxx:732
TMethod * GetMethodAny(const char *method)
Return pointer to method without looking at parameters.
Definition: TClass.cxx:4195
static Cppyy::TCppMethod_t FindAndAddOperator(const std::string &lcname, const std::string &rcname, const char *op, TClass *klass=0)
Helper to find a function with matching signature in &#39;funcs&#39;.
Definition: Utility.cxx:350
TMethod * GetMethodWithPrototype(const char *method, const char *proto, Bool_t objectIsConst=kFALSE, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
Find the method with a given prototype.
Definition: TClass.cxx:4277
const Bool_t kTRUE
Definition: RtypesCore.h:87
char name[80]
Definition: TGX11.cxx:109
_object PyObject
Definition: TPyArg.h:20
const std::string Compound(const std::string &name)
Break down the compound of a fully qualified type name.
Definition: Utility.cxx:658