Logo ROOT   6.18/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 ______________________________________________________________________
33namespace PyROOT {
34
35// factories
36 typedef TConverter* (*ConverterFactory_t) ( Long_t size );
37 typedef std::map< std::string, ConverterFactory_t > ConvFactories_t;
40
41}
42
43//- pretend-ctypes helpers ----------------------------------------------------
44#if PY_VERSION_HEX >= 0x02050000
45
46struct PyROOT_tagCDataObject { // non-public (but so far very stable)
47 PyObject_HEAD
48 char* b_ptr;
49};
50
51static 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
65static 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
78static 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
84static 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
102static 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
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 ) \
154Bool_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 \
166PyObject* PyROOT::T##name##Converter::FromMemory( void* address ) \
167{ \
168 return F1( (stype)*((type*)address) ); \
169} \
170 \
171Bool_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
181static 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 )\
207Bool_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 )\
220Bool_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 ) \
236Bool_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 \
248PyObject* PyROOT::T##name##Converter::FromMemory( void* address ) \
249{ \
250 return PyROOT_PyUnicode_FromFormat( "%c", *((type*)address) ); \
251} \
252 \
253Bool_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
286Bool_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
326PYROOT_IMPLEMENT_BASIC_CONST_REF_CONVERTER( LongLong, Long64_t, PyLong_AsLongLong )
328
329////////////////////////////////////////////////////////////////////////////////
330/// convert `pyobject` to C++ (pseudo)int&, set arg for call
331
332Bool_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
377
378////////////////////////////////////////////////////////////////////////////////
379
383
384////////////////////////////////////////////////////////////////////////////////
385/// convert `pyobject` to C++ unsigned long, set arg for call
386
387Bool_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
397PyObject* 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
403Bool_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
416PyObject* PyROOT::TUIntConverter::FromMemory( void* address )
417{
418 return PyLong_FromUnsignedLong( *((UInt_t*)address) );
419}
420
421Bool_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
440PYROOT_IMPLEMENT_BASIC_CONVERTER( Float, Float_t, Double_t, PyFloat_FromDouble, PyFloat_AsDouble, 'f' )
441PYROOT_IMPLEMENT_BASIC_CONVERTER( Double, Double_t, Double_t, PyFloat_FromDouble, PyFloat_AsDouble, 'd' )
442
443PYROOT_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
448Bool_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
472PYROOT_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
486Bool_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
503PyObject* 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
509Bool_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
522Bool_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
532PyObject* 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
538Bool_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 -------------------------------------------------
611namespace {
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 ) \
784Bool_t PyROOT::T##name##ArrayConverter::SetArg( \
785 PyObject* pyobject, TParameter& para, TCallContext* /* ctxt */ ) \
786{ \
787 return CArraySetArg( pyobject, para, code, sizeof(type) ); \
788} \
789 \
790Bool_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 \
798PyObject* PyROOT::T##name##ArrayConverter::FromMemory( void* address ) \
799{ \
800 return BufFac_t::Instance()->PyBuffer_FromMemory( *(type**)address, fSize * sizeof(type) );\
801} \
802 \
803Bool_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 ) \
850PyROOT::T##name##Converter::T##name##Converter( Bool_t keepControl ) : \
851 TCppObjectConverter( Cppyy::GetScope( #type ), keepControl ) {} \
852 \
853Bool_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 \
872PyObject* 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 \
880Bool_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
891PYROOT_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
1105template <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
1133template <bool ISREFERENCE>
1135{
1136 return BindCppObject( address, fClass, kTRUE );
1137}
1138
1139////////////////////////////////////////////////////////////////////////////////
1140/// convert <value> to C++ instance*, write it at <address>
1141
1142template <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
1162namespace PyROOT {
1163////////////////////////////////////////////////////////////////////////////////
1164/// Instantiate the templates
1165
1166template class TCppObjectPtrConverter<true>;
1167template 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
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
1292Bool_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
1300PyObject* 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
1314Bool_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 -----------------------------------------------------------------
1404PyROOT::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->", /*bases?*/ true );
1460 if ( ! methods.empty() ) {
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 // Get underlying type of enum
1499 std::string et(TClassEdit::ResolveTypedef(Cppyy::ResolveEnum(realType).c_str()));
1500 if (cpd == "&") {
1501 auto reft = et + "&";
1502 h = isConst ? gConvFactories.find("const " + reft) : gConvFactories.find(reft);
1503 } else
1504 h = gConvFactories.find(et);
1505 } else if ( realType.find( "(*)" ) != std::string::npos ||
1506 ( realType.find( "::*)" ) != std::string::npos ) ) {
1507 // this is a function function pointer
1508 // TODO: find better way of finding the type
1509 // TODO: a converter that generates wrappers as appropriate
1510 h = gConvFactories.find( "void*" );
1511 }
1512
1513 if ( ! result && cpd == "&&" ) // moves
1514 result = new TNotImplementedConverter();
1515
1516 if ( ! result && h != gConvFactories.end() )
1517 // converter factory available, use it to create converter
1518 result = (h->second)( size );
1519 else if ( ! result ) {
1520 if ( cpd != "" ) {
1521 std::stringstream s;
1522 s << "creating converter for unknown type \"" << fullType << "\"" << std::ends;
1523 PyErr_Warn( PyExc_RuntimeWarning, (char*)s.str().c_str() );
1524 result = new TVoidArrayConverter(); // "user knows best"
1525 } else
1526 result = new TVoidConverter(); // fails on use
1527 }
1528
1529 return result;
1530}
1531
1532////////////////////////////////////////////////////////////////////////////////
1533
1534#define PYROOT_BASIC_CONVERTER_FACTORY( name ) \
1535TConverter* Create##name##Converter( Long_t ) \
1536{ \
1537 return new T##name##Converter(); \
1538}
1539
1540#define PYROOT_ARRAY_CONVERTER_FACTORY( name ) \
1541TConverter* Create##name##Converter( Long_t size ) \
1542{ \
1543 return new T##name##Converter( size ); \
1544}
1545
1546////////////////////////////////////////////////////////////////////////////////
1547
1548namespace {
1549 using namespace PyROOT;
1550
1551// use macro rather than template for portability ...
1553 PYROOT_BASIC_CONVERTER_FACTORY( ConstBoolRef )
1555 PYROOT_BASIC_CONVERTER_FACTORY( ConstCharRef )
1557 PYROOT_BASIC_CONVERTER_FACTORY( ConstUCharRef )
1559 PYROOT_BASIC_CONVERTER_FACTORY( ConstShortRef )
1561 PYROOT_BASIC_CONVERTER_FACTORY( ConstUShortRef )
1564 PYROOT_BASIC_CONVERTER_FACTORY( ConstIntRef )
1566 PYROOT_BASIC_CONVERTER_FACTORY( ConstUIntRef )
1569 PYROOT_BASIC_CONVERTER_FACTORY( ConstLongRef )
1571 PYROOT_BASIC_CONVERTER_FACTORY( ConstULongRef )
1573 PYROOT_BASIC_CONVERTER_FACTORY( ConstFloatRef )
1576 PYROOT_BASIC_CONVERTER_FACTORY( ConstDoubleRef )
1577 PYROOT_BASIC_CONVERTER_FACTORY( LongDouble )
1578 PYROOT_BASIC_CONVERTER_FACTORY( ConstLongDoubleRef )
1581 PYROOT_BASIC_CONVERTER_FACTORY( ConstLongLongRef )
1583 PYROOT_BASIC_CONVERTER_FACTORY( ConstULongLongRef )
1585 PYROOT_ARRAY_CONVERTER_FACTORY( NonConstCString )
1586 PYROOT_ARRAY_CONVERTER_FACTORY( NonConstUCString )
1588 PYROOT_BASIC_CONVERTER_FACTORY( BoolArrayRef )
1589 PYROOT_ARRAY_CONVERTER_FACTORY( ShortArray )
1590 PYROOT_ARRAY_CONVERTER_FACTORY( ShortArrayRef )
1591 PYROOT_ARRAY_CONVERTER_FACTORY( UShortArray )
1592 PYROOT_ARRAY_CONVERTER_FACTORY( UShortArrayRef )
1595 PYROOT_ARRAY_CONVERTER_FACTORY( UIntArrayRef )
1597 PYROOT_ARRAY_CONVERTER_FACTORY( ULongArray )
1598 PYROOT_ARRAY_CONVERTER_FACTORY( ULongArrayRef )
1599 PYROOT_ARRAY_CONVERTER_FACTORY( FloatArray )
1600 PYROOT_ARRAY_CONVERTER_FACTORY( FloatArrayRef )
1601 PYROOT_ARRAY_CONVERTER_FACTORY( DoubleArray )
1603 PYROOT_BASIC_CONVERTER_FACTORY( LongLongArray )
1606 PYROOT_BASIC_CONVERTER_FACTORY( STLStringView )
1607 PYROOT_BASIC_CONVERTER_FACTORY( VoidPtrRef )
1608 PYROOT_BASIC_CONVERTER_FACTORY( VoidPtrPtr )
1610
1611// converter factories for ROOT types
1612 typedef std::pair< const char*, ConverterFactory_t > NFp_t;
1613
1614 // clang-format off
1615 NFp_t factories_[] = {
1616 // factories for built-ins
1617 NFp_t( "bool", &CreateBoolConverter ),
1618 NFp_t( "const bool&", &CreateConstBoolRefConverter ),
1619 NFp_t( "char", &CreateCharConverter ),
1620 NFp_t( "const char&", &CreateConstCharRefConverter ),
1621 NFp_t( "signed char", &CreateCharConverter ),
1622 NFp_t( "const signed char&", &CreateConstCharRefConverter ),
1623 NFp_t( "unsigned char", &CreateUCharConverter ),
1624 NFp_t( "const unsigned char&", &CreateConstUCharRefConverter ),
1625 NFp_t( "short", &CreateShortConverter ),
1626 NFp_t( "const short&", &CreateConstShortRefConverter ),
1627 NFp_t( "unsigned short", &CreateUShortConverter ),
1628 NFp_t( "const unsigned short&", &CreateConstUShortRefConverter ),
1629 NFp_t( "int", &CreateIntConverter ),
1630 NFp_t( "int&", &CreateIntRefConverter ),
1631 NFp_t( "const int&", &CreateConstIntRefConverter ),
1632 NFp_t( "unsigned int", &CreateUIntConverter ),
1633 NFp_t( "const unsigned int&", &CreateConstUIntRefConverter ),
1634 NFp_t( "long", &CreateLongConverter ),
1635 NFp_t( "long&", &CreateLongRefConverter ),
1636 NFp_t( "const long&", &CreateConstLongRefConverter ),
1637 NFp_t( "unsigned long", &CreateULongConverter ),
1638 NFp_t( "const unsigned long&", &CreateConstULongRefConverter ),
1639 NFp_t( "long long", &CreateLongLongConverter ),
1640 NFp_t( "const long long&", &CreateConstLongLongRefConverter ),
1641 NFp_t( "Long64_t", &CreateLongLongConverter ),
1642 NFp_t( "const Long64_t&", &CreateConstLongLongRefConverter ),
1643 NFp_t( "unsigned long long", &CreateULongLongConverter ),
1644 NFp_t( "const unsigned long long&", &CreateConstULongLongRefConverter ),
1645 NFp_t( "ULong64_t", &CreateULongLongConverter ),
1646 NFp_t( "const ULong64_t&", &CreateConstULongLongRefConverter ),
1647
1648 NFp_t( "float", &CreateFloatConverter ),
1649 NFp_t( "const float&", &CreateConstFloatRefConverter ),
1650 NFp_t( "double", &CreateDoubleConverter ),
1651 NFp_t( "double&", &CreateDoubleRefConverter ),
1652 NFp_t( "const double&", &CreateConstDoubleRefConverter ),
1653 NFp_t( "long double", &CreateLongDoubleConverter ),
1654 NFp_t( "const long double&", &CreateConstLongDoubleRefConverter ),
1655 NFp_t( "void", &CreateVoidConverter ),
1656
1657 // pointer/array factories
1658 NFp_t( "bool*", &CreateBoolArrayConverter ),
1659 NFp_t( "bool&", &CreateBoolArrayRefConverter ),
1660 NFp_t( "const unsigned char*", &CreateCStringConverter ),
1661 NFp_t( "unsigned char*", &CreateNonConstUCStringConverter ),
1662 NFp_t( "short*", &CreateShortArrayConverter ),
1663 NFp_t( "short&", &CreateShortArrayRefConverter ),
1664 NFp_t( "unsigned short*", &CreateUShortArrayConverter ),
1665 NFp_t( "unsigned short&", &CreateUShortArrayRefConverter ),
1666 NFp_t( "int*", &CreateIntArrayConverter ),
1667 NFp_t( "unsigned int*", &CreateUIntArrayConverter ),
1668 NFp_t( "unsigned int&", &CreateUIntArrayRefConverter ),
1669 NFp_t( "long*", &CreateLongArrayConverter ),
1670 NFp_t( "unsigned long*", &CreateULongArrayConverter ),
1671 NFp_t( "unsigned long&", &CreateULongArrayRefConverter ),
1672 NFp_t( "float*", &CreateFloatArrayConverter ),
1673 NFp_t( "float&", &CreateFloatArrayRefConverter ),
1674 NFp_t( "double*", &CreateDoubleArrayConverter ),
1675 NFp_t( "long long*", &CreateLongLongArrayConverter ),
1676 NFp_t( "Long64_t*", &CreateLongLongArrayConverter ),
1677 NFp_t( "unsigned long long*", &CreateLongLongArrayConverter ), // TODO: ULongLong
1678 NFp_t( "ULong64_t*", &CreateLongLongArrayConverter ), // TODO: ULongLong
1679 NFp_t( "void*", &CreateVoidArrayConverter ),
1680
1681 // factories for special cases
1682 NFp_t( "const char*", &CreateCStringConverter ),
1683 NFp_t( "char*", &CreateNonConstCStringConverter ),
1684 NFp_t( "TString", &CreateTStringConverter ),
1685 NFp_t( "const TString&", &CreateTStringConverter ),
1686 NFp_t( "std::string", &CreateSTLStringConverter ),
1687 NFp_t( "string", &CreateSTLStringConverter ),
1688 NFp_t( "const std::string&", &CreateSTLStringConverter ),
1689 NFp_t( "const string&", &CreateSTLStringConverter ),
1690 NFp_t( "std::string_view", &CreateSTLStringViewConverter ),
1691 NFp_t( "string_view", &CreateSTLStringViewConverter ),
1692 NFp_t( "experimental::basic_string_view<char,char_traits<char> >",&CreateSTLStringViewConverter),
1693 NFp_t( "basic_string_view<char,char_traits<char> >",&CreateSTLStringViewConverter),
1694 NFp_t( "void*&", &CreateVoidPtrRefConverter ),
1695 NFp_t( "void**", &CreateVoidPtrPtrConverter ),
1696 NFp_t( "PyObject*", &CreatePyObjectConverter ),
1697 NFp_t( "_object*", &CreatePyObjectConverter ),
1698 NFp_t( "FILE*", &CreateVoidArrayConverter ),
1699 NFp_t( "Float16_t", &CreateFloatConverter ),
1700 NFp_t( "const Float16_t&", &CreateConstFloatRefConverter ),
1701 NFp_t( "Double32_t", &CreateDoubleConverter ),
1702 NFp_t( "Double32_t&", &CreateDoubleRefConverter ),
1703 NFp_t( "const Double32_t&", &CreateConstDoubleRefConverter )
1704 };
1705 // clang-format on
1706
1707 struct InitConvFactories_t {
1708 public:
1709 InitConvFactories_t()
1710 {
1711 // load all converter factories in the global map 'gConvFactories'
1712 int nf = sizeof( factories_ ) / sizeof( factories_[ 0 ] );
1713 for ( int i = 0; i < nf; ++i ) {
1714 gConvFactories[ factories_[ i ].first ] = factories_[ i ].second;
1715 }
1716 }
1717 } initConvFactories_;
1718
1719} // unnamed namespace
#define PYROOT_IMPLEMENT_BASIC_CHAR_CONVERTER(name, type, low, high)
Definition: Converters.cxx:235
static Bool_t PyROOT_PyLong_AsBool(PyObject *pyobject)
range-checking python integer to C++ bool conversion
Definition: Converters.cxx:65
static UShort_t PyROOT_PyLong_AsUShort(PyObject *pyobject)
range-checking python integer to C++ unsigned short int conversion
Definition: Converters.cxx:84
#define PYROOT_ARRAY_CONVERTER_FACTORY(name)
#define PYROOT_IMPLEMENT_BASIC_CONST_REF_CONVERTER(name, type, F1)
Definition: Converters.cxx:206
static Char_t PyROOT_PyUnicode_AsChar(PyObject *pyobject)
python string to C++ char conversion
Definition: Converters.cxx:78
static Int_t ExtractChar(PyObject *pyobject, const char *tname, Int_t low, Int_t high)
Definition: Converters.cxx:181
#define PYROOT_IMPLEMENT_BASIC_CONST_CHAR_REF_CONVERTER(name, type, low, high)
Definition: Converters.cxx:219
#define PYROOT_IMPLEMENT_ARRAY_CONVERTER(name, type, code)
Definition: Converters.cxx:783
static Short_t PyROOT_PyLong_AsShort(PyObject *pyobject)
range-checking python integer to C++ short int conversion
Definition: Converters.cxx:102
#define PYROOT_IMPLEMENT_BASIC_CONVERTER(name, type, stype, F1, F2, tc)
Definition: Converters.cxx:153
#define PYROOT_BASIC_CONVERTER_FACTORY(name)
static Long_t PyROOT_PyLong_AsStrictLong(PyObject *pyobject)
strict python integer to C++ integer conversion
Definition: Converters.cxx:121
#define PYROOT_IMPLEMENT_STRING_AS_PRIMITIVE_CONVERTER(name, type, F1, F2)
Definition: Converters.cxx:849
#define R__EXTERN
Definition: DllImport.h:27
PyLong_FromUnsignedLongLong
Definition: Executors.cxx:289
#define Py_TYPE(ob)
Definition: PyROOT.h:161
#define PY_SSIZE_T_FORMAT
Definition: PyROOT.h:169
#define PyROOT_PyUnicode_Check
Definition: PyROOT.h:76
#define PyROOT_PyUnicode_AsString
Definition: PyROOT.h:78
#define PyROOT_PyCapsule_CheckExact
Definition: PyROOT.h:94
static void * PyROOT_PyCapsule_GetPointer(PyObject *capsule, const char *)
Definition: PyROOT.h:95
#define PyROOT_PyUnicode_GET_SIZE
Definition: PyROOT.h:80
#define PyROOT_PyUnicode_FromString
Definition: PyROOT.h:82
#define PyROOT_PyUnicode_FromStringAndSize
Definition: PyROOT.h:86
#define PyROOT_PyUnicode_AsStringChecked
Definition: PyROOT.h:79
#define d(i)
Definition: RSha256.hxx:102
#define f(i)
Definition: RSha256.hxx:104
#define h(i)
Definition: RSha256.hxx:106
unsigned short UShort_t
Definition: RtypesCore.h:36
int Int_t
Definition: RtypesCore.h:41
unsigned char UChar_t
Definition: RtypesCore.h:34
char Char_t
Definition: RtypesCore.h:29
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
unsigned long ULong_t
Definition: RtypesCore.h:51
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
short Short_t
Definition: RtypesCore.h:35
double Double_t
Definition: RtypesCore.h:55
long double LongDouble_t
Definition: RtypesCore.h:57
long long Long64_t
Definition: RtypesCore.h:69
unsigned long long ULong64_t
Definition: RtypesCore.h:70
float Float_t
Definition: RtypesCore.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
char name[80]
Definition: TGX11.cxx:109
_object PyObject
Definition: TPyArg.h:20
Cppyy::TCppType_t ObjectIsA() const
Definition: ObjectProxy.h:66
void * GetObject() const
Definition: ObjectProxy.h:47
void SetSmartPtr(void *address, Cppyy::TCppType_t ptrType)
Definition: ObjectProxy.h:40
Cppyy::TCppType_t fSmartPtrType
Definition: ObjectProxy.h:80
virtual Bool_t ToMemory(PyObject *value, void *address)
could happen if no derived class override
Definition: Converters.cxx:589
virtual PyObject * FromMemory(void *address)
Definition: Converters.cxx:572
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 ToMemory(PyObject *value, void *address)
could happen if no derived class override
Definition: Converters.cxx:145
virtual PyObject * FromMemory(void *address)
Definition: Converters.cxx:135
virtual PyObject * FromMemory(void *address)
construct python tuple of instances from C++ array read at <address>
virtual Bool_t ToMemory(PyObject *value, void *address)
convert to C++ array of instances, write it at <address>
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
convert pyobject to C++ instance**, set arg for call
virtual PyObject * FromMemory(void *address)
construct python object from C++ instance read at <address>
Definition: Converters.cxx:940
virtual Bool_t ToMemory(PyObject *value, void *address)
convert to C++ instance, write it at <address>
Definition: Converters.cxx:948
virtual Bool_t ToMemory(PyObject *value, void *address)
convert to C++ instance*, write it at <address>
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
convert pyobject to C++ instance**, set arg for call
virtual PyObject * FromMemory(void *address)
construct python object from C++ instance* read at <address>
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
virtual PyObject * FromMemory(void *address)
assume this is a buffer access if the size is known; otherwise assume string
Definition: Converters.cxx:650
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 SetArg(PyObject *, TParameter &, TCallContext *=0)
raise a NotImplemented exception to take a method out of overload resolution
PyObject * PyBuffer_FromMemory(Bool_t *buf, Py_ssize_t size=-1)
static TPyBufferFactory * Instance()
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
convert pyobject to C++ instance&, set arg for call
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
smart pointer converter
virtual PyObject * FromMemory(void *address)
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
convert pyobject to C++ instance, set arg for call
Definition: Converters.cxx:985
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
just convert pointer if it is a ROOT object
Definition: Converters.cxx:704
virtual Bool_t GetAddressSpecialCase(PyObject *pyobject, void *&address)
(1): "null pointer" or C++11 style nullptr
Definition: Converters.cxx:674
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
virtual PyObject * FromMemory(void *address)
read a void** from address; since this is unknown, long is used (user can cast)
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
convert pyobject to C++ void**, set arg for call
virtual Bool_t SetArg(PyObject *, TParameter &, TCallContext *ctxt=0)
convert pyobject to C++ void*&, set arg for call
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:2895
Basic string class.
Definition: TString.h:131
basic_string_view< char > string_view
#define I(x, y, z)
#define H(x, y, z)
ptrdiff_t GetBaseOffset(TCppType_t derived, TCppType_t base, TCppObject_t address, int direction, bool rerror=false)
Definition: Cppyy.cxx:640
ptrdiff_t TCppScope_t
Definition: Cppyy.h:15
void CallDestructor(TCppType_t type, TCppObject_t self)
Definition: Cppyy.cxx:509
void * CallR(TCppMethod_t method, TCppObject_t self, void *args)
Definition: Cppyy.cxx:485
std::string ResolveName(const std::string &cppitem_name)
Definition: Cppyy.cxx:167
TCppScope_t TCppType_t
Definition: Cppyy.h:16
void Deallocate(TCppType_t type, TCppObject_t instance)
Definition: Cppyy.cxx:277
Bool_t IsEnum(const std::string &type_name)
Definition: Cppyy.cxx:575
TCppScope_t GetScope(const std::string &scope_name)
Definition: Cppyy.cxx:193
std::vector< TCppMethod_t > GetMethodsFromName(TCppScope_t scope, const std::string &name, bool alsoInBases=false)
Definition: Cppyy.cxx:710
ptrdiff_t TCppMethod_t
Definition: Cppyy.h:18
std::string GetMethodResultType(TCppMethod_t)
Definition: Cppyy.cxx:764
std::string GetFinalName(TCppType_t type)
Definition: Cppyy.cxx:581
Bool_t IsSmartPtr(const std::string &)
Definition: Cppyy.cxx:631
std::string ResolveEnum(const TEnum *en)
Definition: Cppyy.cxx:177
Bool_t IsSubtype(TCppType_t derived, TCppType_t base)
Definition: Cppyy.cxx:618
R__EXTERN PyObject * gEmptyString
Definition: PyStrings.h:23
R__EXTERN PyObject * gInit
Definition: PyStrings.h:27
R__EXTERN PyObject * gTypeCode
Definition: PyStrings.h:36
const std::string Compound(const std::string &name)
Break down the compound of a fully qualified type name.
Definition: Utility.cxx:680
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:561
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 TTupleOfInstances_CheckExact(T *object)
std::map< std::string, ConverterFactory_t > ConvFactories_t
Definition: Converters.cxx:37
ConvFactories_t gConvFactories
Definition: Converters.cxx:38
Bool_t ObjectProxy_Check(T *object)
Definition: ObjectProxy.h:91
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's useful.
ULong64_t PyLongOrInt_AsULong64(PyObject *pyobject)
Convert <pyobject> to C++ unsigned long long, with bounds checking.
Definition: Utility.cxx:166
Bool_t UseStrictOwnership(TCallContext *ctxt)
Definition: TCallContext.h:85
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
Convenience function with a lookup first through the known existing proxies.
TConverter * CreateConverter(const std::string &fullType, Long_t size=-1)
ULong_t PyLongOrInt_AsULong(PyObject *pyobject)
Definition: Utility.cxx:145
Bool_t TCustomFloat_CheckExact(T *object)
R__EXTERN PyObject * gNullPtrObject
Definition: Converters.cxx:39
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)
Bool_t TCustomInt_CheckExact(T *object)
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
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 ...
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.
static constexpr double s
static constexpr double L
Definition: first.py:1
const char * Long
const char * ULong
const char * Float
const char * Double
const char * UChar
const char * Short
const char * Int
const char * UInt
const char * UShort
const char * Bool
const char * Char
static ECallFlags sMemoryPolicy
Definition: TCallContext.h:49
union PyROOT::TParameter::Value fValue
auto * l
Definition: textangle.C:4