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