Logo ROOT   6.14/05
Reference Guide
Converters.cxx
Go to the documentation of this file.
1 // @(#)root/pyroot:$Id$
2 // Author: Wim Lavrijsen, Jan 2005
3 
4 // Bindings
5 #include "PyROOT.h"
6 #include "PyStrings.h"
7 #include "Converters.h"
8 #include "TCallContext.h"
9 #include "ObjectProxy.h"
10 #include "TPyBufferFactory.h"
11 #include "TCustomPyTypes.h"
12 #include "TTupleOfInstances.h"
13 #include "Utility.h"
14 #include "RootWrapper.h"
15 
16 // ROOT
17 #include "TClass.h" // for checking class info existence
18 #include "TClassEdit.h" // for CleanType and ShortType
19 
20 // Standard
21 #include <limits.h>
22 #include <stddef.h> // for ptrdiff_t
23 #include <string.h>
24 #include <utility>
25 #include <sstream>
26 
27 // FIXME: Should refer to PyROOT::TParameter in the code.
28 #ifdef R__CXXMODULES
29  #define TParameter PyROOT::TParameter
30 #endif
31 
32 //- data ______________________________________________________________________
33 namespace PyROOT {
34 
35 // factories
36  typedef TConverter* (*ConverterFactory_t) ( Long_t size );
37  typedef std::map< std::string, ConverterFactory_t > ConvFactories_t;
38  ConvFactories_t gConvFactories;
40 
41 }
42 
43 //- pretend-ctypes helpers ----------------------------------------------------
44 #if PY_VERSION_HEX >= 0x02050000
45 
46 struct PyROOT_tagCDataObject { // non-public (but so far very stable)
47  PyObject_HEAD
48  char* b_ptr;
49 };
50 
51 static inline PyTypeObject* GetCTypesType( const char* name ) {
52  PyObject* ct = PyImport_ImportModule( "ctypes" );
53  if ( ! ct ) return nullptr;
54  PyTypeObject* ct_t = (PyTypeObject*)PyObject_GetAttrString( ct, name );
55  Py_DECREF( ct );
56  return ct_t;
57 }
58 
59 #endif
60 
61 //- custom helpers to check ranges --------------------------------------------
62 
63 ////////////////////////////////////////////////////////////////////////////////
64 /// range-checking python integer to C++ bool conversion
65 static inline Bool_t PyROOT_PyLong_AsBool( PyObject* pyobject )
66 {
67  Long_t l = PyLong_AsLong( pyobject );
68 // fail to pass float -> bool; the problem is rounding (0.1 -> 0 -> False)
69  if ( ! ( l == 0 || l == 1 ) || PyFloat_Check( pyobject ) ) {
70  PyErr_SetString( PyExc_ValueError, "boolean value should be bool, or integer 1 or 0" );
71  return (Bool_t)-1;
72  }
73  return (Bool_t)l;
74 }
75 
76 ////////////////////////////////////////////////////////////////////////////////
77 /// python string to C++ char conversion
78 static inline Char_t PyROOT_PyUnicode_AsChar( PyObject* pyobject ) {
79  return (Char_t)PyROOT_PyUnicode_AsString( pyobject )[0];
80 }
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 /// range-checking python integer to C++ unsigned short int conversion
84 static inline UShort_t PyROOT_PyLong_AsUShort( PyObject* pyobject )
85 {
86 // prevent p2.7 silent conversions and do a range check
87  if ( ! (PyLong_Check( pyobject ) || PyInt_Check( pyobject )) ) {
88  PyErr_SetString( PyExc_TypeError, "unsigned short conversion expects an integer object" );
89  return (UShort_t)-1;
90  }
91  Long_t l = PyLong_AsLong( pyobject );
92  if ( l < 0 || USHRT_MAX < l ) {
93  PyErr_Format( PyExc_ValueError, "integer %ld out of range for unsigned short", l );
94  return (UShort_t)-1;
95 
96  }
97  return (UShort_t)l;
98 }
99 
100 ////////////////////////////////////////////////////////////////////////////////
101 /// range-checking python integer to C++ short int conversion
102 static inline Short_t PyROOT_PyLong_AsShort( PyObject* pyobject )
103 {
104 // prevent p2.7 silent conversions and do a range check
105  if ( ! (PyLong_Check( pyobject ) || PyInt_Check( pyobject )) ) {
106  PyErr_SetString( PyExc_TypeError, "short int conversion expects an integer object" );
107  return (Short_t)-1;
108  }
109  Long_t l = PyLong_AsLong( pyobject );
110  if ( l < SHRT_MIN || SHRT_MAX < l ) {
111  PyErr_Format( PyExc_ValueError, "integer %ld out of range for short int", l );
112  return (Short_t)-1;
113 
114  }
115  return (Short_t)l;
116 }
117 
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 /// strict python integer to C++ integer conversion
121 static inline Long_t PyROOT_PyLong_AsStrictLong( PyObject* pyobject )
122 {
123 // p2.7 and later silently converts floats to long, therefore require this
124 // check; earlier pythons may raise a SystemError which should be avoided as
125 // it is confusing
126  if ( ! (PyLong_Check( pyobject ) || PyInt_Check( pyobject )) ) {
127  PyErr_SetString( PyExc_TypeError, "int/long conversion expects an integer object" );
128  return (Long_t)-1;
129  }
130  return (Long_t)PyLong_AsLong( pyobject );
131 }
132 
133 
134 //- base converter implementation ---------------------------------------------
136 {
137 // could happen if no derived class override
138  PyErr_SetString( PyExc_TypeError, "C++ type can not be converted from memory" );
139  return 0;
140 }
141 
142 ////////////////////////////////////////////////////////////////////////////////
143 /// could happen if no derived class override
144 
146 {
147  PyErr_SetString( PyExc_TypeError, "C++ type can not be converted to memory" );
148  return kFALSE;
149 }
150 
151 
152 //- helper macro's ------------------------------------------------------------
153 #define PYROOT_IMPLEMENT_BASIC_CONVERTER( name, type, stype, F1, F2, tc ) \
154 Bool_t PyROOT::T##name##Converter::SetArg( \
155  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ ) \
156 { \
157 /* convert `pyobject` to C++ 'type', set arg for call */ \
158  type val = (type)F2( pyobject ); \
159  if ( val == (type)-1 && PyErr_Occurred() ) \
160  return kFALSE; \
161  para.fValue.f##name = val; \
162  para.fTypeCode = tc; \
163  return kTRUE; \
164 } \
165  \
166 PyObject* PyROOT::T##name##Converter::FromMemory( void* address ) \
167 { \
168  return F1( (stype)*((type*)address) ); \
169 } \
170  \
171 Bool_t PyROOT::T##name##Converter::ToMemory( PyObject* value, void* address ) \
172 { \
173  type s = (type)F2( value ); \
174  if ( s == (type)-1 && PyErr_Occurred() ) \
175  return kFALSE; \
176  *((type*)address) = (type)s; \
177  return kTRUE; \
178 }
179 
180 
181 static inline Int_t ExtractChar( PyObject* pyobject, const char* tname, Int_t low, Int_t high )
182 {
183  Int_t lchar = -1;
184  if ( PyROOT_PyUnicode_Check( pyobject ) ) {
185  if ( PyROOT_PyUnicode_GET_SIZE( pyobject ) == 1 )
186  lchar = (Int_t)PyROOT_PyUnicode_AsChar( pyobject );
187  else
188  PyErr_Format( PyExc_TypeError, "%s expected, got string of size " PY_SSIZE_T_FORMAT,
189  tname, PyROOT_PyUnicode_GET_SIZE( pyobject ) );
190  } else if ( ! PyFloat_Check( pyobject ) ) { // don't allow truncating conversion
191  lchar = PyLong_AsLong( pyobject );
192  if ( lchar == -1 && PyErr_Occurred() )
193  ; // empty, as error already set
194  else if ( ! ( low <= lchar && lchar <= high ) ) {
195  PyErr_Format( PyExc_ValueError,
196  "integer to character: value %d not in range [%d,%d]", lchar, low, high );
197  lchar = -1;
198  }
199  } else
200  PyErr_SetString( PyExc_TypeError, "char or small int type expected" );
201 
202  return lchar;
203 }
204 
205 
206 #define PYROOT_IMPLEMENT_BASIC_CONST_REF_CONVERTER( name, type, F1 )\
207 Bool_t PyROOT::TConst##name##RefConverter::SetArg( \
208  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ ) \
209 { \
210  type val = (type)F1( pyobject ); \
211  if ( val == (type)-1 && PyErr_Occurred() ) \
212  return kFALSE; \
213  para.fValue.f##name = val; \
214  para.fRef = &para.fValue.f##name; \
215  para.fTypeCode = 'r'; \
216  return kTRUE; \
217 }
218 
219 #define PYROOT_IMPLEMENT_BASIC_CONST_CHAR_REF_CONVERTER( name, type, low, high )\
220 Bool_t PyROOT::TConst##name##RefConverter::SetArg( \
221  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ ) \
222 { \
223 /* convert `pyobject` to C++ <<type>>, set arg for call, allow int -> char */ \
224  type val = (type)ExtractChar( pyobject, #type, low, high ); \
225  if ( val == (type)-1 && PyErr_Occurred() ) \
226  return kFALSE; \
227  para.fValue.fLong = val; \
228  para.fTypeCode = 'l'; \
229  return kTRUE; \
230 }
231 
232 
233 ////////////////////////////////////////////////////////////////////////////////
234 
235 #define PYROOT_IMPLEMENT_BASIC_CHAR_CONVERTER( name, type, low, high ) \
236 Bool_t PyROOT::T##name##Converter::SetArg( \
237  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ ) \
238 { \
239 /* convert `pyobject` to C++ <<type>>, set arg for call, allow int -> char */ \
240  Long_t val = ExtractChar( pyobject, #type, low, high ); \
241  if ( val == -1 && PyErr_Occurred() ) \
242  return kFALSE; \
243  para.fValue.fLong = val; \
244  para.fTypeCode = 'l'; \
245  return kTRUE; \
246 } \
247  \
248 PyObject* PyROOT::T##name##Converter::FromMemory( void* address ) \
249 { \
250  return PyROOT_PyUnicode_FromFormat( "%c", *((type*)address) ); \
251 } \
252  \
253 Bool_t PyROOT::T##name##Converter::ToMemory( PyObject* value, void* address ) \
254 { \
255  if ( PyROOT_PyUnicode_Check( value ) ) { \
256  const char* buf = PyROOT_PyUnicode_AsString( value ); \
257  if ( PyErr_Occurred() ) \
258  return kFALSE; \
259  int len = PyROOT_PyUnicode_GET_SIZE( value ); \
260  if ( len != 1 ) { \
261  PyErr_Format( PyExc_TypeError, #type" expected, got string of size %d", len );\
262  return kFALSE; \
263  } \
264  *((type*)address) = (type)buf[0]; \
265  } else { \
266  Long_t l = PyLong_AsLong( value ); \
267  if ( l == -1 && PyErr_Occurred() ) \
268  return kFALSE; \
269  if ( ! ( low <= l && l <= high ) ) { \
270  PyErr_Format( PyExc_ValueError, \
271  "integer to character: value %ld not in range [%d,%d]", l, low, high );\
272  return kFALSE; \
273  } \
274  *((type*)address) = (type)l; \
275  } \
276  return kTRUE; \
277 }
278 
279 
280 //- converters for built-ins --------------------------------------------------
282 
283 ////////////////////////////////////////////////////////////////////////////////
284 /// convert `pyobject` to C++ long&, set arg for call
285 
286 Bool_t PyROOT::TLongRefConverter::SetArg(
287  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
288 {
289 #if PY_VERSION_HEX < 0x03000000
290  if ( TCustomInt_CheckExact( pyobject ) ) {
291  para.fValue.fVoidp = (void*)&((PyIntObject*)pyobject)->ob_ival;
292  para.fTypeCode = 'V';
293  return kTRUE;
294  }
295 #endif
296 
297 #if PY_VERSION_HEX < 0x02050000
298  PyErr_SetString( PyExc_TypeError, "use ROOT.Long for pass-by-ref of longs" );
299  return kFALSE;
300 #endif
301 
302 // TODO: this keeps a refcount to the type .. it should be okay to drop that
303  static PyTypeObject* c_long_type = GetCTypesType( "c_long" );
304  if ( Py_TYPE( pyobject ) == c_long_type ) {
305  para.fValue.fVoidp = (void*)((PyROOT_tagCDataObject*)pyobject)->b_ptr;
306  para.fTypeCode = 'V';
307  return kTRUE;
308  }
309 
310  PyErr_SetString( PyExc_TypeError, "use ctypes.c_long for pass-by-ref of longs" );
311  return kFALSE;
312 }
313 
314 ////////////////////////////////////////////////////////////////////////////////
315 
318 
326 PYROOT_IMPLEMENT_BASIC_CONST_REF_CONVERTER( LongLong, Long64_t, PyLong_AsLongLong )
328 
329 ////////////////////////////////////////////////////////////////////////////////
330 /// convert `pyobject` to C++ (pseudo)int&, set arg for call
331 
332 Bool_t PyROOT::TIntRefConverter::SetArg(
333  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
334 {
335 #if PY_VERSION_HEX < 0x03000000
336  if ( TCustomInt_CheckExact( pyobject ) ) {
337  para.fValue.fVoidp = (void*)&((PyIntObject*)pyobject)->ob_ival;
338  para.fTypeCode = 'V';
339  return kTRUE;
340  }
341 #endif
342 
343 #if PY_VERSION_HEX >= 0x02050000
344 // TODO: this keeps a refcount to the type .. it should be okay to drop that
345  static PyTypeObject* c_int_type = GetCTypesType( "c_int" );
346  if ( Py_TYPE( pyobject ) == c_int_type ) {
347  para.fValue.fVoidp = (void*)((PyROOT_tagCDataObject*)pyobject)->b_ptr;
348  para.fTypeCode = 'V';
349  return kTRUE;
350  }
351 #endif
352 
353 // alternate, pass pointer from buffer
354  int buflen = Utility::GetBuffer( pyobject, 'i', sizeof(int), para.fValue.fVoidp );
355  if ( para.fValue.fVoidp && buflen ) {
356  para.fTypeCode = 'V';
357  return kTRUE;
358  };
359 
360 #if PY_VERSION_HEX < 0x02050000
361  PyErr_SetString( PyExc_TypeError, "use ROOT.Long for pass-by-ref of ints" );
362 #else
363  PyErr_SetString( PyExc_TypeError, "use ctypes.c_int for pass-by-ref of ints" );
364 #endif
365  return kFALSE;
366 }
367 
368 ////////////////////////////////////////////////////////////////////////////////
369 /// convert `pyobject` to C++ bool, allow int/long -> bool, set arg for call
370 
372 
373 ////////////////////////////////////////////////////////////////////////////////
374 
375 PYROOT_IMPLEMENT_BASIC_CHAR_CONVERTER( Char, Char_t, CHAR_MIN, CHAR_MAX )
377 
378 ////////////////////////////////////////////////////////////////////////////////
379 
383 
384 ////////////////////////////////////////////////////////////////////////////////
385 /// convert `pyobject` to C++ unsigned long, set arg for call
386 
387 Bool_t PyROOT::TULongConverter::SetArg(
388  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
389 {
390  para.fValue.fULong = PyLongOrInt_AsULong( pyobject );
391  if ( PyErr_Occurred() )
392  return kFALSE;
393  para.fTypeCode = 'U';
394  return kTRUE;
395 }
396 
397 PyObject* PyROOT::TULongConverter::FromMemory( void* address )
398 {
399 // construct python object from C++ unsigned long read at <address>
400  return PyLong_FromUnsignedLong( *((ULong_t*)address) );
401 }
402 
403 Bool_t PyROOT::TULongConverter::ToMemory( PyObject* value, void* address )
404 {
405 // convert <value> to C++ unsigned long, write it at <address>
406  ULong_t u = PyLongOrInt_AsULong( value );
407  if ( PyErr_Occurred() )
408  return kFALSE;
409  *((ULong_t*)address) = u;
410  return kTRUE;
411 }
412 
413 ////////////////////////////////////////////////////////////////////////////////
414 /// construct python object from C++ unsigned int read at <address>
415 
416 PyObject* PyROOT::TUIntConverter::FromMemory( void* address )
417 {
418  return PyLong_FromUnsignedLong( *((UInt_t*)address) );
419 }
420 
421 Bool_t PyROOT::TUIntConverter::ToMemory( PyObject* value, void* address )
422 {
423 // convert <value> to C++ unsigned int, write it at <address>
424  ULong_t u = PyLongOrInt_AsULong( value );
425  if ( PyErr_Occurred() )
426  return kFALSE;
427 
428  if ( u > (ULong_t)UINT_MAX ) {
429  PyErr_SetString( PyExc_OverflowError, "value too large for unsigned int" );
430  return kFALSE;
431  }
432 
433  *((UInt_t*)address) = (UInt_t)u;
434  return kTRUE;
435 }
436 
437 ////////////////////////////////////////////////////////////////////////////////
438 /// floating point converters
439 
440 PYROOT_IMPLEMENT_BASIC_CONVERTER( Float, Float_t, Double_t, PyFloat_FromDouble, PyFloat_AsDouble, 'f' )
441 PYROOT_IMPLEMENT_BASIC_CONVERTER( Double, Double_t, Double_t, PyFloat_FromDouble, PyFloat_AsDouble, 'd' )
442 
443 PYROOT_IMPLEMENT_BASIC_CONVERTER( LongDouble, LongDouble_t, LongDouble_t, PyFloat_FromDouble, PyFloat_AsDouble, 'D' )
444 
445 ////////////////////////////////////////////////////////////////////////////////
446 /// convert `pyobject` to C++ double&, set arg for call
447 
448 Bool_t PyROOT::TDoubleRefConverter::SetArg(
449  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
450 {
451  if ( TCustomFloat_CheckExact( pyobject ) ) {
452  para.fValue.fVoidp = (void*)&((PyFloatObject*)pyobject)->ob_fval;
453  para.fTypeCode = 'V';
454  return kTRUE;
455  }
456 
457 // alternate, pass pointer from buffer
458  int buflen = Utility::GetBuffer( pyobject, 'd', sizeof(double), para.fValue.fVoidp );
459  if ( para.fValue.fVoidp && buflen ) {
460  para.fTypeCode = 'V';
461  return kTRUE;
462  }
463 
464  PyErr_SetString( PyExc_TypeError, "use ROOT.Double for pass-by-ref of doubles" );
465  return kFALSE;
466 }
467 
468 ////////////////////////////////////////////////////////////////////////////////
469 
472 PYROOT_IMPLEMENT_BASIC_CONST_REF_CONVERTER( LongDouble, LongDouble_t, PyFloat_AsDouble )
473 
474 ////////////////////////////////////////////////////////////////////////////////
475 /// can't happen (unless a type is mapped wrongly), but implemented for completeness
476 
478 {
479  PyErr_SetString( PyExc_SystemError, "void/unknown arguments can\'t be set" );
480  return kFALSE;
481 }
482 
483 ////////////////////////////////////////////////////////////////////////////////
484 /// convert `pyobject` to C++ long long, set arg for call
485 
486 Bool_t PyROOT::TLongLongConverter::SetArg(
487  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
488 {
489  if ( PyFloat_Check( pyobject ) ) {
490  // special case: float implements nb_int, but allowing rounding conversions
491  // interferes with overloading
492  PyErr_SetString( PyExc_ValueError, "can not convert float to long long" );
493  return kFALSE;
494  }
495 
496  para.fValue.fLongLong = PyLong_AsLongLong( pyobject );
497  if ( PyErr_Occurred() )
498  return kFALSE;
499  para.fTypeCode = 'k';
500  return kTRUE;
501 }
502 
503 PyObject* PyROOT::TLongLongConverter::FromMemory( void* address )
504 {
505 // construct python object from C++ long long read at <address>
506  return PyLong_FromLongLong( *(Long64_t*)address );
507 }
508 
509 Bool_t PyROOT::TLongLongConverter::ToMemory( PyObject* value, void* address )
510 {
511 // convert <value> to C++ long long, write it at <address>
512  Long64_t ll = PyLong_AsLongLong( value );
513  if ( ll == -1 && PyErr_Occurred() )
514  return kFALSE;
515  *((Long64_t*)address) = ll;
516  return kTRUE;
517 }
518 
519 ////////////////////////////////////////////////////////////////////////////////
520 /// convert `pyobject` to C++ unsigned long long, set arg for call
521 
522 Bool_t PyROOT::TULongLongConverter::SetArg(
523  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
524 {
525  para.fValue.fULongLong = PyLongOrInt_AsULong64( pyobject );
526  if ( PyErr_Occurred() )
527  return kFALSE;
528  para.fTypeCode = 'K';
529  return kTRUE;
530 }
531 
532 PyObject* PyROOT::TULongLongConverter::FromMemory( void* address )
533 {
534 // construct python object from C++ unsigned long long read at <address>
535  return PyLong_FromUnsignedLongLong( *(ULong64_t*)address );
536 }
537 
538 Bool_t PyROOT::TULongLongConverter::ToMemory( PyObject* value, void* address )
539 {
540 // convert <value> to C++ unsigned long long, write it at <address>
541  Long64_t ull = PyLongOrInt_AsULong64( value );
542  if ( PyErr_Occurred() )
543  return kFALSE;
544  *((ULong64_t*)address) = ull;
545  return kTRUE;
546 }
547 
548 ////////////////////////////////////////////////////////////////////////////////
549 /// construct a new string and copy it in new memory
550 
552  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
553 {
554  const char* s = PyROOT_PyUnicode_AsStringChecked( pyobject );
555  if ( PyErr_Occurred() )
556  return kFALSE;
557 
558  fBuffer = std::string( s, PyROOT_PyUnicode_GET_SIZE( pyobject ) );
559 
560 // verify (too long string will cause truncation, no crash)
561  if ( fMaxSize < (UInt_t)fBuffer.size() )
562  PyErr_Warn( PyExc_RuntimeWarning, (char*)"string too long for char array (truncated)" );
563  else if ( fMaxSize != UINT_MAX )
564  fBuffer.resize( fMaxSize, '\0' ); // padd remainder of buffer as needed
565 
566 // set the value and declare success
567  para.fValue.fVoidp = (void*)fBuffer.c_str();
568  para.fTypeCode = 'p';
569  return kTRUE;
570 }
571 
573 {
574 // construct python object from C++ const char* read at <address>
575  if ( address && *(char**)address ) {
576  if ( fMaxSize != UINT_MAX ) { // need to prevent reading beyond boundary
577  std::string buf( *(char**)address, fMaxSize ); // cut on fMaxSize
578  return PyROOT_PyUnicode_FromString( buf.c_str() ); // cut on \0
579  }
580 
581  return PyROOT_PyUnicode_FromString( *(char**)address );
582  }
583 
584 // empty string in case there's no address
585  Py_INCREF( PyStrings::gEmptyString );
587 }
588 
590 {
591 // convert <value> to C++ const char*, write it at <address>
592  const char* s = PyROOT_PyUnicode_AsStringChecked( value );
593  if ( PyErr_Occurred() )
594  return kFALSE;
595 
596 // verify (too long string will cause truncation, no crash)
597  if ( fMaxSize < (UInt_t)PyROOT_PyUnicode_GET_SIZE( value ) )
598  PyErr_Warn( PyExc_RuntimeWarning, (char*)"string too long for char array (truncated)" );
599 
600  if ( fMaxSize != UINT_MAX )
601  strncpy( *(char**)address, s, fMaxSize ); // padds remainder
602  else
603  // coverity[secure_coding] - can't help it, it's intentional.
604  strcpy( *(char**)address, s );
605 
606  return kTRUE;
607 }
608 
609 
610 //- pointer/array conversions -------------------------------------------------
611 namespace {
612 
613  using namespace PyROOT;
614 
615  inline Bool_t CArraySetArg(
616  PyObject* pyobject, TParameter& para, char tc, int size )
617  {
618  // general case of loading a C array pointer (void* + type code) as function argument
619  if ( pyobject == gNullPtrObject ) {
620  para.fValue.fVoidp = NULL;
621  } else {
622  int buflen = Utility::GetBuffer( pyobject, tc, size, para.fValue.fVoidp );
623  if ( ! para.fValue.fVoidp || buflen == 0 )
624  return kFALSE;
625  }
626  para.fTypeCode = 'p';
627  return kTRUE;
628  }
629 
630 } // unnamed namespace
631 
632 
633 ////////////////////////////////////////////////////////////////////////////////
634 /// attempt base class first (i.e. passing a string), but if that fails, try a buffer
635 
637  PyObject* pyobject, TParameter& para, TCallContext* ctxt )
638 {
639  if ( this->TCStringConverter::SetArg( pyobject, para, ctxt ) )
640  return kTRUE;
641 
642 // apparently failed, try char buffer
643  PyErr_Clear();
644  return CArraySetArg( pyobject, para, 'c', sizeof(char) );
645 }
646 
647 ////////////////////////////////////////////////////////////////////////////////
648 /// assume this is a buffer access if the size is known; otherwise assume string
649 
651 {
652  if ( fMaxSize != UINT_MAX )
653  return PyROOT_PyUnicode_FromStringAndSize( *(char**)address, fMaxSize );
654  return this->TCStringConverter::FromMemory( address );
655 }
656 
657 ////////////////////////////////////////////////////////////////////////////////
658 /// attempt base class first (i.e. passing a string), but if that fails, try a buffer
659 
661  PyObject* pyobject, TParameter& para, TCallContext* ctxt )
662 {
663  if ( this->TCStringConverter::SetArg( pyobject, para, ctxt ) )
664  return kTRUE;
665 
666 // apparently failed, try char buffer
667  PyErr_Clear();
668  return CArraySetArg( pyobject, para, 'B', sizeof(unsigned char) );
669 }
670 
671 ////////////////////////////////////////////////////////////////////////////////
672 /// (1): "null pointer" or C++11 style nullptr
673 
675 {
676  if ( pyobject == Py_None || pyobject == gNullPtrObject ) {
677  address = (void*)0;
678  return kTRUE;
679  }
680 
681 // (2): allow integer zero to act as a null pointer, no deriveds
682  if ( PyInt_CheckExact( pyobject ) || PyLong_CheckExact( pyobject ) ) {
683  Long_t val = (Long_t)PyLong_AsLong( pyobject );
684  if ( val == 0l ) {
685  address = (void*)val;
686  return kTRUE;
687  }
688 
689  return kFALSE;
690  }
691 
692 // (3): opaque PyCapsule (CObject in older pythons) from somewhere
693  if ( PyROOT_PyCapsule_CheckExact( pyobject ) ) {
694  address = (void*)PyROOT_PyCapsule_GetPointer( pyobject, NULL );
695  return kTRUE;
696  }
697 
698  return kFALSE;
699 }
700 
701 ////////////////////////////////////////////////////////////////////////////////
702 /// just convert pointer if it is a ROOT object
703 
705  PyObject* pyobject, TParameter& para, TCallContext* ctxt )
706 {
707  if ( ObjectProxy_Check( pyobject ) ) {
708  // depending on memory policy, some objects are no longer owned when passed to C++
709  if ( ! fKeepControl && ! UseStrictOwnership( ctxt ) )
710  ((ObjectProxy*)pyobject)->Release();
711 
712  // set pointer (may be null) and declare success
713  para.fValue.fVoidp = ((ObjectProxy*)pyobject)->GetObject();
714  para.fTypeCode = 'p';
715  return kTRUE;
716  }
717 
718 // handle special cases
719  if ( GetAddressSpecialCase( pyobject, para.fValue.fVoidp ) ) {
720  para.fTypeCode = 'p';
721  return kTRUE;
722  }
723 
724 // final try: attempt to get buffer
725  int buflen = Utility::GetBuffer( pyobject, '*', 1, para.fValue.fVoidp, kFALSE );
726 
727 // ok if buffer exists (can't perform any useful size checks)
728  if ( para.fValue.fVoidp && buflen != 0 ) {
729  para.fTypeCode = 'p';
730  return kTRUE;
731  }
732 
733 // give up
734  return kFALSE;
735 }
736 
737 ////////////////////////////////////////////////////////////////////////////////
738 /// nothing sensible can be done, just return <address> as pylong
739 
741 {
742  if ( ! address || *(ptrdiff_t*)address == 0 ) {
743  Py_INCREF( gNullPtrObject );
744  return gNullPtrObject;
745  }
746  return BufFac_t::Instance()->PyBuffer_FromMemory( (Long_t*)*(ptrdiff_t**)address, sizeof(void*) );
747 }
748 
749 ////////////////////////////////////////////////////////////////////////////////
750 /// just convert pointer if it is a ROOT object
751 
753 {
754  if ( ObjectProxy_Check( value ) ) {
755  // depending on memory policy, some objects are no longer owned when passed to C++
756  if ( ! fKeepControl && TCallContext::sMemoryPolicy != TCallContext::kUseStrict )
757  ((ObjectProxy*)value)->Release();
758 
759  // set pointer (may be null) and declare success
760  *(void**)address = ((ObjectProxy*)value)->GetObject();
761  return kTRUE;
762  }
763 
764 // handle special cases
765  void* ptr = 0;
766  if ( GetAddressSpecialCase( value, ptr ) ) {
767  *(void**)address = ptr;
768  return kTRUE;
769  }
770 
771 // final try: attempt to get buffer
772  void* buf = 0;
773  int buflen = Utility::GetBuffer( value, '*', 1, buf, kFALSE );
774  if ( ! buf || buflen == 0 )
775  return kFALSE;
776 
777  *(void**)address = buf;
778  return kTRUE;
779 }
780 
781 ////////////////////////////////////////////////////////////////////////////////
782 
783 #define PYROOT_IMPLEMENT_ARRAY_CONVERTER( name, type, code ) \
784 Bool_t PyROOT::T##name##ArrayConverter::SetArg( \
785  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ ) \
786 { \
787  return CArraySetArg( pyobject, para, code, sizeof(type) ); \
788 } \
789  \
790 Bool_t PyROOT::T##name##ArrayRefConverter::SetArg( \
791  PyObject* pyobject, TParameter& para, TCallContext* ctxt ) \
792 { \
793  Bool_t result = T##name##ArrayConverter::SetArg( pyobject, para, ctxt ); \
794  para.fTypeCode = 'V'; \
795  return result; \
796 } \
797  \
798 PyObject* PyROOT::T##name##ArrayConverter::FromMemory( void* address ) \
799 { \
800  return BufFac_t::Instance()->PyBuffer_FromMemory( *(type**)address, fSize * sizeof(type) );\
801 } \
802  \
803 Bool_t PyROOT::T##name##ArrayConverter::ToMemory( PyObject* value, void* address )\
804 { \
805  void* buf = 0; \
806  int buflen = Utility::GetBuffer( value, code, sizeof(type), buf ); \
807  if ( ! buf || buflen == 0 ) \
808  return kFALSE; \
809  if ( 0 <= fSize ) { \
810  if ( fSize < buflen/(int)sizeof(type) ) { \
811  PyErr_SetString( PyExc_ValueError, "buffer too large for value" ); \
812  return kFALSE; \
813  } \
814  memcpy( *(type**)address, buf, 0 < buflen ? ((size_t) buflen) : sizeof(type) );\
815  } else \
816  *(type**)address = (type*)buf; \
817  return kTRUE; \
818 }
819 
820 ////////////////////////////////////////////////////////////////////////////////
821 
831 
832 ////////////////////////////////////////////////////////////////////////////////
833 /// convert `pyobject` to C++ long long*, set arg for call
834 
836  PyObject* pyobject, TParameter& para, TCallContext* ctxt )
837 {
838  PyObject* pytc = PyObject_GetAttr( pyobject, PyStrings::gTypeCode );
839  if ( pytc != 0 ) { // iow, this array has a known type, but there's no
840  Py_DECREF( pytc ); // such thing for long long in module array
841  return kFALSE;
842  }
843 
844  return TVoidArrayConverter::SetArg( pyobject, para, ctxt );
845 }
846 
847 
848 //- converters for special cases ----------------------------------------------
849 #define PYROOT_IMPLEMENT_STRING_AS_PRIMITIVE_CONVERTER( name, type, F1, F2 ) \
850 PyROOT::T##name##Converter::T##name##Converter( Bool_t keepControl ) : \
851  TCppObjectConverter( Cppyy::GetScope( #type ), keepControl ) {} \
852  \
853 Bool_t PyROOT::T##name##Converter::SetArg( \
854  PyObject* pyobject, TParameter& para, TCallContext* ctxt ) \
855 { \
856  if ( PyROOT_PyUnicode_Check( pyobject ) ) { \
857  fBuffer = type( PyROOT_PyUnicode_AsString( pyobject ), \
858  PyROOT_PyUnicode_GET_SIZE( pyobject ) ); \
859  para.fValue.fVoidp = &fBuffer; \
860  para.fTypeCode = 'V'; \
861  return kTRUE; \
862  } \
863  \
864  if ( ! ( PyInt_Check( pyobject ) || PyLong_Check( pyobject ) ) ) { \
865  Bool_t result = TCppObjectConverter::SetArg( pyobject, para, ctxt ); \
866  para.fTypeCode = 'V'; \
867  return result; \
868  } \
869  return kFALSE; \
870 } \
871  \
872 PyObject* PyROOT::T##name##Converter::FromMemory( void* address ) \
873 { \
874  if ( address ) \
875  return PyROOT_PyUnicode_FromStringAndSize( ((type*)address)->F1(), ((type*)address)->F2() );\
876  Py_INCREF( PyStrings::gEmptyString ); \
877  return PyStrings::gEmptyString; \
878 } \
879  \
880 Bool_t PyROOT::T##name##Converter::ToMemory( PyObject* value, void* address ) \
881 { \
882  if ( PyROOT_PyUnicode_Check( value ) ) { \
883  *((type*)address) = PyROOT_PyUnicode_AsString( value ); \
884  return kTRUE; \
885  } \
886  \
887  return TCppObjectConverter::ToMemory( value, address ); \
888 }
889 
890 PYROOT_IMPLEMENT_STRING_AS_PRIMITIVE_CONVERTER( TString, TString, Data, Length )
891 PYROOT_IMPLEMENT_STRING_AS_PRIMITIVE_CONVERTER( STLString, std::string, c_str, size )
893 
894 ////////////////////////////////////////////////////////////////////////////////
895 /// convert `pyobject` to C++ instance*, set arg for call
896 
898  PyObject* pyobject, TParameter& para, TCallContext* ctxt )
899 {
900  if ( ! ObjectProxy_Check( pyobject ) ) {
901  if ( GetAddressSpecialCase( pyobject, para.fValue.fVoidp ) ) {
902  para.fTypeCode = 'p'; // allow special cases such as NULL
903  return kTRUE;
904  }
905 
906  // not a PyROOT object (TODO: handle SWIG etc.)
907  return kFALSE;
908  }
909 
910  ObjectProxy* pyobj = (ObjectProxy*)pyobject;
911  if ( pyobj->ObjectIsA() && Cppyy::IsSubtype( pyobj->ObjectIsA(), fClass ) ) {
912  // depending on memory policy, some objects need releasing when passed into functions
913  if ( ! KeepControl() && ! UseStrictOwnership( ctxt ) )
914  ((ObjectProxy*)pyobject)->Release();
915 
916  // calculate offset between formal and actual arguments
917  para.fValue.fVoidp = pyobj->GetObject();
918  if ( pyobj->ObjectIsA() != fClass ) {
919  para.fValue.fLong += Cppyy::GetBaseOffset(
920  pyobj->ObjectIsA(), fClass, para.fValue.fVoidp, 1 /* up-cast */ );
921  }
922 
923  // set pointer (may be null) and declare success
924  para.fTypeCode = 'p';
925  return kTRUE;
926 
927  } else if ( ! TClass::GetClass( Cppyy::GetFinalName( fClass ).c_str() )->GetClassInfo() ) {
928  // assume "user knows best" to allow anonymous pointer passing
929  para.fValue.fVoidp = pyobj->GetObject();
930  para.fTypeCode = 'p';
931  return kTRUE;
932  }
933 
934  return kFALSE;
935 }
936 
937 ////////////////////////////////////////////////////////////////////////////////
938 /// construct python object from C++ instance read at <address>
939 
941 {
942  return BindCppObject( address, fClass, kFALSE );
943 }
944 
945 ////////////////////////////////////////////////////////////////////////////////
946 /// convert <value> to C++ instance, write it at <address>
947 
949 {
950  if ( ! ObjectProxy_Check( value ) ) {
951  void* ptr = 0;
952  if ( GetAddressSpecialCase( value, ptr ) ) {
953  *(void**)address = ptr; // allow special cases such as NULL
954  return kTRUE;
955  }
956 
957  // not a PyROOT object (TODO: handle SWIG etc.)
958  return kFALSE;
959  }
960 
961  if ( Cppyy::IsSubtype( ((ObjectProxy*)value)->ObjectIsA(), fClass ) ) {
962  // depending on memory policy, some objects need releasing when passed into functions
963  if ( ! KeepControl() && TCallContext::sMemoryPolicy != TCallContext::kUseStrict )
964  ((ObjectProxy*)value)->Release();
965 
966  // call assignment operator through a temporarily wrapped object proxy
967  PyObject* pyobj = BindCppObjectNoCast( address, fClass );
968  ((ObjectProxy*)pyobj)->Release(); // TODO: might be recycled (?)
969  PyObject* result = PyObject_CallMethod( pyobj, (char*)"__assign__", (char*)"O", value );
970  Py_DECREF( pyobj );
971  if ( result ) {
972  Py_DECREF( result );
973  return kTRUE;
974  }
975  }
976 
977  return kFALSE;
978 }
979 
980 // TODO: CONSOLIDATE ValueCpp, RefCpp, and CppObject ...
981 
982 ////////////////////////////////////////////////////////////////////////////////
983 /// convert `pyobject` to C++ instance, set arg for call
984 
986  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
987 {
988  if ( ObjectProxy_Check( pyobject ) ) {
989  ObjectProxy* pyobj = (ObjectProxy*)pyobject;
990  if ( pyobj->ObjectIsA() && Cppyy::IsSubtype( pyobj->ObjectIsA(), fClass ) ) {
991  // calculate offset between formal and actual arguments
992  para.fValue.fVoidp = pyobj->GetObject();
993  if ( ! para.fValue.fVoidp )
994  return kFALSE;
995 
996  if ( pyobj->ObjectIsA() != fClass ) {
998  pyobj->ObjectIsA(), fClass, para.fValue.fVoidp, 1 /* up-cast */ );
999  }
1000 
1001  para.fTypeCode = 'V';
1002  return kTRUE;
1003  }
1004  }
1005  else if ( PyTuple_Check( pyobject ) ){ // It is a Python tuple (equivalent to a C++ initializer list)
1006 
1007  // instantiate an object proxy of this class
1008  if( ! fObjProxy ) {
1009  // retrieve the python class from which we will create an instance
1010  PyObject* pyclass = CreateScopeProxy( fClass );
1011  if ( ! pyclass ) return kFALSE; // error has been set in CreateScopeProxy
1012  fObjProxy = (ObjectProxy*)((PyTypeObject*)pyclass)->tp_new( (PyTypeObject*)pyclass, NULL, NULL );
1013  Py_DECREF( pyclass );
1014  }
1015 
1016  if( fObjProxy->GetObject() ) {
1017  // the actual C++ object was already created (in a previous call), so we need to destroy it
1018  Cppyy::CallDestructor( fObjProxy->ObjectIsA(), fObjProxy->GetObject() );
1019  Cppyy::Deallocate( fObjProxy->ObjectIsA(), fObjProxy->GetObject() );
1020  fObjProxy->Set(nullptr);
1021  }
1022 
1023  // get the constructor (i.e. __init__)
1024  PyObject* constructor = PyObject_GetAttr( (PyObject*)fObjProxy, PyStrings::gInit );
1025  if( ! constructor ) return kFALSE;
1026 
1027  // call the constructor with the arguments in the given tuple
1028  PyObject* obj = PyObject_CallObject( constructor, pyobject );
1029  Py_DECREF( constructor );
1030  if ( ! obj ) return kFALSE;
1031  Py_DECREF( obj );
1032 
1033  para.fValue.fVoidp = fObjProxy->GetObject();
1034  para.fTypeCode = 'V';
1035  return kTRUE;
1036 
1037  }
1038  return kFALSE;
1039 }
1040 
1041 ////////////////////////////////////////////////////////////////////////////////
1042 /// convert `pyobject` to C++ instance&, set arg for call
1043 
1045  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
1046 {
1047  if ( ObjectProxy_Check( pyobject ) ) { // It is PyROOT object
1048  ObjectProxy* pyobj = (ObjectProxy*)pyobject;
1049  if ( pyobj->ObjectIsA() && Cppyy::IsSubtype( pyobj->ObjectIsA(), fClass ) ) {
1050  // calculate offset between formal and actual arguments
1051  para.fValue.fVoidp = pyobj->GetObject();
1052  if ( pyobj->ObjectIsA() != fClass ) {
1054  pyobj->ObjectIsA(), fClass, para.fValue.fVoidp, 1 /* up-cast */ );
1055  }
1056 
1057  para.fTypeCode = 'V';
1058  return kTRUE;
1059  } else if ( ! TClass::GetClass( Cppyy::GetFinalName( fClass ).c_str() )->GetClassInfo() ) {
1060  // assume "user knows best" to allow anonymous reference passing
1061  para.fValue.fVoidp = pyobj->GetObject();
1062  para.fTypeCode = 'V';
1063  return kTRUE;
1064  }
1065  }
1066  else if ( PyTuple_Check( pyobject ) ){ // It is a Python tuple (equivalent to a C++ initializer list)
1067 
1068  // instantiate an object proxy of this class
1069  if( ! fObjProxy ) {
1070  // retrieve the python class from which we will create an instance
1071  PyObject* pyclass = CreateScopeProxy( fClass );
1072  if ( ! pyclass ) return kFALSE; // error has been set in CreateScopeProxy
1073  fObjProxy = (ObjectProxy*)((PyTypeObject*)pyclass)->tp_new( (PyTypeObject*)pyclass, NULL, NULL );
1074  Py_DECREF( pyclass );
1075  }
1076 
1077  if( fObjProxy->GetObject() ) {
1078  // the actual C++ object was already created (in a previous call), so we need to destroy it
1079  Cppyy::CallDestructor( fObjProxy->ObjectIsA(), fObjProxy->GetObject() );
1080  Cppyy::Deallocate( fObjProxy->ObjectIsA(), fObjProxy->GetObject() );
1081  fObjProxy->Set(nullptr);
1082  }
1083 
1084  // get the constructor (i.e. __init__)
1085  PyObject* constructor = PyObject_GetAttr( (PyObject*)fObjProxy, PyStrings::gInit );
1086  if( ! constructor ) return kFALSE;
1087 
1088  // call the constructor with the arguments in the given tuple
1089  PyObject* obj = PyObject_CallObject( constructor, pyobject );
1090  Py_DECREF( constructor );
1091  if ( ! obj ) return kFALSE;
1092  Py_DECREF( obj );
1093 
1094  para.fValue.fVoidp = fObjProxy->GetObject();
1095  para.fTypeCode = 'V';
1096  return kTRUE;
1097  }
1098 
1099  return kFALSE;
1100 }
1101 
1102 ////////////////////////////////////////////////////////////////////////////////
1103 /// convert `pyobject` to C++ instance**, set arg for call
1104 
1105 template <bool ISREFERENCE>
1107  PyObject* pyobject, TParameter& para, TCallContext* ctxt )
1108 {
1109  if ( ! ObjectProxy_Check( pyobject ) )
1110  return kFALSE; // not a PyROOT object (TODO: handle SWIG etc.)
1111 
1112  if ( Cppyy::IsSubtype( ((ObjectProxy*)pyobject)->ObjectIsA(), fClass ) ) {
1113  // depending on memory policy, some objects need releasing when passed into functions
1114  if ( ! KeepControl() && ! UseStrictOwnership( ctxt ) )
1115  ((ObjectProxy*)pyobject)->Release();
1116 
1117  // set pointer (may be null) and declare success
1118  if( ((ObjectProxy*)pyobject)->fFlags & ObjectProxy::kIsReference)
1119  // If given object is already a reference (aka pointer) then we should not take the address of it
1120  para.fValue.fVoidp = ((ObjectProxy*)pyobject)->fObject;
1121  else
1122  para.fValue.fVoidp = &((ObjectProxy*)pyobject)->fObject;
1123  para.fTypeCode = ISREFERENCE ? 'V' : 'p';
1124  return kTRUE;
1125  }
1126 
1127  return kFALSE;
1128 }
1129 
1130 ////////////////////////////////////////////////////////////////////////////////
1131 /// construct python object from C++ instance* read at <address>
1132 
1133 template <bool ISREFERENCE>
1135 {
1136  return BindCppObject( address, fClass, kTRUE );
1137 }
1138 
1139 ////////////////////////////////////////////////////////////////////////////////
1140 /// convert <value> to C++ instance*, write it at <address>
1141 
1142 template <bool ISREFERENCE>
1144 {
1145  if ( ! ObjectProxy_Check( value ) )
1146  return kFALSE; // not a PyROOT object (TODO: handle SWIG etc.)
1147 
1148  if ( Cppyy::IsSubtype( ((ObjectProxy*)value)->ObjectIsA(), fClass ) ) {
1149  // depending on memory policy, some objects need releasing when passed into functions
1150  if ( ! KeepControl() && TCallContext::sMemoryPolicy != TCallContext::kUseStrict )
1151  ((ObjectProxy*)value)->Release();
1152 
1153  // set pointer (may be null) and declare success
1154  *(void**)address = ((ObjectProxy*)value)->GetObject();
1155  return kTRUE;
1156  }
1157 
1158  return kFALSE;
1159 }
1160 
1161 
1162 namespace PyROOT {
1163 ////////////////////////////////////////////////////////////////////////////////
1164 /// Instantiate the templates
1165 
1166 template class TCppObjectPtrConverter<true>;
1167 template class TCppObjectPtrConverter<false>;
1168 }
1169 
1170 ////////////////////////////////////////////////////////////////////////////////
1171 /// convert `pyobject` to C++ instance**, set arg for call
1172 
1174  PyObject* pyobject, TParameter& para, TCallContext* /* txt */ )
1175 {
1176  if ( ! TTupleOfInstances_CheckExact( pyobject ) )
1177  return kFALSE; // no guarantee that the tuple is okay
1178 
1179 // treat the first instance of the tuple as the start of the array, and pass it
1180 // by pointer (TODO: store and check sizes)
1181  if ( PyTuple_Size( pyobject ) < 1 )
1182  return kFALSE;
1183 
1184  PyObject* first = PyTuple_GetItem( pyobject, 0 );
1185  if ( ! ObjectProxy_Check( first ) )
1186  return kFALSE; // should not happen
1187 
1188  if ( Cppyy::IsSubtype( ((ObjectProxy*)first)->ObjectIsA(), fClass ) ) {
1189  // no memory policies supported; set pointer (may be null) and declare success
1190  para.fValue.fVoidp = ((ObjectProxy*)first)->fObject;
1191  para.fTypeCode = 'p';
1192  return kTRUE;
1193  }
1194 
1195  return kFALSE;
1196 }
1197 
1198 ////////////////////////////////////////////////////////////////////////////////
1199 /// construct python tuple of instances from C++ array read at <address>
1200 
1202 {
1203  if ( m_size <= 0 ) // if size unknown, just hand out the first object
1204  return BindCppObjectNoCast( address, fClass );
1205 
1206  return BindCppObjectArray( address, fClass, m_size );
1207 }
1208 
1209 ////////////////////////////////////////////////////////////////////////////////
1210 /// convert <value> to C++ array of instances, write it at <address>
1211 
1212 Bool_t PyROOT::TCppObjectArrayConverter::ToMemory( PyObject* /* value */, void* /* address */ )
1213 {
1214 // TODO: need to have size both for the array and from the input
1215  PyErr_SetString( PyExc_NotImplementedError,
1216  "access to C-arrays of objects not yet implemented!" );
1217  return kFALSE;
1218 }
1219 
1220 //____________________________________________________________________________
1221 // CLING WORKAROUND -- classes for STL iterators are completely undefined in that
1222 // they come in a bazillion different guises, so just do whatever
1224  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
1225 {
1226  if ( ! ObjectProxy_Check( pyobject ) )
1227  return kFALSE;
1228 
1229 // just set the pointer value, no check
1230  ObjectProxy* pyobj = (ObjectProxy*)pyobject;
1231  para.fValue.fVoidp = pyobj->GetObject();
1232  para.fTypeCode = 'V';
1233  return kTRUE;
1234 }
1235 // -- END CLING WORKAROUND
1236 
1237 ////////////////////////////////////////////////////////////////////////////////
1238 /// convert `pyobject` to C++ void*&, set arg for call
1239 
1241  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
1242 {
1243  if ( ObjectProxy_Check( pyobject ) ) {
1244  para.fValue.fVoidp = &((ObjectProxy*)pyobject)->fObject;
1245  para.fTypeCode = 'V';
1246  return kTRUE;
1247  }
1248 
1249  return kFALSE;
1250 }
1251 
1252 ////////////////////////////////////////////////////////////////////////////////
1253 /// convert `pyobject` to C++ void**, set arg for call
1254 
1256  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
1257 {
1258  if ( ObjectProxy_Check( pyobject ) ) {
1259  // this is a ROOT object, take and set its address
1260  para.fValue.fVoidp = &((ObjectProxy*)pyobject)->fObject;
1261  para.fTypeCode = 'p';
1262  return kTRUE;
1263  }
1264 
1265 // buffer objects are allowed under "user knows best"
1266  int buflen = Utility::GetBuffer( pyobject, '*', 1, para.fValue.fVoidp, kFALSE );
1267 
1268 // ok if buffer exists (can't perform any useful size checks)
1269  if ( para.fValue.fVoidp && buflen != 0 ) {
1270  para.fTypeCode = 'p';
1271  return kTRUE;
1272  }
1273 
1274  return kFALSE;
1275 }
1276 
1277 ////////////////////////////////////////////////////////////////////////////////
1278 /// read a void** from address; since this is unknown, long is used (user can cast)
1279 
1281 {
1282  if ( ! address || *(ptrdiff_t*)address == 0 ) {
1283  Py_INCREF( gNullPtrObject );
1284  return gNullPtrObject;
1285  }
1286  return BufFac_t::Instance()->PyBuffer_FromMemory( (Long_t*)*(ptrdiff_t**)address, sizeof(void*) );
1287 }
1288 
1289 ////////////////////////////////////////////////////////////////////////////////
1290 /// by definition: set and declare success
1291 
1292 Bool_t PyROOT::TPyObjectConverter::SetArg(
1293  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
1294 {
1295  para.fValue.fVoidp = pyobject;
1296  para.fTypeCode = 'p';
1297  return kTRUE;
1298 }
1299 
1300 PyObject* PyROOT::TPyObjectConverter::FromMemory( void* address )
1301 {
1302 // construct python object from C++ PyObject* read at <address>
1303  PyObject* pyobject = *((PyObject**)address);
1304 
1305  if ( ! pyobject ) {
1306  Py_INCREF( Py_None );
1307  return Py_None;
1308  }
1309 
1310  Py_INCREF( pyobject );
1311  return pyobject;
1312 }
1313 
1314 Bool_t PyROOT::TPyObjectConverter::ToMemory( PyObject* value, void* address )
1315 {
1316 // no conversion needed, write <value> at <address>
1317  Py_INCREF( value );
1318  *((PyObject**)address) = value;
1319  return kTRUE;
1320 }
1321 
1322 
1323 ////////////////////////////////////////////////////////////////////////////////
1324 /// smart pointer converter
1325 
1327  PyObject* pyobject, TParameter& para, TCallContext* ctxt )
1328 {
1329  char typeCode = fHandlePtr ? 'p' : 'V';
1330 
1331  if ( ! ObjectProxy_Check( pyobject ) ) {
1332  if ( fHandlePtr && GetAddressSpecialCase( pyobject, para.fValue.fVoidp ) ) {
1333  para.fTypeCode = typeCode; // allow special cases such as NULL
1334  return kTRUE;
1335  }
1336 
1337  return kFALSE;
1338  }
1339 
1340  ObjectProxy* pyobj = (ObjectProxy*)pyobject;
1341 
1342 // for the case where we have a 'hidden' smart pointer:
1343  if ( pyobj->fFlags & ObjectProxy::kIsSmartPtr && Cppyy::IsSubtype( pyobj->fSmartPtrType, fClass ) ) {
1344  // depending on memory policy, some objects need releasing when passed into functions
1345  if ( fKeepControl && ! UseStrictOwnership( ctxt ) )
1346  ((ObjectProxy*)pyobject)->Release();
1347 
1348  // calculate offset between formal and actual arguments
1349  para.fValue.fVoidp = pyobj->fSmartPtr;
1350  if ( pyobj->fSmartPtrType != fClass ) {
1352  pyobj->fSmartPtrType, fClass, para.fValue.fVoidp, 1 /* up-cast */ );
1353  }
1354 
1355  // set pointer (may be null) and declare success
1356  para.fTypeCode = typeCode;
1357  return kTRUE;
1358  }
1359 
1360 // for the case where we have an 'exposed' smart pointer:
1361  if ( pyobj->ObjectIsA() && Cppyy::IsSubtype( pyobj->ObjectIsA(), fClass ) ) {
1362  // calculate offset between formal and actual arguments
1363  para.fValue.fVoidp = pyobj->GetObject();
1364  if ( pyobj->ObjectIsA() != fClass ) {
1366  pyobj->ObjectIsA(), fClass, para.fValue.fVoidp, 1 /* up-cast */ );
1367  }
1368 
1369  // set pointer (may be null) and declare success
1370  para.fTypeCode = typeCode;
1371  return kTRUE;
1372  }
1373 
1374  return kFALSE;
1375 }
1376 
1378 {
1379  if ( !address || !fClass )
1380  return nullptr;
1381 
1382 // obtain raw pointer
1383  std::vector<TParameter> args;
1385  Cppyy::CallR( (Cppyy::TCppMethod_t)fDereferencer, address, &args ), fRawPtrType );
1386  if ( pyobj )
1387  pyobj->SetSmartPtr( (void*)address, fClass );
1388 
1389  return (PyObject*)pyobj;
1390 }
1391 
1392 
1393 ////////////////////////////////////////////////////////////////////////////////
1394 /// raise a NotImplemented exception to take a method out of overload resolution
1395 
1397 {
1398  PyErr_SetString( PyExc_NotImplementedError, "this method can not (yet) be called" );
1399  return kFALSE;
1400 }
1401 
1402 
1403 //- factories -----------------------------------------------------------------
1404 PyROOT::TConverter* PyROOT::CreateConverter( const std::string& fullType, Long_t size )
1405 {
1406 // The matching of the fulltype to a converter factory goes through up to five levels:
1407 // 1) full, exact match
1408 // 2) match of decorated, unqualified type
1409 // 3) accept const ref as by value
1410 // 4) accept ref as pointer
1411 // 5) generalized cases (covers basically all ROOT classes)
1412 //
1413 // If all fails, void is used, which will generate a run-time warning when used.
1414 
1415 // an exactly matching converter is best
1416  ConvFactories_t::iterator h = gConvFactories.find( fullType );
1417  if ( h != gConvFactories.end() )
1418  return (h->second)( size );
1419 
1420 // resolve typedefs etc.
1421  std::string resolvedType = Cppyy::ResolveName( fullType );
1422 
1423 // a full, qualified matching converter is preferred
1424  h = gConvFactories.find( resolvedType );
1425  if ( h != gConvFactories.end() )
1426  return (h->second)( size );
1427 
1428 //-- nothing? ok, collect information about the type and possible qualifiers/decorators
1429  const std::string& cpd = Utility::Compound( resolvedType );
1430  std::string realType = TClassEdit::ShortType( resolvedType.c_str(), 1 );
1431 
1432 // accept unqualified type (as python does not know about qualifiers)
1433  h = gConvFactories.find( realType + cpd );
1434  if ( h != gConvFactories.end() )
1435  return (h->second)( size );
1436 
1437 // CLING WORKAROUND -- if the type is a fixed-size array, it will have a funky
1438 // resolved type like MyClass(&)[N], which TClass::GetClass() fails on. So, strip
1439 // it down:
1440  if ( cpd == "[]" )
1441  realType = TClassEdit::CleanType( realType.substr( 0, realType.rfind("(") ).c_str(), 1 );
1442 // -- CLING WORKAROUND
1443 
1444 //-- still nothing? try pointer instead of array (for builtins)
1445  if ( cpd == "[]" ) {
1446  h = gConvFactories.find( realType + "*" );
1447  if ( h != gConvFactories.end() )
1448  return (h->second)( size );
1449  }
1450 
1451 //-- still nothing? use a generalized converter
1452  Bool_t isConst = resolvedType.substr(0, 5) == "const";
1453  Bool_t control = cpd == "&" || isConst;
1454 
1455 // converters for known/ROOT classes and default (void*)
1456  TConverter* result = 0;
1457  if ( Cppyy::TCppScope_t klass = Cppyy::GetScope( realType ) ) {
1458  if ( Cppyy::IsSmartPtr( realType ) ) {
1459  const std::vector< Cppyy::TCppMethod_t > methods = Cppyy::GetMethodsFromName( klass, "operator->" );
1460  if ( ! methods.empty() ) {
1461  Cppyy::TCppType_t rawPtrType = Cppyy::GetScope(
1462  TClassEdit::ShortType( Cppyy::GetMethodResultType( methods[0] ).c_str(), 1 ) );
1463  if ( rawPtrType ) {
1464  if ( cpd == "" ) {
1465  result = new TSmartPtrCppObjectConverter( klass, rawPtrType, methods[0], control );
1466  } else if ( cpd == "&" ) {
1467  result = new TSmartPtrCppObjectConverter( klass, rawPtrType, methods[0] );
1468  } else if ( cpd == "*" && size <= 0 ) {
1469  result = new TSmartPtrCppObjectConverter( klass, rawPtrType, methods[0], control, kTRUE );
1470  } /* else if ( cpd == "**" || cpd == "*&" || cpd == "&*" ) {
1471  } else if ( cpd == "[]" || size > 0 ) {
1472  } else {
1473  } */
1474  }
1475  }
1476  }
1477 
1478  if ( ! result ) {
1479  // CLING WORKAROUND -- special case for STL iterators
1480  if ( realType.find( "__gnu_cxx::__normal_iterator", 0 ) /* vector */ == 0 )
1481  result = new TSTLIteratorConverter();
1482  else
1483  // -- CLING WORKAROUND
1484  if ( cpd == "**" || cpd == "&*" )
1485  result = new TCppObjectPtrConverter<false>( klass, control);
1486  else if ( cpd == "*&" )
1487  result = new TCppObjectPtrConverter<true>( klass, control);
1488  else if ( cpd == "*" && size <= 0 )
1489  result = new TCppObjectConverter( klass, control );
1490  else if ( cpd == "&" )
1491  result = new TRefCppObjectConverter( klass );
1492  else if ( cpd == "[]" || size > 0 )
1493  result = new TCppObjectArrayConverter( klass, size, kFALSE );
1494  else if ( cpd == "" ) // by value
1495  result = new TValueCppObjectConverter( klass, kTRUE );
1496  }
1497  } else if ( Cppyy::IsEnum( realType ) ) {
1498  // special case (Cling): represent enums as unsigned integers
1499  if ( cpd == "&" )
1500  h = isConst ? gConvFactories.find( "const long&" ) : gConvFactories.find( "long&" );
1501  else
1502  h = gConvFactories.find( "UInt_t" );
1503  } else if ( realType.find( "(*)" ) != std::string::npos ||
1504  ( realType.find( "::*)" ) != std::string::npos ) ) {
1505  // this is a function function pointer
1506  // TODO: find better way of finding the type
1507  // TODO: a converter that generates wrappers as appropriate
1508  h = gConvFactories.find( "void*" );
1509  }
1510 
1511  if ( ! result && cpd == "&&" ) // moves
1512  result = new TNotImplementedConverter();
1513 
1514  if ( ! result && h != gConvFactories.end() )
1515  // converter factory available, use it to create converter
1516  result = (h->second)( size );
1517  else if ( ! result ) {
1518  if ( cpd != "" ) {
1519  std::stringstream s;
1520  s << "creating converter for unknown type \"" << fullType << "\"" << std::ends;
1521  PyErr_Warn( PyExc_RuntimeWarning, (char*)s.str().c_str() );
1522  result = new TVoidArrayConverter(); // "user knows best"
1523  } else
1524  result = new TVoidConverter(); // fails on use
1525  }
1526 
1527  return result;
1528 }
1529 
1530 ////////////////////////////////////////////////////////////////////////////////
1531 
1532 #define PYROOT_BASIC_CONVERTER_FACTORY( name ) \
1533 TConverter* Create##name##Converter( Long_t ) \
1534 { \
1535  return new T##name##Converter(); \
1536 }
1537 
1538 #define PYROOT_ARRAY_CONVERTER_FACTORY( name ) \
1539 TConverter* Create##name##Converter( Long_t size ) \
1540 { \
1541  return new T##name##Converter( size ); \
1542 }
1543 
1544 ////////////////////////////////////////////////////////////////////////////////
1545 
1546 namespace {
1547  using namespace PyROOT;
1548 
1549 // use macro rather than template for portability ...
1551  PYROOT_BASIC_CONVERTER_FACTORY( ConstBoolRef )
1553  PYROOT_BASIC_CONVERTER_FACTORY( ConstCharRef )
1555  PYROOT_BASIC_CONVERTER_FACTORY( ConstUCharRef )
1557  PYROOT_BASIC_CONVERTER_FACTORY( ConstShortRef )
1559  PYROOT_BASIC_CONVERTER_FACTORY( ConstUShortRef )
1562  PYROOT_BASIC_CONVERTER_FACTORY( ConstIntRef )
1564  PYROOT_BASIC_CONVERTER_FACTORY( ConstUIntRef )
1567  PYROOT_BASIC_CONVERTER_FACTORY( ConstLongRef )
1569  PYROOT_BASIC_CONVERTER_FACTORY( ConstULongRef )
1571  PYROOT_BASIC_CONVERTER_FACTORY( ConstFloatRef )
1573  PYROOT_BASIC_CONVERTER_FACTORY( DoubleRef )
1574  PYROOT_BASIC_CONVERTER_FACTORY( ConstDoubleRef )
1575  PYROOT_BASIC_CONVERTER_FACTORY( LongDouble )
1576  PYROOT_BASIC_CONVERTER_FACTORY( ConstLongDoubleRef )
1578  PYROOT_BASIC_CONVERTER_FACTORY( LongLong )
1579  PYROOT_BASIC_CONVERTER_FACTORY( ConstLongLongRef )
1580  PYROOT_BASIC_CONVERTER_FACTORY( ULongLong )
1581  PYROOT_BASIC_CONVERTER_FACTORY( ConstULongLongRef )
1583  PYROOT_ARRAY_CONVERTER_FACTORY( NonConstCString )
1584  PYROOT_ARRAY_CONVERTER_FACTORY( NonConstUCString )
1585  PYROOT_ARRAY_CONVERTER_FACTORY( BoolArray )
1586  PYROOT_BASIC_CONVERTER_FACTORY( BoolArrayRef )
1587  PYROOT_ARRAY_CONVERTER_FACTORY( ShortArray )
1588  PYROOT_ARRAY_CONVERTER_FACTORY( ShortArrayRef )
1589  PYROOT_ARRAY_CONVERTER_FACTORY( UShortArray )
1590  PYROOT_ARRAY_CONVERTER_FACTORY( UShortArrayRef )
1591  PYROOT_ARRAY_CONVERTER_FACTORY( IntArray )
1592  PYROOT_ARRAY_CONVERTER_FACTORY( UIntArray )
1593  PYROOT_ARRAY_CONVERTER_FACTORY( UIntArrayRef )
1594  PYROOT_ARRAY_CONVERTER_FACTORY( LongArray )
1595  PYROOT_ARRAY_CONVERTER_FACTORY( ULongArray )
1596  PYROOT_ARRAY_CONVERTER_FACTORY( ULongArrayRef )
1597  PYROOT_ARRAY_CONVERTER_FACTORY( FloatArray )
1598  PYROOT_ARRAY_CONVERTER_FACTORY( FloatArrayRef )
1599  PYROOT_ARRAY_CONVERTER_FACTORY( DoubleArray )
1600  PYROOT_BASIC_CONVERTER_FACTORY( VoidArray )
1601  PYROOT_BASIC_CONVERTER_FACTORY( LongLongArray )
1603  PYROOT_BASIC_CONVERTER_FACTORY( STLString )
1604  PYROOT_BASIC_CONVERTER_FACTORY( STLStringView )
1605  PYROOT_BASIC_CONVERTER_FACTORY( VoidPtrRef )
1606  PYROOT_BASIC_CONVERTER_FACTORY( VoidPtrPtr )
1608 
1609 // converter factories for ROOT types
1610  typedef std::pair< const char*, ConverterFactory_t > NFp_t;
1611 
1612  // clang-format off
1613  NFp_t factories_[] = {
1614  // factories for built-ins
1615  NFp_t( "bool", &CreateBoolConverter ),
1616  NFp_t( "const bool&", &CreateConstBoolRefConverter ),
1617  NFp_t( "char", &CreateCharConverter ),
1618  NFp_t( "const char&", &CreateConstCharRefConverter ),
1619  NFp_t( "signed char", &CreateCharConverter ),
1620  NFp_t( "const signed char&", &CreateConstCharRefConverter ),
1621  NFp_t( "unsigned char", &CreateUCharConverter ),
1622  NFp_t( "const unsigned char&", &CreateConstUCharRefConverter ),
1623  NFp_t( "short", &CreateShortConverter ),
1624  NFp_t( "const short&", &CreateConstShortRefConverter ),
1625  NFp_t( "unsigned short", &CreateUShortConverter ),
1626  NFp_t( "const unsigned short&", &CreateConstUShortRefConverter ),
1627  NFp_t( "int", &CreateIntConverter ),
1628  NFp_t( "int&", &CreateIntRefConverter ),
1629  NFp_t( "const int&", &CreateConstIntRefConverter ),
1630  NFp_t( "unsigned int", &CreateUIntConverter ),
1631  NFp_t( "const unsigned int&", &CreateConstUIntRefConverter ),
1632  NFp_t( "UInt_t", /* enum */ &CreateIntConverter /* yes: Int */ ),
1633  NFp_t( "long", &CreateLongConverter ),
1634  NFp_t( "long&", &CreateLongRefConverter ),
1635  NFp_t( "const long&", &CreateConstLongRefConverter ),
1636  NFp_t( "unsigned long", &CreateULongConverter ),
1637  NFp_t( "const unsigned long&", &CreateConstULongRefConverter ),
1638  NFp_t( "long long", &CreateLongLongConverter ),
1639  NFp_t( "const long long&", &CreateConstLongLongRefConverter ),
1640  NFp_t( "Long64_t", &CreateLongLongConverter ),
1641  NFp_t( "const Long64_t&", &CreateConstLongLongRefConverter ),
1642  NFp_t( "unsigned long long", &CreateULongLongConverter ),
1643  NFp_t( "const unsigned long long&", &CreateConstULongLongRefConverter ),
1644  NFp_t( "ULong64_t", &CreateULongLongConverter ),
1645  NFp_t( "const ULong64_t&", &CreateConstULongLongRefConverter ),
1646 
1647  NFp_t( "float", &CreateFloatConverter ),
1648  NFp_t( "const float&", &CreateConstFloatRefConverter ),
1649  NFp_t( "double", &CreateDoubleConverter ),
1650  NFp_t( "double&", &CreateDoubleRefConverter ),
1651  NFp_t( "const double&", &CreateConstDoubleRefConverter ),
1652  NFp_t( "long double", &CreateLongDoubleConverter ),
1653  NFp_t( "const long double&", &CreateConstLongDoubleRefConverter ),
1654  NFp_t( "void", &CreateVoidConverter ),
1655 
1656  // pointer/array factories
1657  NFp_t( "bool*", &CreateBoolArrayConverter ),
1658  NFp_t( "bool&", &CreateBoolArrayRefConverter ),
1659  NFp_t( "const unsigned char*", &CreateCStringConverter ),
1660  NFp_t( "unsigned char*", &CreateNonConstUCStringConverter ),
1661  NFp_t( "short*", &CreateShortArrayConverter ),
1662  NFp_t( "short&", &CreateShortArrayRefConverter ),
1663  NFp_t( "unsigned short*", &CreateUShortArrayConverter ),
1664  NFp_t( "unsigned short&", &CreateUShortArrayRefConverter ),
1665  NFp_t( "int*", &CreateIntArrayConverter ),
1666  NFp_t( "unsigned int*", &CreateUIntArrayConverter ),
1667  NFp_t( "unsigned int&", &CreateUIntArrayRefConverter ),
1668  NFp_t( "long*", &CreateLongArrayConverter ),
1669  NFp_t( "unsigned long*", &CreateULongArrayConverter ),
1670  NFp_t( "unsigned long&", &CreateULongArrayRefConverter ),
1671  NFp_t( "float*", &CreateFloatArrayConverter ),
1672  NFp_t( "float&", &CreateFloatArrayRefConverter ),
1673  NFp_t( "double*", &CreateDoubleArrayConverter ),
1674  NFp_t( "long long*", &CreateLongLongArrayConverter ),
1675  NFp_t( "Long64_t*", &CreateLongLongArrayConverter ),
1676  NFp_t( "unsigned long long*", &CreateLongLongArrayConverter ), // TODO: ULongLong
1677  NFp_t( "ULong64_t*", &CreateLongLongArrayConverter ), // TODO: ULongLong
1678  NFp_t( "void*", &CreateVoidArrayConverter ),
1679 
1680  // factories for special cases
1681  NFp_t( "const char*", &CreateCStringConverter ),
1682  NFp_t( "char*", &CreateNonConstCStringConverter ),
1683  NFp_t( "TString", &CreateTStringConverter ),
1684  NFp_t( "const TString&", &CreateTStringConverter ),
1685  NFp_t( "std::string", &CreateSTLStringConverter ),
1686  NFp_t( "string", &CreateSTLStringConverter ),
1687  NFp_t( "const std::string&", &CreateSTLStringConverter ),
1688  NFp_t( "const string&", &CreateSTLStringConverter ),
1689  NFp_t( "std::string_view", &CreateSTLStringViewConverter ),
1690  NFp_t( "string_view", &CreateSTLStringViewConverter ),
1691  NFp_t( "experimental::basic_string_view<char,char_traits<char> >",&CreateSTLStringViewConverter),
1692  NFp_t( "basic_string_view<char,char_traits<char> >",&CreateSTLStringViewConverter),
1693  NFp_t( "void*&", &CreateVoidPtrRefConverter ),
1694  NFp_t( "void**", &CreateVoidPtrPtrConverter ),
1695  NFp_t( "PyObject*", &CreatePyObjectConverter ),
1696  NFp_t( "_object*", &CreatePyObjectConverter ),
1697  NFp_t( "FILE*", &CreateVoidArrayConverter ),
1698  NFp_t( "Float16_t", &CreateFloatConverter ),
1699  NFp_t( "const Float16_t&", &CreateConstFloatRefConverter ),
1700  NFp_t( "Double32_t", &CreateDoubleConverter ),
1701  NFp_t( "Double32_t&", &CreateDoubleRefConverter ),
1702  NFp_t( "const Double32_t&", &CreateConstDoubleRefConverter )
1703  };
1704  // clang-format on
1705 
1706  struct InitConvFactories_t {
1707  public:
1708  InitConvFactories_t()
1709  {
1710  // load all converter factories in the global map 'gConvFactories'
1711  int nf = sizeof( factories_ ) / sizeof( factories_[ 0 ] );
1712  for ( int i = 0; i < nf; ++i ) {
1713  gConvFactories[ factories_[ i ].first ] = factories_[ i ].second;
1714  }
1715  }
1716  } initConvFactories_;
1717 
1718 } // unnamed namespace
TCppScope_t TCppType_t
Definition: Cppyy.h:13
virtual Bool_t ToMemory(PyObject *value, void *address)
could happen if no derived class override
Definition: Converters.cxx:145
R__EXTERN PyObject * gInit
Definition: PyStrings.h:27
#define PyROOT_PyUnicode_FromString
Definition: PyROOT.h:71
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
construct a new string and copy it in new memory
Definition: Converters.cxx:551
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
long long Long64_t
Definition: RtypesCore.h:69
#define PyROOT_PyUnicode_GET_SIZE
Definition: PyROOT.h:68
Cppyy::TCppType_t fSmartPtrType
Definition: ObjectProxy.h:80
float Float_t
Definition: RtypesCore.h:53
const char * Int
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
convert pyobject to C++ instance**, set arg for call
virtual Bool_t ToMemory(PyObject *value, void *address)
just convert pointer if it is a ROOT object
Definition: Converters.cxx:752
virtual PyObject * FromMemory(void *address)
nothing sensible can be done, just return <address> as pylong
Definition: Converters.cxx:740
unsigned short UShort_t
Definition: RtypesCore.h:36
ptrdiff_t GetBaseOffset(TCppType_t derived, TCppType_t base, TCppObject_t address, int direction, bool rerror=false)
Definition: Cppyy.cxx:620
static Long_t PyROOT_PyLong_AsStrictLong(PyObject *pyobject)
strict python integer to C++ integer conversion
Definition: Converters.cxx:121
std::vector< TCppMethod_t > GetMethodsFromName(TCppScope_t scope, const std::string &name)
Definition: Cppyy.cxx:690
#define PyROOT_PyCapsule_CheckExact
Definition: PyROOT.h:83
#define H(x, y, z)
std::string GetFinalName(TCppType_t type)
Definition: Cppyy.cxx:561
std::string CleanType(const char *typeDesc, int mode=0, const char **tail=0)
Cleanup type description, redundant blanks removed and redundant tail ignored return *tail = pointer ...
const char * Long
#define f(i)
Definition: RSha256.hxx:104
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const char * Char
#define PYROOT_BASIC_CONVERTER_FACTORY(name)
const char * UShort
PyObject * BindCppObjectArray(Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, Int_t size)
TODO: this function exists for symmetry; need to figure out if it&#39;s useful.
const char * UInt
virtual Bool_t ToMemory(PyObject *value, void *address)
could happen if no derived class override
Definition: Converters.cxx:589
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
smart pointer converter
Bool_t UseStrictOwnership(TCallContext *ctxt)
Definition: TCallContext.h:85
#define PY_SSIZE_T_FORMAT
Definition: PyROOT.h:159
virtual PyObject * FromMemory(void *address)
Definition: Converters.cxx:572
#define PYROOT_IMPLEMENT_BASIC_CHAR_CONVERTER(name, type, low, high)
Definition: Converters.cxx:235
#define PYROOT_IMPLEMENT_BASIC_CONST_CHAR_REF_CONVERTER(name, type, low, high)
Definition: Converters.cxx:219
std::string ResolveName(const std::string &cppitem_name)
Definition: Cppyy.cxx:166
PyLong_FromUnsignedLongLong
Definition: Executors.cxx:289
union PyROOT::TParameter::Value fValue
static UShort_t PyROOT_PyLong_AsUShort(PyObject *pyobject)
range-checking python integer to C++ unsigned short int conversion
Definition: Converters.cxx:84
virtual PyObject * FromMemory(void *address)
Definition: Converters.cxx:135
void SetSmartPtr(void *address, Cppyy::TCppType_t ptrType)
Definition: ObjectProxy.h:40
static constexpr double L
ClassInfo_t * GetClassInfo() const
Definition: TClass.h:400
#define PyROOT_PyUnicode_AsStringChecked
Definition: PyROOT.h:67
virtual Bool_t ToMemory(PyObject *value, void *address)
convert to C++ array of instances, write it at <address>
#define PyROOT_PyUnicode_AsString
Definition: PyROOT.h:66
void CallDestructor(TCppType_t type, TCppObject_t self)
Definition: Cppyy.cxx:492
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *=0)
raise a NotImplemented exception to take a method out of overload resolution
const char * UChar
const char * Float
virtual PyObject * FromMemory(void *address)
R__EXTERN PyObject * gNullPtrObject
Definition: Converters.cxx:39
ULong_t PyLongOrInt_AsULong(PyObject *pyobject)
Definition: Utility.cxx:145
#define PYROOT_ARRAY_CONVERTER_FACTORY(name)
TConverter * CreateConverter(const std::string &fullType, Long_t size=-1)
virtual Bool_t ToMemory(PyObject *value, void *address)
convert to C++ instance*, write it at <address>
ptrdiff_t TCppMethod_t
Definition: Cppyy.h:15
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
convert pyobject to C++ instance**, set arg for call
Bool_t ObjectProxy_Check(T *object)
Definition: ObjectProxy.h:91
virtual Bool_t GetAddressSpecialCase(PyObject *pyobject, void *&address)
(1): "null pointer" or C++11 style nullptr
Definition: Converters.cxx:674
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
attempt base class first (i.e. passing a string), but if that fails, try a buffer ...
Definition: Converters.cxx:660
virtual Bool_t ToMemory(PyObject *value, void *address)
convert to C++ instance, write it at <address>
Definition: Converters.cxx:948
Bool_t TTupleOfInstances_CheckExact(T *object)
#define PyROOT_PyUnicode_FromStringAndSize
Definition: PyROOT.h:75
virtual PyObject * FromMemory(void *address)
assume this is a buffer access if the size is known; otherwise assume string
Definition: Converters.cxx:650
#define PYROOT_IMPLEMENT_ARRAY_CONVERTER(name, type, code)
Definition: Converters.cxx:783
unsigned int UInt_t
Definition: RtypesCore.h:42
const char * ULong
ULong64_t PyLongOrInt_AsULong64(PyObject *pyobject)
Convert <pyobject> to C++ unsigned long long, with bounds checking.
Definition: Utility.cxx:166
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, Bool_t isRef=kFALSE, Bool_t isValue=kFALSE)
only known or knowable objects will be bound (null object is ok)
short Short_t
Definition: RtypesCore.h:35
const char * Double
long double LongDouble_t
Definition: RtypesCore.h:57
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
convert pyobject to C++ void*&, set arg for call
virtual PyObject * FromMemory(void *address)
construct python object from C++ instance* read at <address>
#define h(i)
Definition: RSha256.hxx:106
PyObject * PyBuffer_FromMemory(Bool_t *buf, Py_ssize_t size=-1)
const Bool_t kFALSE
Definition: RtypesCore.h:88
virtual PyObject * FromMemory(void *address)
construct python tuple of instances from C++ array read at <address>
Bool_t TCustomFloat_CheckExact(T *object)
void * CallR(TCppMethod_t method, TCppObject_t self, void *args)
Definition: Cppyy.cxx:468
long Long_t
Definition: RtypesCore.h:50
#define d(i)
Definition: RSha256.hxx:102
Bool_t IsSubtype(TCppType_t derived, TCppType_t base)
Definition: Cppyy.cxx:598
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
Convenience function with a lookup first through the known existing proxies.
static Bool_t PyROOT_PyLong_AsBool(PyObject *pyobject)
range-checking python integer to C++ bool conversion
Definition: Converters.cxx:65
TCppScope_t GetScope(const std::string &scope_name)
Definition: Cppyy.cxx:176
double Double_t
Definition: RtypesCore.h:55
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
attempt base class first (i.e. passing a string), but if that fails, try a buffer ...
Definition: Converters.cxx:636
std::string GetMethodResultType(TCppMethod_t)
Definition: Cppyy.cxx:744
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
just convert pointer if it is a ROOT object
Definition: Converters.cxx:704
virtual PyObject * FromMemory(void *address)
construct python object from C++ instance read at <address>
Definition: Converters.cxx:940
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
basic_string_view< char > string_view
Definition: RStringView.hxx:35
#define PYROOT_IMPLEMENT_BASIC_CONST_REF_CONVERTER(name, type, F1)
Definition: Converters.cxx:206
static constexpr double s
#define PyROOT_PyUnicode_Check
Definition: PyROOT.h:64
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
void Deallocate(TCppType_t type, TCppObject_t instance)
Definition: Cppyy.cxx:260
virtual PyObject * FromMemory(void *address)
read a void** from address; since this is unknown, long is used (user can cast)
static Int_t ExtractChar(PyObject *pyobject, const char *tname, Int_t low, Int_t high)
Definition: Converters.cxx:181
static void * PyROOT_PyCapsule_GetPointer(PyObject *capsule, const char *)
Definition: PyROOT.h:84
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
convert pyobject to C++ instance, set arg for call
Definition: Converters.cxx:985
static Short_t PyROOT_PyLong_AsShort(PyObject *pyobject)
range-checking python integer to C++ short int conversion
Definition: Converters.cxx:102
Bool_t IsSmartPtr(const std::string &)
Definition: Cppyy.cxx:611
const char * Bool
#define R__EXTERN
Definition: DllImport.h:27
char Char_t
Definition: RtypesCore.h:29
#define Py_TYPE(ob)
Definition: PyROOT.h:151
auto * l
Definition: textangle.C:4
void * GetObject() const
Definition: ObjectProxy.h:47
static TPyBufferFactory * Instance()
static Char_t PyROOT_PyUnicode_AsChar(PyObject *pyobject)
python string to C++ char conversion
Definition: Converters.cxx:78
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
std::map< std::string, ConverterFactory_t > ConvFactories_t
Definition: Converters.cxx:37
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.
unsigned char UChar_t
Definition: RtypesCore.h:34
Definition: first.py:1
#define I(x, y, z)
ptrdiff_t TCppScope_t
Definition: Cppyy.h:12
const Bool_t kTRUE
Definition: RtypesCore.h:87
PyObject * BindCppObject(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, Bool_t isRef=kFALSE)
if the object is a null pointer, return a typed one (as needed for overloading)
Bool_t IsEnum(const std::string &type_name)
Definition: Cppyy.cxx:555
Bool_t TCustomInt_CheckExact(T *object)
static ECallFlags sMemoryPolicy
Definition: TCallContext.h:49
char name[80]
Definition: TGX11.cxx:109
ConvFactories_t gConvFactories
Definition: Converters.cxx:38
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
convert pyobject to C++ void**, set arg for call
#define PYROOT_IMPLEMENT_STRING_AS_PRIMITIVE_CONVERTER(name, type, F1, F2)
Definition: Converters.cxx:849
_object PyObject
Definition: TPyArg.h:20
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
convert pyobject to C++ instance&, set arg for call
R__EXTERN PyObject * gEmptyString
Definition: PyStrings.h:23
Cppyy::TCppType_t ObjectIsA() const
Definition: ObjectProxy.h:66
#define PYROOT_IMPLEMENT_BASIC_CONVERTER(name, type, stype, F1, F2, tc)
Definition: Converters.cxx:153
const std::string Compound(const std::string &name)
Break down the compound of a fully qualified type name.
Definition: Utility.cxx:658
const char * Short