Logo ROOT   6.10/09
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++ unsigend 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 converion 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 converion 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 converion 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, 1 );
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 );\
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 )
892 PYROOT_IMPLEMENT_STRING_AS_PRIMITIVE_CONVERTER( STLStringView, std::string_view, data, 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  return kFALSE;
990 
991  ObjectProxy* pyobj = (ObjectProxy*)pyobject;
992  if ( pyobj->ObjectIsA() && Cppyy::IsSubtype( pyobj->ObjectIsA(), fClass ) ) {
993  // calculate offset between formal and actual arguments
994  para.fValue.fVoidp = pyobj->GetObject();
995  if ( ! para.fValue.fVoidp )
996  return kFALSE;
997 
998  if ( pyobj->ObjectIsA() != fClass ) {
1000  pyobj->ObjectIsA(), fClass, para.fValue.fVoidp, 1 /* up-cast */ );
1001  }
1002 
1003  para.fTypeCode = 'V';
1004  return kTRUE;
1005  }
1006 
1007  return kFALSE;
1008 }
1009 
1010 ////////////////////////////////////////////////////////////////////////////////
1011 /// convert <pyobject> to C++ instance&, set arg for call
1012 
1014  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
1015 {
1016  if ( ! ObjectProxy_Check( pyobject ) )
1017  return kFALSE;
1018 
1019  ObjectProxy* pyobj = (ObjectProxy*)pyobject;
1020  if ( pyobj->ObjectIsA() && Cppyy::IsSubtype( pyobj->ObjectIsA(), fClass ) ) {
1021  // calculate offset between formal and actual arguments
1022  para.fValue.fVoidp = pyobj->GetObject();
1023  if ( pyobj->ObjectIsA() != fClass ) {
1025  pyobj->ObjectIsA(), fClass, para.fValue.fVoidp, 1 /* up-cast */ );
1026  }
1027 
1028  para.fTypeCode = 'V';
1029  return kTRUE;
1030  } else if ( ! TClass::GetClass( Cppyy::GetFinalName( fClass ).c_str() )->GetClassInfo() ) {
1031  // assume "user knows best" to allow anonymous reference passing
1032  para.fValue.fVoidp = pyobj->GetObject();
1033  para.fTypeCode = 'V';
1034  return kTRUE;
1035  }
1036 
1037  return kFALSE;
1038 }
1039 
1040 ////////////////////////////////////////////////////////////////////////////////
1041 /// convert <pyobject> to C++ instance**, set arg for call
1042 
1043 template <bool ISREFERENCE>
1045  PyObject* pyobject, TParameter& para, TCallContext* ctxt )
1046 {
1047  if ( ! ObjectProxy_Check( pyobject ) )
1048  return kFALSE; // not a PyROOT object (TODO: handle SWIG etc.)
1049 
1050  if ( Cppyy::IsSubtype( ((ObjectProxy*)pyobject)->ObjectIsA(), fClass ) ) {
1051  // depending on memory policy, some objects need releasing when passed into functions
1052  if ( ! KeepControl() && ! UseStrictOwnership( ctxt ) )
1053  ((ObjectProxy*)pyobject)->Release();
1054 
1055  // set pointer (may be null) and declare success
1056  if( ((ObjectProxy*)pyobject)->fFlags & ObjectProxy::kIsReference)
1057  // If given object is already a reference (aka pointer) then we should not take the address of it
1058  para.fValue.fVoidp = ((ObjectProxy*)pyobject)->fObject;
1059  else
1060  para.fValue.fVoidp = &((ObjectProxy*)pyobject)->fObject;
1061  para.fTypeCode = ISREFERENCE ? 'V' : 'p';
1062  return kTRUE;
1063  }
1064 
1065  return kFALSE;
1066 }
1067 
1068 ////////////////////////////////////////////////////////////////////////////////
1069 /// construct python object from C++ instance* read at <address>
1070 
1071 template <bool ISREFERENCE>
1073 {
1074  return BindCppObject( address, fClass, kTRUE );
1075 }
1076 
1077 ////////////////////////////////////////////////////////////////////////////////
1078 /// convert <value> to C++ instance*, write it at <address>
1079 
1080 template <bool ISREFERENCE>
1082 {
1083  if ( ! ObjectProxy_Check( value ) )
1084  return kFALSE; // not a PyROOT object (TODO: handle SWIG etc.)
1085 
1086  if ( Cppyy::IsSubtype( ((ObjectProxy*)value)->ObjectIsA(), fClass ) ) {
1087  // depending on memory policy, some objects need releasing when passed into functions
1088  if ( ! KeepControl() && TCallContext::sMemoryPolicy != TCallContext::kUseStrict )
1089  ((ObjectProxy*)value)->Release();
1090 
1091  // set pointer (may be null) and declare success
1092  *(void**)address = ((ObjectProxy*)value)->GetObject();
1093  return kTRUE;
1094  }
1095 
1096  return kFALSE;
1097 }
1098 
1099 
1100 namespace PyROOT {
1101 ////////////////////////////////////////////////////////////////////////////////
1102 /// Instantiate the templates
1103 
1104 template class TCppObjectPtrConverter<true>;
1105 template class TCppObjectPtrConverter<false>;
1106 }
1107 
1108 ////////////////////////////////////////////////////////////////////////////////
1109 /// convert <pyobject> to C++ instance**, set arg for call
1110 
1112  PyObject* pyobject, TParameter& para, TCallContext* /* txt */ )
1113 {
1114  if ( ! TTupleOfInstances_CheckExact( pyobject ) )
1115  return kFALSE; // no guarantee that the tuple is okay
1116 
1117 // treat the first instance of the tuple as the start of the array, and pass it
1118 // by pointer (TODO: store and check sizes)
1119  if ( PyTuple_Size( pyobject ) < 1 )
1120  return kFALSE;
1121 
1122  PyObject* first = PyTuple_GetItem( pyobject, 0 );
1123  if ( ! ObjectProxy_Check( first ) )
1124  return kFALSE; // should not happen
1125 
1126  if ( Cppyy::IsSubtype( ((ObjectProxy*)first)->ObjectIsA(), fClass ) ) {
1127  // no memory policies supported; set pointer (may be null) and declare success
1128  para.fValue.fVoidp = ((ObjectProxy*)first)->fObject;
1129  para.fTypeCode = 'p';
1130  return kTRUE;
1131  }
1132 
1133  return kFALSE;
1134 }
1135 
1136 ////////////////////////////////////////////////////////////////////////////////
1137 /// construct python tuple of instances from C++ array read at <address>
1138 
1140 {
1141  if ( m_size <= 0 ) // if size unknown, just hand out the first object
1142  return BindCppObjectNoCast( address, fClass );
1143 
1144  return BindCppObjectArray( address, fClass, m_size );
1145 }
1146 
1147 ////////////////////////////////////////////////////////////////////////////////
1148 /// convert <value> to C++ array of instances, write it at <address>
1149 
1150 Bool_t PyROOT::TCppObjectArrayConverter::ToMemory( PyObject* /* value */, void* /* address */ )
1151 {
1152 // TODO: need to have size both for the array and from the input
1153  PyErr_SetString( PyExc_NotImplementedError,
1154  "access to C-arrays of objects not yet implemented!" );
1155  return kFALSE;
1156 }
1157 
1158 //____________________________________________________________________________
1159 // CLING WORKAROUND -- classes for STL iterators are completely undefined in that
1160 // they come in a bazillion different guises, so just do whatever
1162  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
1163 {
1164  if ( ! ObjectProxy_Check( pyobject ) )
1165  return kFALSE;
1166 
1167 // just set the pointer value, no check
1168  ObjectProxy* pyobj = (ObjectProxy*)pyobject;
1169  para.fValue.fVoidp = pyobj->GetObject();
1170  para.fTypeCode = 'V';
1171  return kTRUE;
1172 }
1173 // -- END CLING WORKAROUND
1174 
1175 ////////////////////////////////////////////////////////////////////////////////
1176 /// convert <pyobject> to C++ void*&, set arg for call
1177 
1179  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
1180 {
1181  if ( ObjectProxy_Check( pyobject ) ) {
1182  para.fValue.fVoidp = &((ObjectProxy*)pyobject)->fObject;
1183  para.fTypeCode = 'V';
1184  return kTRUE;
1185  }
1186 
1187  return kFALSE;
1188 }
1189 
1190 ////////////////////////////////////////////////////////////////////////////////
1191 /// convert <pyobject> to C++ void**, set arg for call
1192 
1194  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
1195 {
1196  if ( ObjectProxy_Check( pyobject ) ) {
1197  // this is a ROOT object, take and set its address
1198  para.fValue.fVoidp = &((ObjectProxy*)pyobject)->fObject;
1199  para.fTypeCode = 'p';
1200  return kTRUE;
1201  }
1202 
1203 // buffer objects are allowed under "user knows best"
1204  int buflen = Utility::GetBuffer( pyobject, '*', 1, para.fValue.fVoidp, kFALSE );
1205 
1206 // ok if buffer exists (can't perform any useful size checks)
1207  if ( para.fValue.fVoidp && buflen != 0 ) {
1208  para.fTypeCode = 'p';
1209  return kTRUE;
1210  }
1211 
1212  return kFALSE;
1213 }
1214 
1215 ////////////////////////////////////////////////////////////////////////////////
1216 /// read a void** from address; since this is unknown, long is used (user can cast)
1217 
1219 {
1220  if ( ! address || *(ptrdiff_t*)address == 0 ) {
1221  Py_INCREF( gNullPtrObject );
1222  return gNullPtrObject;
1223  }
1224  return BufFac_t::Instance()->PyBuffer_FromMemory( (Long_t*)*(ptrdiff_t**)address, 1 );
1225 }
1226 
1227 ////////////////////////////////////////////////////////////////////////////////
1228 /// by definition: set and declare success
1229 
1230 Bool_t PyROOT::TPyObjectConverter::SetArg(
1231  PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ )
1232 {
1233  para.fValue.fVoidp = pyobject;
1234  para.fTypeCode = 'p';
1235  return kTRUE;
1236 }
1237 
1238 PyObject* PyROOT::TPyObjectConverter::FromMemory( void* address )
1239 {
1240 // construct python object from C++ PyObject* read at <address>
1241  PyObject* pyobject = *((PyObject**)address);
1242 
1243  if ( ! pyobject ) {
1244  Py_INCREF( Py_None );
1245  return Py_None;
1246  }
1247 
1248  Py_INCREF( pyobject );
1249  return pyobject;
1250 }
1251 
1252 Bool_t PyROOT::TPyObjectConverter::ToMemory( PyObject* value, void* address )
1253 {
1254 // no conversion needed, write <value> at <address>
1255  Py_INCREF( value );
1256  *((PyObject**)address) = value;
1257  return kTRUE;
1258 }
1259 
1260 
1261 ////////////////////////////////////////////////////////////////////////////////
1262 /// smart pointer converter
1263 
1265  PyObject* pyobject, TParameter& para, TCallContext* ctxt )
1266 {
1267  char typeCode = fHandlePtr ? 'p' : 'V';
1268 
1269  if ( ! ObjectProxy_Check( pyobject ) ) {
1270  if ( fHandlePtr && GetAddressSpecialCase( pyobject, para.fValue.fVoidp ) ) {
1271  para.fTypeCode = typeCode; // allow special cases such as NULL
1272  return kTRUE;
1273  }
1274 
1275  return kFALSE;
1276  }
1277 
1278  ObjectProxy* pyobj = (ObjectProxy*)pyobject;
1279 
1280 // for the case where we have a 'hidden' smart pointer:
1281  if ( pyobj->fFlags & ObjectProxy::kIsSmartPtr && Cppyy::IsSubtype( pyobj->fSmartPtrType, fClass ) ) {
1282  // depending on memory policy, some objects need releasing when passed into functions
1283  if ( fKeepControl && ! UseStrictOwnership( ctxt ) )
1284  ((ObjectProxy*)pyobject)->Release();
1285 
1286  // calculate offset between formal and actual arguments
1287  para.fValue.fVoidp = pyobj->fSmartPtr;
1288  if ( pyobj->fSmartPtrType != fClass ) {
1290  pyobj->fSmartPtrType, fClass, para.fValue.fVoidp, 1 /* up-cast */ );
1291  }
1292 
1293  // set pointer (may be null) and declare success
1294  para.fTypeCode = typeCode;
1295  return kTRUE;
1296  }
1297 
1298 // for the case where we have an 'exposed' smart pointer:
1299  if ( pyobj->ObjectIsA() && Cppyy::IsSubtype( pyobj->ObjectIsA(), fClass ) ) {
1300  // calculate offset between formal and actual arguments
1301  para.fValue.fVoidp = pyobj->GetObject();
1302  if ( pyobj->ObjectIsA() != fClass ) {
1304  pyobj->ObjectIsA(), fClass, para.fValue.fVoidp, 1 /* up-cast */ );
1305  }
1306 
1307  // set pointer (may be null) and declare success
1308  para.fTypeCode = typeCode;
1309  return kTRUE;
1310  }
1311 
1312  return kFALSE;
1313 }
1314 
1316 {
1317  if ( !address || !fClass )
1318  return nullptr;
1319 
1320 // obtain raw pointer
1321  std::vector<TParameter> args;
1323  Cppyy::CallR( (Cppyy::TCppMethod_t)fDereferencer, address, &args ), fRawPtrType );
1324  if ( pyobj )
1325  pyobj->SetSmartPtr( (void*)address, fClass );
1326 
1327  return (PyObject*)pyobj;
1328 }
1329 
1330 
1331 ////////////////////////////////////////////////////////////////////////////////
1332 /// raise a NotImplemented exception to take a method out of overload resolution
1333 
1335 {
1336  PyErr_SetString( PyExc_NotImplementedError, "this method can not (yet) be called" );
1337  return kFALSE;
1338 }
1339 
1340 
1341 //- factories -----------------------------------------------------------------
1342 PyROOT::TConverter* PyROOT::CreateConverter( const std::string& fullType, Long_t size )
1343 {
1344 // The matching of the fulltype to a converter factory goes through up to five levels:
1345 // 1) full, exact match
1346 // 2) match of decorated, unqualified type
1347 // 3) accept const ref as by value
1348 // 4) accept ref as pointer
1349 // 5) generalized cases (covers basically all ROOT classes)
1350 //
1351 // If all fails, void is used, which will generate a run-time warning when used.
1352 
1353 // an exactly matching converter is best
1354  ConvFactories_t::iterator h = gConvFactories.find( fullType );
1355  if ( h != gConvFactories.end() )
1356  return (h->second)( size );
1357 
1358 // resolve typedefs etc.
1359  std::string resolvedType = Cppyy::ResolveName( fullType );
1360 
1361 // a full, qualified matching converter is preferred
1362  h = gConvFactories.find( resolvedType );
1363  if ( h != gConvFactories.end() )
1364  return (h->second)( size );
1365 
1366 //-- nothing? ok, collect information about the type and possible qualifiers/decorators
1367  const std::string& cpd = Utility::Compound( resolvedType );
1368  std::string realType = TClassEdit::ShortType( resolvedType.c_str(), 1 );
1369 
1370 // accept unqualified type (as python does not know about qualifiers)
1371  h = gConvFactories.find( realType + cpd );
1372  if ( h != gConvFactories.end() )
1373  return (h->second)( size );
1374 
1375 // CLING WORKAROUND -- if the type is a fixed-size array, it will have a funky
1376 // resolved type like MyClass(&)[N], which TClass::GetClass() fails on. So, strip
1377 // it down:
1378  if ( cpd == "[]" )
1379  realType = TClassEdit::CleanType( realType.substr( 0, realType.rfind("(") ).c_str(), 1 );
1380 // -- CLING WORKAROUND
1381 
1382 //-- still nothing? try pointer instead of array (for builtins)
1383  if ( cpd == "[]" ) {
1384  h = gConvFactories.find( realType + "*" );
1385  if ( h != gConvFactories.end() )
1386  return (h->second)( size );
1387  }
1388 
1389 //-- still nothing? use a generalized converter
1390  Bool_t isConst = resolvedType.substr(0, 5) == "const";
1391  Bool_t control = cpd == "&" || isConst;
1392 
1393 // converters for known/ROOT classes and default (void*)
1394  TConverter* result = 0;
1395  if ( Cppyy::TCppScope_t klass = Cppyy::GetScope( realType ) ) {
1396  if ( Cppyy::IsSmartPtr( realType ) ) {
1397  const std::vector< Cppyy::TCppMethod_t > methods = Cppyy::GetMethodsFromName( klass, "operator->" );
1398  if ( ! methods.empty() ) {
1399  Cppyy::TCppType_t rawPtrType = Cppyy::GetScope(
1400  TClassEdit::ShortType( Cppyy::GetMethodResultType( methods[0] ).c_str(), 1 ) );
1401  if ( rawPtrType ) {
1402  if ( cpd == "" ) {
1403  result = new TSmartPtrCppObjectConverter( klass, rawPtrType, methods[0], control );
1404  } else if ( cpd == "&" ) {
1405  result = new TSmartPtrCppObjectConverter( klass, rawPtrType, methods[0] );
1406  } else if ( cpd == "*" && size <= 0 ) {
1407  result = new TSmartPtrCppObjectConverter( klass, rawPtrType, methods[0], control, kTRUE );
1408  } /* else if ( cpd == "**" || cpd == "*&" || cpd == "&*" ) {
1409  } else if ( cpd == "[]" || size > 0 ) {
1410  } else {
1411  } */
1412  }
1413  }
1414  }
1415 
1416  if ( ! result ) {
1417  // CLING WORKAROUND -- special case for STL iterators
1418  if ( realType.find( "__gnu_cxx::__normal_iterator", 0 ) /* vector */ == 0 )
1419  result = new TSTLIteratorConverter();
1420  else
1421  // -- CLING WORKAROUND
1422  if ( cpd == "**" || cpd == "&*" )
1423  result = new TCppObjectPtrConverter<false>( klass, control);
1424  else if ( cpd == "*&" )
1425  result = new TCppObjectPtrConverter<true>( klass, control);
1426  else if ( cpd == "*" && size <= 0 )
1427  result = new TCppObjectConverter( klass, control );
1428  else if ( cpd == "&" )
1429  result = new TRefCppObjectConverter( klass );
1430  else if ( cpd == "[]" || size > 0 )
1431  result = new TCppObjectArrayConverter( klass, size, kFALSE );
1432  else if ( cpd == "" ) // by value
1433  result = new TValueCppObjectConverter( klass, kTRUE );
1434  }
1435  } else if ( Cppyy::IsEnum( realType ) ) {
1436  // special case (Cling): represent enums as unsigned integers
1437  if ( cpd == "&" )
1438  h = isConst ? gConvFactories.find( "const long&" ) : gConvFactories.find( "long&" );
1439  else
1440  h = gConvFactories.find( "UInt_t" );
1441  } else if ( realType.find( "(*)" ) != std::string::npos ||
1442  ( realType.find( "::*)" ) != std::string::npos ) ) {
1443  // this is a function function pointer
1444  // TODO: find better way of finding the type
1445  // TODO: a converter that generates wrappers as appropriate
1446  h = gConvFactories.find( "void*" );
1447  }
1448 
1449  if ( ! result && cpd == "&&" ) // moves
1450  result = new TNotImplementedConverter();
1451 
1452  if ( ! result && h != gConvFactories.end() )
1453  // converter factory available, use it to create converter
1454  result = (h->second)( size );
1455  else if ( ! result ) {
1456  if ( cpd != "" ) {
1457  std::stringstream s;
1458  s << "creating converter for unknown type \"" << fullType << "\"" << std::ends;
1459  PyErr_Warn( PyExc_RuntimeWarning, (char*)s.str().c_str() );
1460  result = new TVoidArrayConverter(); // "user knows best"
1461  } else
1462  result = new TVoidConverter(); // fails on use
1463  }
1464 
1465  return result;
1466 }
1467 
1468 ////////////////////////////////////////////////////////////////////////////////
1469 
1470 #define PYROOT_BASIC_CONVERTER_FACTORY( name ) \
1471 TConverter* Create##name##Converter( Long_t ) \
1472 { \
1473  return new T##name##Converter(); \
1474 }
1475 
1476 #define PYROOT_ARRAY_CONVERTER_FACTORY( name ) \
1477 TConverter* Create##name##Converter( Long_t size ) \
1478 { \
1479  return new T##name##Converter( size ); \
1480 }
1481 
1482 ////////////////////////////////////////////////////////////////////////////////
1483 
1484 namespace {
1485  using namespace PyROOT;
1486 
1487 // use macro rather than template for portability ...
1489  PYROOT_BASIC_CONVERTER_FACTORY( ConstBoolRef )
1491  PYROOT_BASIC_CONVERTER_FACTORY( ConstCharRef )
1493  PYROOT_BASIC_CONVERTER_FACTORY( ConstUCharRef )
1495  PYROOT_BASIC_CONVERTER_FACTORY( ConstShortRef )
1497  PYROOT_BASIC_CONVERTER_FACTORY( ConstUShortRef )
1500  PYROOT_BASIC_CONVERTER_FACTORY( ConstIntRef )
1502  PYROOT_BASIC_CONVERTER_FACTORY( ConstUIntRef )
1505  PYROOT_BASIC_CONVERTER_FACTORY( ConstLongRef )
1507  PYROOT_BASIC_CONVERTER_FACTORY( ConstULongRef )
1509  PYROOT_BASIC_CONVERTER_FACTORY( ConstFloatRef )
1511  PYROOT_BASIC_CONVERTER_FACTORY( DoubleRef )
1512  PYROOT_BASIC_CONVERTER_FACTORY( ConstDoubleRef )
1513  PYROOT_BASIC_CONVERTER_FACTORY( LongDouble )
1514  PYROOT_BASIC_CONVERTER_FACTORY( ConstLongDoubleRef )
1516  PYROOT_BASIC_CONVERTER_FACTORY( LongLong )
1517  PYROOT_BASIC_CONVERTER_FACTORY( ConstLongLongRef )
1518  PYROOT_BASIC_CONVERTER_FACTORY( ULongLong )
1519  PYROOT_BASIC_CONVERTER_FACTORY( ConstULongLongRef )
1521  PYROOT_ARRAY_CONVERTER_FACTORY( NonConstCString )
1522  PYROOT_ARRAY_CONVERTER_FACTORY( NonConstUCString )
1523  PYROOT_ARRAY_CONVERTER_FACTORY( BoolArray )
1524  PYROOT_BASIC_CONVERTER_FACTORY( BoolArrayRef )
1525  PYROOT_ARRAY_CONVERTER_FACTORY( ShortArray )
1526  PYROOT_ARRAY_CONVERTER_FACTORY( ShortArrayRef )
1527  PYROOT_ARRAY_CONVERTER_FACTORY( UShortArray )
1528  PYROOT_ARRAY_CONVERTER_FACTORY( UShortArrayRef )
1529  PYROOT_ARRAY_CONVERTER_FACTORY( IntArray )
1530  PYROOT_ARRAY_CONVERTER_FACTORY( UIntArray )
1531  PYROOT_ARRAY_CONVERTER_FACTORY( UIntArrayRef )
1532  PYROOT_ARRAY_CONVERTER_FACTORY( LongArray )
1533  PYROOT_ARRAY_CONVERTER_FACTORY( ULongArray )
1534  PYROOT_ARRAY_CONVERTER_FACTORY( ULongArrayRef )
1535  PYROOT_ARRAY_CONVERTER_FACTORY( FloatArray )
1536  PYROOT_ARRAY_CONVERTER_FACTORY( FloatArrayRef )
1537  PYROOT_ARRAY_CONVERTER_FACTORY( DoubleArray )
1538  PYROOT_BASIC_CONVERTER_FACTORY( VoidArray )
1539  PYROOT_BASIC_CONVERTER_FACTORY( LongLongArray )
1541  PYROOT_BASIC_CONVERTER_FACTORY( STLString )
1542  PYROOT_BASIC_CONVERTER_FACTORY( STLStringView )
1543  PYROOT_BASIC_CONVERTER_FACTORY( VoidPtrRef )
1544  PYROOT_BASIC_CONVERTER_FACTORY( VoidPtrPtr )
1546 
1547 // converter factories for ROOT types
1548  typedef std::pair< const char*, ConverterFactory_t > NFp_t;
1549 
1550  // clang-format off
1551  NFp_t factories_[] = {
1552  // factories for built-ins
1553  NFp_t( "bool", &CreateBoolConverter ),
1554  NFp_t( "const bool&", &CreateConstBoolRefConverter ),
1555  NFp_t( "char", &CreateCharConverter ),
1556  NFp_t( "const char&", &CreateConstCharRefConverter ),
1557  NFp_t( "signed char", &CreateCharConverter ),
1558  NFp_t( "const signed char&", &CreateConstCharRefConverter ),
1559  NFp_t( "unsigned char", &CreateUCharConverter ),
1560  NFp_t( "const unsigned char&", &CreateConstUCharRefConverter ),
1561  NFp_t( "short", &CreateShortConverter ),
1562  NFp_t( "const short&", &CreateConstShortRefConverter ),
1563  NFp_t( "unsigned short", &CreateUShortConverter ),
1564  NFp_t( "const unsigned short&", &CreateConstUShortRefConverter ),
1565  NFp_t( "int", &CreateIntConverter ),
1566  NFp_t( "int&", &CreateIntRefConverter ),
1567  NFp_t( "const int&", &CreateConstIntRefConverter ),
1568  NFp_t( "unsigned int", &CreateUIntConverter ),
1569  NFp_t( "const unsigned int&", &CreateConstUIntRefConverter ),
1570  NFp_t( "UInt_t", /* enum */ &CreateIntConverter /* yes: Int */ ),
1571  NFp_t( "long", &CreateLongConverter ),
1572  NFp_t( "long&", &CreateLongRefConverter ),
1573  NFp_t( "const long&", &CreateConstLongRefConverter ),
1574  NFp_t( "unsigned long", &CreateULongConverter ),
1575  NFp_t( "const unsigned long&", &CreateConstULongRefConverter ),
1576  NFp_t( "long long", &CreateLongLongConverter ),
1577  NFp_t( "const long long&", &CreateConstLongLongRefConverter ),
1578  NFp_t( "Long64_t", &CreateLongLongConverter ),
1579  NFp_t( "const Long64_t&", &CreateConstLongLongRefConverter ),
1580  NFp_t( "unsigned long long", &CreateULongLongConverter ),
1581  NFp_t( "const unsigned long long&", &CreateConstULongLongRefConverter ),
1582  NFp_t( "ULong64_t", &CreateULongLongConverter ),
1583  NFp_t( "const ULong64_t&", &CreateConstULongLongRefConverter ),
1584 
1585  NFp_t( "float", &CreateFloatConverter ),
1586  NFp_t( "const float&", &CreateConstFloatRefConverter ),
1587  NFp_t( "double", &CreateDoubleConverter ),
1588  NFp_t( "double&", &CreateDoubleRefConverter ),
1589  NFp_t( "const double&", &CreateConstDoubleRefConverter ),
1590  NFp_t( "long double", &CreateLongDoubleConverter ),
1591  NFp_t( "const long double&", &CreateConstLongDoubleRefConverter ),
1592  NFp_t( "void", &CreateVoidConverter ),
1593 
1594  // pointer/array factories
1595  NFp_t( "bool*", &CreateBoolArrayConverter ),
1596  NFp_t( "bool&", &CreateBoolArrayRefConverter ),
1597  NFp_t( "const unsigned char*", &CreateCStringConverter ),
1598  NFp_t( "unsigned char*", &CreateNonConstUCStringConverter ),
1599  NFp_t( "short*", &CreateShortArrayConverter ),
1600  NFp_t( "short&", &CreateShortArrayRefConverter ),
1601  NFp_t( "unsigned short*", &CreateUShortArrayConverter ),
1602  NFp_t( "unsigned short&", &CreateUShortArrayRefConverter ),
1603  NFp_t( "int*", &CreateIntArrayConverter ),
1604  NFp_t( "unsigned int*", &CreateUIntArrayConverter ),
1605  NFp_t( "unsigned int&", &CreateUIntArrayRefConverter ),
1606  NFp_t( "long*", &CreateLongArrayConverter ),
1607  NFp_t( "unsigned long*", &CreateULongArrayConverter ),
1608  NFp_t( "unsigned long&", &CreateULongArrayRefConverter ),
1609  NFp_t( "float*", &CreateFloatArrayConverter ),
1610  NFp_t( "float&", &CreateFloatArrayRefConverter ),
1611  NFp_t( "double*", &CreateDoubleArrayConverter ),
1612  NFp_t( "long long*", &CreateLongLongArrayConverter ),
1613  NFp_t( "Long64_t*", &CreateLongLongArrayConverter ),
1614  NFp_t( "unsigned long long*", &CreateLongLongArrayConverter ), // TODO: ULongLong
1615  NFp_t( "ULong64_t*", &CreateLongLongArrayConverter ), // TODO: ULongLong
1616  NFp_t( "void*", &CreateVoidArrayConverter ),
1617 
1618  // factories for special cases
1619  NFp_t( "const char*", &CreateCStringConverter ),
1620  NFp_t( "char*", &CreateNonConstCStringConverter ),
1621  NFp_t( "TString", &CreateTStringConverter ),
1622  NFp_t( "const TString&", &CreateTStringConverter ),
1623  NFp_t( "std::string", &CreateSTLStringConverter ),
1624  NFp_t( "string", &CreateSTLStringConverter ),
1625  NFp_t( "const std::string&", &CreateSTLStringConverter ),
1626  NFp_t( "const string&", &CreateSTLStringConverter ),
1627  NFp_t( "std::string_view", &CreateSTLStringViewConverter ),
1628  NFp_t( "string_view", &CreateSTLStringViewConverter ),
1629  NFp_t( "experimental::basic_string_view<char,char_traits<char> >",&CreateSTLStringViewConverter),
1630  NFp_t( "basic_string_view<char,char_traits<char> >",&CreateSTLStringViewConverter),
1631  NFp_t( "void*&", &CreateVoidPtrRefConverter ),
1632  NFp_t( "void**", &CreateVoidPtrPtrConverter ),
1633  NFp_t( "PyObject*", &CreatePyObjectConverter ),
1634  NFp_t( "_object*", &CreatePyObjectConverter ),
1635  NFp_t( "FILE*", &CreateVoidArrayConverter ),
1636  NFp_t( "Float16_t", &CreateFloatConverter ),
1637  NFp_t( "const Float16_t&", &CreateConstFloatRefConverter ),
1638  NFp_t( "Double32_t", &CreateDoubleConverter ),
1639  NFp_t( "Double32_t&", &CreateDoubleRefConverter ),
1640  NFp_t( "const Double32_t&", &CreateConstDoubleRefConverter )
1641  };
1642  // clang-format on
1643 
1644  struct InitConvFactories_t {
1645  public:
1646  InitConvFactories_t()
1647  {
1648  // load all converter factories in the global map 'gConvFactories'
1649  int nf = sizeof( factories_ ) / sizeof( factories_[ 0 ] );
1650  for ( int i = 0; i < nf; ++i ) {
1651  gConvFactories[ factories_[ i ].first ] = factories_[ i ].second;
1652  }
1653  }
1654  } initConvFactories_;
1655 
1656 } // 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
#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
RooArgList L(const RooAbsArg &v1)
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
Definition: data.h:2
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
TH1 * h
Definition: legend2.C:5
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
const char * Long
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const char * Char
#define NULL
Definition: RtypesCore.h:88
#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++ unsigend 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
ClassInfo_t * GetClassInfo() const
Definition: TClass.h:381
#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
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
TLine * l
Definition: textangle.C:4
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>
PyObject * PyBuffer_FromMemory(Bool_t *buf, Py_ssize_t size=-1)
const Bool_t kFALSE
Definition: RtypesCore.h:92
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
Bool_t IsSubtype(TCppType_t derived, TCppType_t base)
Definition: Cppyy.cxx:598
static Bool_t PyROOT_PyLong_AsBool(PyObject *pyobject)
range-checking python integer to C++ bool conversion
Definition: Converters.cxx:65
double f(double x)
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
#define PYROOT_IMPLEMENT_BASIC_CONST_REF_CONVERTER(name, type, F1)
Definition: Converters.cxx:206
#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:2885
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
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
double result[121]
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:91
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
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