Logo ROOT  
Reference Guide
Converters.cxx
Go to the documentation of this file.
1 // Bindings
2 #include "CPyCppyy.h"
3 #include "DeclareConverters.h"
4 #include "CallContext.h"
5 #include "CPPExcInstance.h"
6 #include "CPPInstance.h"
7 #include "CPPOverload.h"
8 #include "CustomPyTypes.h"
9 #include "LowLevelViews.h"
10 #include "MemoryRegulator.h"
11 #include "ProxyWrappers.h"
12 #include "PyStrings.h"
13 #include "TemplateProxy.h"
14 #include "TupleOfInstances.h"
15 #include "TypeManip.h"
16 #include "Utility.h"
17 
18 // Standard
19 #include <limits.h>
20 #include <stddef.h> // for ptrdiff_t
21 #include <string.h>
22 #include <array>
23 #include <utility>
24 #include <sstream>
25 #if __cplusplus > 201402L
26 #include <cstddef>
27 #endif
28 #include "ROOT/RStringView.hxx"
29 
30 #define UNKNOWN_SIZE -1
31 #define UNKNOWN_ARRAY_SIZE -2
32 
33 
34 //- data _____________________________________________________________________
35 namespace CPyCppyy {
36 
37 // factories
38  typedef std::map<std::string, cf_t> ConvFactories_t;
40  extern PyObject* gNullPtrObject;
41 
42 }
43 
44 #if PY_VERSION_HEX < 0x03000000
45 const size_t MOVE_REFCOUNT_CUTOFF = 1;
46 #else
47 // p3 has at least 2 ref-counts, as contrary to p2, it will create a descriptor
48 // copy for the method holding self in the case of __init__; but there can also
49 // be a reference held by the frame object, which is indistinguishable from a
50 // local variable reference, so the cut-off has to remain 2.
51 const size_t MOVE_REFCOUNT_CUTOFF = 2;
52 #endif
53 
54 //- pretend-ctypes helpers ---------------------------------------------------
55 struct CPyCppyy_tagCDataObject { // non-public (but stable)
56  PyObject_HEAD
57  char* b_ptr;
58  int b_needsfree;
59 };
60 
61 struct CPyCppyy_tagPyCArgObject { // not public (but stable; note that older
62  PyObject_HEAD // Pythons protect 'D' with HAVE_LONG_LONG)
63  void* pffi_type;
64  char tag;
65  union { // for convenience, kept only relevant vals
66  long long q;
67  long double D;
68  void *p;
69  } value;
70  PyObject* obj;
71 };
72 
73 // indices of ctypes types into the array caches (not that c_complex does not
74 // exist as a type in ctypes)
75 #define ct_c_bool 0
76 #define ct_c_char 1
77 #define ct_c_shar 1
78 #define ct_c_wchar 2
79 #define ct_c_byte 3
80 #define ct_c_int8 3
81 #define ct_c_ubyte 4
82 #define ct_c_uchar 4
83 #define ct_c_uint8 4
84 #define ct_c_short 5
85 #define ct_c_ushort 6
86 #define ct_c_uint16 7
87 #define ct_c_int 8
88 #define ct_c_uint 9
89 #define ct_c_uint32 10
90 #define ct_c_long 11
91 #define ct_c_ulong 12
92 #define ct_c_longlong 13
93 #define ct_c_ulonglong 14
94 #define ct_c_float 15
95 #define ct_c_double 16
96 #define ct_c_longdouble 17
97 #define ct_c_char_p 18
98 #define ct_c_wchar_p 19
99 #define ct_c_void_p 20
100 #define ct_c_complex 21
101 #define NTYPES 22
102 
103 static std::array<const char*, NTYPES> gCTypesNames = {
104  "c_bool", "c_char", "c_wchar", "c_byte", "c_ubyte", "c_short", "c_ushort", "c_uint16",
105  "c_int", "c_uint", "c_uint32", "c_long", "c_ulong", "c_longlong", "c_ulonglong",
106  "c_float", "c_double", "c_longdouble",
107  "c_char_p", "c_wchar_p", "c_void_p", "c_complex" };
108 static std::array<PyTypeObject*, NTYPES> gCTypesTypes;
109 static std::array<PyTypeObject*, NTYPES> gCTypesPtrTypes;
110 
111 // Both GetCTypesType and GetCTypesPtrType, rely on the ctypes module itself
112 // caching the types (thus also making them unique), so no ref-count is needed.
113 // Further, by keeping a ref-count on the module, it won't be off-loaded until
114 // the 2nd cleanup cycle.
115 static PyTypeObject* GetCTypesType(int nidx)
116 {
117  static PyObject* ctmod = PyImport_ImportModule("ctypes"); // ref-count kept
118  if (!ctmod) {
119  PyErr_Clear();
120  return nullptr;
121  }
122  PyTypeObject* ct_t = gCTypesTypes[nidx];
123  if (!ct_t) {
124  ct_t = (PyTypeObject*)PyObject_GetAttrString(ctmod, gCTypesNames[nidx]);
125  if (!ct_t) PyErr_Clear();
126  else {
127  gCTypesTypes[nidx] = ct_t;
128  Py_DECREF(ct_t);
129  }
130  }
131  return ct_t;
132 }
133 
134 static PyTypeObject* GetCTypesPtrType(int nidx)
135 {
136  static PyObject* ctmod = PyImport_ImportModule("ctypes"); // ref-count kept
137  if (!ctmod) {
138  PyErr_Clear();
139  return nullptr;
140  }
141  PyTypeObject* cpt_t = gCTypesPtrTypes[nidx];
142  if (!cpt_t) {
143  if (strcmp(gCTypesNames[nidx], "c_char") == 0) {
144  cpt_t = (PyTypeObject*)PyObject_GetAttrString(ctmod, "c_char_p");
145  } else {
146  PyObject* ct_t = (PyObject*)GetCTypesType(nidx);
147  if (ct_t) {
148  PyObject* ptrcreat = PyObject_GetAttrString(ctmod, "POINTER");
149  cpt_t = (PyTypeObject*)PyObject_CallFunctionObjArgs(ptrcreat, ct_t, NULL);
150  Py_DECREF(ptrcreat);
151  }
152  }
153  if (cpt_t) {
154  gCTypesPtrTypes[nidx] = cpt_t;
155  Py_DECREF(cpt_t);
156  }
157  }
158  return cpt_t;
159 }
160 
161 static bool IsPyCArgObject(PyObject* pyobject)
162 {
163  static PyTypeObject* pycarg_type = nullptr;
164  if (!pycarg_type) {
165  PyObject* ctmod = PyImport_ImportModule("ctypes");
166  if (!ctmod) PyErr_Clear();
167  else {
168  PyTypeObject* ct_t = (PyTypeObject*)PyObject_GetAttrString(ctmod, "c_int");
169  PyObject* cobj = ct_t->tp_new(ct_t, nullptr, nullptr);
170  PyObject* byref = PyObject_GetAttrString(ctmod, "byref");
171  PyObject* pyptr = PyObject_CallFunctionObjArgs(byref, cobj, NULL);
172  Py_DECREF(byref); Py_DECREF(cobj); Py_DECREF(ct_t);
173  pycarg_type = Py_TYPE(pyptr); // static, no ref-count needed
174  Py_DECREF(pyptr);
175  }
176  Py_DECREF(ctmod);
177  }
178  return Py_TYPE(pyobject) == pycarg_type;
179 }
180 
181 static bool IsCTypesArrayOrPointer(PyObject* pyobject)
182 {
183  static PyTypeObject* cstgdict_type = nullptr;
184  if (!cstgdict_type) {
185  // get any pointer type to initialize the extended dictionary type
186  PyTypeObject* ct_int = GetCTypesType(ct_c_int);
187  if (ct_int && ct_int->tp_dict) {
188  cstgdict_type = Py_TYPE(ct_int->tp_dict);
189  }
190  }
191 
192  PyTypeObject* pytype = Py_TYPE(pyobject);
193  if (pytype->tp_dict && Py_TYPE(pytype->tp_dict) == cstgdict_type)
194  return true;
195  return false;
196 }
197 
198 
199 //- helper to work with both CPPInstance and CPPExcInstance ------------------
201 {
202  using namespace CPyCppyy;
203  if (CPPInstance_Check(pyobject))
204  return (CPPInstance*)pyobject;
205  if (CPPExcInstance_Check(pyobject))
206  return (CPPInstance*)((CPPExcInstance*)pyobject)->fCppInstance;
207  return nullptr;
208 }
209 
210 
211 //- custom helpers to check ranges -------------------------------------------
212 static inline bool CPyCppyy_PyLong_AsBool(PyObject* pyobject)
213 {
214 // range-checking python integer to C++ bool conversion
215  long l = PyLong_AsLong(pyobject);
216 // fail to pass float -> bool; the problem is rounding (0.1 -> 0 -> False)
217  if (!(l == 0|| l == 1) || PyFloat_Check(pyobject)) {
218  PyErr_SetString(PyExc_ValueError, "boolean value should be bool, or integer 1 or 0");
219  return (bool)-1;
220  }
221  return (bool)l;
222 }
223 
224 static inline char CPyCppyy_PyText_AsChar(PyObject* pyobject) {
225 // python string to C++ char conversion
226  return (char)CPyCppyy_PyText_AsString(pyobject)[0];
227 }
228 
229 static inline uint8_t CPyCppyy_PyLong_AsUInt8(PyObject* pyobject)
230 {
231 // range-checking python integer to C++ uint8_t conversion (typically, an unsigned char)
232 // prevent p2.7 silent conversions and do a range check
233  if (!(PyLong_Check(pyobject) || PyInt_Check(pyobject))) {
234  PyErr_SetString(PyExc_TypeError, "short int conversion expects an integer object");
235  return (uint8_t)-1;
236  }
237  long l = PyLong_AsLong(pyobject);
238  if (l < 0 || UCHAR_MAX < l) {
239  PyErr_Format(PyExc_ValueError, "integer %ld out of range for uint8_t", l);
240  return (uint8_t)-1;
241 
242  }
243  return (uint8_t)l;
244 }
245 
246 static inline int8_t CPyCppyy_PyLong_AsInt8(PyObject* pyobject)
247 {
248 // range-checking python integer to C++ int8_t conversion (typically, an signed char)
249 // prevent p2.7 silent conversions and do a range check
250  if (!(PyLong_Check(pyobject) || PyInt_Check(pyobject))) {
251  PyErr_SetString(PyExc_TypeError, "short int conversion expects an integer object");
252  return (int8_t)-1;
253  }
254  long l = PyLong_AsLong(pyobject);
255  if (l < SCHAR_MIN || SCHAR_MAX < l) {
256  PyErr_Format(PyExc_ValueError, "integer %ld out of range for int8_t", l);
257  return (int8_t)-1;
258 
259  }
260  return (int8_t)l;
261 }
262 
263 static inline unsigned short CPyCppyy_PyLong_AsUShort(PyObject* pyobject)
264 {
265 // range-checking python integer to C++ unsigend short int conversion
266 
267 // prevent p2.7 silent conversions and do a range check
268  if (!(PyLong_Check(pyobject) || PyInt_Check(pyobject))) {
269  PyErr_SetString(PyExc_TypeError, "unsigned short conversion expects an integer object");
270  return (unsigned short)-1;
271  }
272  long l = PyLong_AsLong(pyobject);
273  if (l < 0 || USHRT_MAX < l) {
274  PyErr_Format(PyExc_ValueError, "integer %ld out of range for unsigned short", l);
275  return (unsigned short)-1;
276 
277  }
278  return (unsigned short)l;
279 }
280 
281 static inline short CPyCppyy_PyLong_AsShort(PyObject* pyobject)
282 {
283 // range-checking python integer to C++ short int conversion
284 // prevent p2.7 silent conversions and do a range check
285  if (!(PyLong_Check(pyobject) || PyInt_Check(pyobject))) {
286  PyErr_SetString(PyExc_TypeError, "short int conversion expects an integer object");
287  return (short)-1;
288  }
289  long l = PyLong_AsLong(pyobject);
290  if (l < SHRT_MIN || SHRT_MAX < l) {
291  PyErr_Format(PyExc_ValueError, "integer %ld out of range for short int", l);
292  return (short)-1;
293 
294  }
295  return (short)l;
296 }
297 
298 static inline int CPyCppyy_PyLong_AsStrictInt(PyObject* pyobject)
299 {
300 // strict python integer to C++ integer conversion
301 
302 // p2.7 and later silently converts floats to long, therefore require this
303 // check; earlier pythons may raise a SystemError which should be avoided as
304 // it is confusing
305  if (!(PyLong_Check(pyobject) || PyInt_Check(pyobject))) {
306  PyErr_SetString(PyExc_TypeError, "int/long conversion expects an integer object");
307  return -1;
308  }
309  long l = PyLong_AsLong(pyobject);
310  if (l < INT_MIN || INT_MAX < l) {
311  PyErr_Format(PyExc_ValueError, "integer %ld out of range for int", l);
312  return (int)-1;
313 
314  }
315  return (int)l;
316 }
317 
318 static inline long CPyCppyy_PyLong_AsStrictLong(PyObject* pyobject)
319 {
320 // strict python integer to C++ long integer conversion
321 
322 // prevent float -> long (see CPyCppyy_PyLong_AsStrictInt)
323  if (!(PyLong_Check(pyobject) || PyInt_Check(pyobject))) {
324  PyErr_SetString(PyExc_TypeError, "int/long conversion expects an integer object");
325  return (long)-1;
326  }
327  return (long)PyLong_AsLong(pyobject);
328 }
329 
330 
331 //- helper for pointer/array/reference conversions ---------------------------
332 static inline bool CArraySetArg(PyObject* pyobject, CPyCppyy::Parameter& para, char tc, int size)
333 {
334 // general case of loading a C array pointer (void* + type code) as function argument
335  if (pyobject == CPyCppyy::gNullPtrObject)
336  para.fValue.fVoidp = nullptr;
337  else {
338  Py_ssize_t buflen = CPyCppyy::Utility::GetBuffer(pyobject, tc, size, para.fValue.fVoidp);
339  if (!buflen) {
340  // stuck here as it's the least common
341  if (CPyCppyy_PyLong_AsStrictInt(pyobject) == 0)
342  para.fValue.fVoidp = nullptr;
343  else {
344  PyErr_Format(PyExc_TypeError, // ValueError?
345  "could not convert argument to buffer or nullptr");
346  return false;
347  }
348  }
349  }
350  para.fTypeCode = 'p';
351  return true;
352 }
353 
354 
355 //- helper for implicit conversions ------------------------------------------
356 static inline bool ConvertImplicit(Cppyy::TCppType_t klass,
357  PyObject* pyobject, CPyCppyy::Parameter& para, CPyCppyy::CallContext* ctxt)
358 {
359  using namespace CPyCppyy;
360 
361 // filter out copy and move constructors
362  if (IsConstructor(ctxt->fFlags) && klass == ctxt->fCurScope && ctxt->GetSize() == 1)
363  return false;
364 
365 // only proceed if implicit conversions are allowed (in "round 2") or if the
366 // argument is exactly a tuple or list, as these are the equivalent of
367 // initializer lists and thus "syntax" not a conversion
368  if (!AllowImplicit(ctxt)) {
369  PyTypeObject* pytype = (PyTypeObject*)Py_TYPE(pyobject);
370  if (!(pytype == &PyList_Type || pytype == &PyTuple_Type)) {
371  if (!NoImplicit(ctxt)) ctxt->fFlags |= CallContext::kHaveImplicit;
372  return false;
373  }
374  }
375 
376 // exercise implicit conversion
377  PyObject* pyscope = CreateScopeProxy(klass);
378  if (!CPPScope_Check(pyscope)) {
379  Py_XDECREF(pyscope);
380  return false;
381  }
382 
383 // add a pseudo-keyword argument to prevent recursion
384  PyObject* kwds = PyDict_New();
385  PyDict_SetItem(kwds, PyStrings::gNoImplicit, Py_True);
386  PyObject* args = PyTuple_New(1);
387  Py_INCREF(pyobject); PyTuple_SET_ITEM(args, 0, pyobject);
388 
389 // call constructor of argument type to attempt implicit conversion
390  CPPInstance* pytmp = (CPPInstance*)PyObject_Call(pyscope, args, kwds);
391  if (!pytmp && PyTuple_CheckExact(pyobject)) {
392  // special case: allow implicit conversion from given set of arguments in tuple
393  PyErr_Clear();
394  PyDict_SetItem(kwds, PyStrings::gNoImplicit, Py_True); // was deleted
395  pytmp = (CPPInstance*)PyObject_Call(pyscope, pyobject, kwds);
396  }
397 
398  Py_DECREF(args);
399  Py_DECREF(kwds);
400  Py_DECREF(pyscope);
401 
402  if (pytmp) {
403  // implicit conversion succeeded!
404  ctxt->AddTemporary((PyObject*)pytmp);
405  para.fValue.fVoidp = pytmp->GetObject();
406  para.fTypeCode = 'V';
407  return true;
408  }
409 
410  PyErr_Clear();
411  return false;
412 }
413 
414 
415 //- base converter implementation --------------------------------------------
417 {
418  /* empty */
419 }
420 
421 //----------------------------------------------------------------------------
423 {
424 // could happen if no derived class override
425  PyErr_SetString(PyExc_TypeError, "C++ type cannot be converted from memory");
426  return nullptr;
427 }
428 
429 //----------------------------------------------------------------------------
431 {
432 // could happen if no derived class override
433  PyErr_SetString(PyExc_TypeError, "C++ type cannot be converted to memory");
434  return false;
435 }
436 
437 
438 //- helper macro's -----------------------------------------------------------
439 #define CPPYY_IMPL_BASIC_CONVERTER(name, type, stype, ctype, F1, F2, tc) \
440 bool CPyCppyy::name##Converter::SetArg( \
441  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */) \
442 { \
443 /* convert <pyobject> to C++ 'type', set arg for call */ \
444  type val = (type)F2(pyobject); \
445  if (val == (type)-1 && PyErr_Occurred()) { \
446  static PyTypeObject* ctypes_type = nullptr; \
447  if (!ctypes_type) { \
448  PyObject* pytype = 0, *pyvalue = 0, *pytrace = 0; \
449  PyErr_Fetch(&pytype, &pyvalue, &pytrace); \
450  ctypes_type = GetCTypesType(ct_##ctype); \
451  PyErr_Restore(pytype, pyvalue, pytrace); \
452  } \
453  if (Py_TYPE(pyobject) == ctypes_type) { \
454  PyErr_Clear(); \
455  val = *((type*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr); \
456  } else \
457  return false; \
458  } \
459  para.fValue.f##name = val; \
460  para.fTypeCode = tc; \
461  return true; \
462 } \
463  \
464 PyObject* CPyCppyy::name##Converter::FromMemory(void* address) \
465 { \
466  return F1((stype)*((type*)address)); \
467 } \
468  \
469 bool CPyCppyy::name##Converter::ToMemory(PyObject* value, void* address) \
470 { \
471  type s = (type)F2(value); \
472  if (s == (type)-1 && PyErr_Occurred()) \
473  return false; \
474  *((type*)address) = (type)s; \
475  return true; \
476 }
477 
478 //----------------------------------------------------------------------------
479 static inline int ExtractChar(PyObject* pyobject, const char* tname, int low, int high)
480 {
481  int lchar = -1;
482  if (CPyCppyy_PyText_Check(pyobject)) {
483  if (CPyCppyy_PyText_GET_SIZE(pyobject) == 1)
484  lchar = (int)CPyCppyy_PyText_AsChar(pyobject);
485  else
486  PyErr_Format(PyExc_ValueError, "%s expected, got string of size " PY_SSIZE_T_FORMAT,
487  tname, CPyCppyy_PyText_GET_SIZE(pyobject));
488  } else if (!PyFloat_Check(pyobject)) { // don't allow truncating conversion
489  lchar = (int)PyLong_AsLong(pyobject);
490  if (lchar == -1 && PyErr_Occurred())
491  ; // empty, as error already set
492  else if (!(low <= lchar && lchar <= high)) {
493  PyErr_Format(PyExc_ValueError,
494  "integer to character: value %d not in range [%d,%d]", lchar, low, high);
495  lchar = -1;
496  }
497  } else
498  PyErr_SetString(PyExc_TypeError, "char or small int type expected");
499 
500  return lchar;
501 }
502 
503 //----------------------------------------------------------------------------
504 #define CPPYY_IMPL_REFCONVERTER_FROM_MEMORY(name, ctype) \
505 PyObject* CPyCppyy::name##RefConverter::FromMemory(void* ptr) \
506 { \
507 /* convert a reference to int to Python through ctypes pointer object */ \
508  PyTypeObject* ctypes_type = GetCTypesType(ct_##ctype); \
509  if (!ctypes_type) { \
510  PyErr_SetString(PyExc_RuntimeError, "no ctypes available"); \
511  return nullptr; \
512  } \
513  PyObject* ref = ctypes_type->tp_new(ctypes_type, nullptr, nullptr); \
514  ((CPyCppyy_tagCDataObject*)ref)->b_ptr = (char*)ptr; \
515  ((CPyCppyy_tagCDataObject*)ref)->b_needsfree = 0; \
516  return ref; \
517 }
518 
519 //----------------------------------------------------------------------------
520 #define CPPYY_IMPL_BASIC_CONST_REFCONVERTER(name, type, ctype, F1) \
521 bool CPyCppyy::Const##name##RefConverter::SetArg( \
522  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */) \
523 { \
524  type val = (type)F1(pyobject); \
525  if (val == (type)-1 && PyErr_Occurred()) \
526  return false; \
527  para.fValue.f##name = val; \
528  para.fRef = &para.fValue.f##name; \
529  para.fTypeCode = 'r'; \
530  return true; \
531 } \
532 CPPYY_IMPL_REFCONVERTER_FROM_MEMORY(Const##name, ctype)
533 
534 //----------------------------------------------------------------------------
535 #define CPPYY_IMPL_BASIC_CONST_CHAR_REFCONVERTER(name, type, ctype, low, high)\
536 bool CPyCppyy::Const##name##RefConverter::SetArg( \
537  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */) \
538 { \
539 /* convert <pyobject> to C++ <<type>>, set arg for call, allow int -> char */\
540  type val = (type)ExtractChar(pyobject, #type, low, high); \
541  if (val == (type)-1 && PyErr_Occurred()) \
542  return false; \
543  para.fValue.fLong = val; \
544  para.fTypeCode = 'l'; \
545  return true; \
546 } \
547 CPPYY_IMPL_REFCONVERTER_FROM_MEMORY(Const##name, ctype)
548 
549 
550 //----------------------------------------------------------------------------
551 #define CPPYY_IMPL_BASIC_CHAR_CONVERTER(name, type, low, high) \
552 bool CPyCppyy::name##Converter::SetArg( \
553  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */) \
554 { \
555 /* convert <pyobject> to C++ <<type>>, set arg for call, allow int -> char */\
556  long val = ExtractChar(pyobject, #type, low, high); \
557  if (val == -1 && PyErr_Occurred()) \
558  return false; \
559  para.fValue.fLong = val; \
560  para.fTypeCode = 'l'; \
561  return true; \
562 } \
563  \
564 PyObject* CPyCppyy::name##Converter::FromMemory(void* address) \
565 { \
566  return CPyCppyy_PyText_FromFormat("%c", *((type*)address)); \
567 } \
568  \
569 bool CPyCppyy::name##Converter::ToMemory(PyObject* value, void* address) \
570 { \
571  Py_ssize_t len; \
572  const char* cstr = CPyCppyy_PyText_AsStringAndSize(value, &len); \
573  if (cstr) { \
574  if (len != 1) { \
575  PyErr_Format(PyExc_TypeError, #type" expected, got string of size %zd", len);\
576  return false; \
577  } \
578  *((type*)address) = (type)cstr[0]; \
579  } else { \
580  PyErr_Clear(); \
581  long l = PyLong_AsLong(value); \
582  if (l == -1 && PyErr_Occurred()) \
583  return false; \
584  if (!(low <= l && l <= high)) { \
585  PyErr_Format(PyExc_ValueError, \
586  "integer to character: value %ld not in range [%d,%d]", l, low, high);\
587  return false; \
588  } \
589  *((type*)address) = (type)l; \
590  } \
591  return true; \
592 }
593 
594 
595 //- converters for built-ins -------------------------------------------------
596 CPPYY_IMPL_BASIC_CONVERTER(Long, long, long, c_long, PyLong_FromLong, CPyCppyy_PyLong_AsStrictLong, 'l')
597 
598 //----------------------------------------------------------------------------
599 bool CPyCppyy::LongRefConverter::SetArg(
600  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
601 {
602 // convert <pyobject> to C++ long&, set arg for call
603 #if PY_VERSION_HEX < 0x03000000
604  if (RefInt_CheckExact(pyobject)) {
605  para.fValue.fVoidp = (void*)&((PyIntObject*)pyobject)->ob_ival;
606  para.fTypeCode = 'V';
607  return true;
608  }
609 #endif
610 
611  if (Py_TYPE(pyobject) == GetCTypesType(ct_c_long)) {
612  para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
613  para.fTypeCode = 'V';
614  return true;
615  }
616 
617  if (CArraySetArg(pyobject, para, 'l', sizeof(long))) {
618  para.fTypeCode = 'V';
619  return true;
620  }
621 
622  PyErr_SetString(PyExc_TypeError, "use ctypes.c_long for pass-by-ref of longs");
623  return false;
624 }
625 
626 //----------------------------------------------------------------------------
627 CPPYY_IMPL_BASIC_CONST_CHAR_REFCONVERTER(Char, char, c_char, CHAR_MIN, CHAR_MAX)
628 CPPYY_IMPL_BASIC_CONST_CHAR_REFCONVERTER(UChar, unsigned char, c_uchar, 0, UCHAR_MAX)
629 
639 CPPYY_IMPL_BASIC_CONST_REFCONVERTER(LLong, Long64_t, c_longlong, PyLong_AsLongLong)
641 
642 //----------------------------------------------------------------------------
643 bool CPyCppyy::IntRefConverter::SetArg(
644  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
645 {
646 // convert <pyobject> to C++ (pseudo)int&, set arg for call
647 #if PY_VERSION_HEX < 0x03000000
648  if (RefInt_CheckExact(pyobject)) {
649  para.fValue.fVoidp = (void*)&((PyIntObject*)pyobject)->ob_ival;
650  para.fTypeCode = 'V';
651  return true;
652  }
653 #endif
654 
655 #if PY_VERSION_HEX >= 0x02050000
656  if (Py_TYPE(pyobject) == GetCTypesType(ct_c_int)) {
657  para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
658  para.fTypeCode = 'V';
659  return true;
660  }
661 #endif
662 
663 // alternate, pass pointer from buffer
664  Py_ssize_t buflen = Utility::GetBuffer(pyobject, 'i', sizeof(int), para.fValue.fVoidp);
665  if (para.fValue.fVoidp && buflen) {
666  para.fTypeCode = 'V';
667  return true;
668  };
669 
670 #if PY_VERSION_HEX < 0x02050000
671  PyErr_SetString(PyExc_TypeError, "use cppyy.Long for pass-by-ref of ints");
672 #else
673  PyErr_SetString(PyExc_TypeError, "use ctypes.c_int for pass-by-ref of ints");
674 #endif
675  return false;
676 }
677 
678 //----------------------------------------------------------------------------
679 #define CPPYY_IMPL_REFCONVERTER(name, ctype, type, code) \
680 bool CPyCppyy::name##RefConverter::SetArg( \
681  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */) \
682 { \
683 /* convert a reference to int to Python through ctypes pointer object */ \
684  if (Py_TYPE(pyobject) == GetCTypesType(ct_##ctype)) { \
685  para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
686  para.fTypeCode = 'V'; \
687  return true; \
688  } \
689  bool res = CArraySetArg(pyobject, para, code, sizeof(type)); \
690  if (!res) { \
691  PyErr_SetString(PyExc_TypeError, "use ctypes."#ctype" for pass-by-ref of "#type);\
692  return false; \
693  } \
694  para.fTypeCode = 'V'; \
695  return res; \
696 } \
697 CPPYY_IMPL_REFCONVERTER_FROM_MEMORY(name, ctype)
698 
699 CPPYY_IMPL_REFCONVERTER(Bool, c_bool, bool, '?');
700 CPPYY_IMPL_REFCONVERTER(Char, c_char, char, 'b');
701 CPPYY_IMPL_REFCONVERTER(WChar, c_wchar, wchar_t, 'u');
702 CPPYY_IMPL_REFCONVERTER(Char16, c_uint16, char16_t, 'H');
703 CPPYY_IMPL_REFCONVERTER(Char32, c_uint32, char32_t, 'I');
704 CPPYY_IMPL_REFCONVERTER(SChar, c_byte, signed char, 'b');
705 CPPYY_IMPL_REFCONVERTER(UChar, c_ubyte, unsigned char, 'B');
706 CPPYY_IMPL_REFCONVERTER(Int8, c_int8, int8_t, 'b');
708 CPPYY_IMPL_REFCONVERTER(Short, c_short, short, 'h');
709 CPPYY_IMPL_REFCONVERTER(UShort, c_ushort, unsigned short, 'H');
711 CPPYY_IMPL_REFCONVERTER(UInt, c_uint, unsigned int, 'I');
713 CPPYY_IMPL_REFCONVERTER(ULong, c_ulong, unsigned long, 'L');
714 CPPYY_IMPL_REFCONVERTER(LLong, c_longlong, long long, 'q');
715 CPPYY_IMPL_REFCONVERTER(ULLong, c_ulonglong, unsigned long long, 'Q');
716 CPPYY_IMPL_REFCONVERTER(Float, c_float, float, 'f');
718 CPPYY_IMPL_REFCONVERTER(LDouble, c_longdouble, LongDouble_t, 'D');
719 
720 
721 //----------------------------------------------------------------------------
722 // convert <pyobject> to C++ bool, allow int/long -> bool, set arg for call
724  Bool, bool, long, c_bool, PyInt_FromLong, CPyCppyy_PyLong_AsBool, 'l')
725 
726 //----------------------------------------------------------------------------
727 CPPYY_IMPL_BASIC_CHAR_CONVERTER(Char, char, CHAR_MIN, CHAR_MAX)
728 CPPYY_IMPL_BASIC_CHAR_CONVERTER(UChar, unsigned char, 0, UCHAR_MAX)
729 
730 PyObject* CPyCppyy::UCharAsIntConverter::FromMemory(void* address)
731 {
732 // special case to be used with arrays: return a Python int instead of str
733 // (following the same convention as module array.array)
734  return PyInt_FromLong((long)*((unsigned char*)address));
735 }
736 
737 //----------------------------------------------------------------------------
738 bool CPyCppyy::WCharConverter::SetArg(
739  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
740 {
741 // convert <pyobject> to C++ <wchar_t>, set arg for call
742  if (!PyUnicode_Check(pyobject) || PyUnicode_GET_SIZE(pyobject) != 1) {
743  PyErr_SetString(PyExc_ValueError, "single wchar_t character expected");
744  return false;
745  }
746  wchar_t val;
747  Py_ssize_t res = CPyCppyy_PyUnicode_AsWideChar(pyobject, &val, 1);
748  if (res == -1)
749  return false;
750  para.fValue.fLong = (long)val;
751  para.fTypeCode = 'U';
752  return true;
753 }
754 
755 PyObject* CPyCppyy::WCharConverter::FromMemory(void* address)
756 {
757  return PyUnicode_FromWideChar((const wchar_t*)address, 1);
758 }
759 
760 bool CPyCppyy::WCharConverter::ToMemory(PyObject* value, void* address)
761 {
762  if (!PyUnicode_Check(value) || PyUnicode_GET_SIZE(value) != 1) {
763  PyErr_SetString(PyExc_ValueError, "single wchar_t character expected");
764  return false;
765  }
766  wchar_t val;
767  Py_ssize_t res = CPyCppyy_PyUnicode_AsWideChar(value, &val, 1);
768  if (res == -1)
769  return false;
770  *((wchar_t*)address) = val;
771  return true;
772 }
773 
774 //----------------------------------------------------------------------------
775 bool CPyCppyy::Char16Converter::SetArg(
776  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
777 {
778 // convert <pyobject> to C++ <char16_t>, set arg for call
779  if (!PyUnicode_Check(pyobject) || PyUnicode_GET_SIZE(pyobject) != 1) {
780  PyErr_SetString(PyExc_ValueError, "single char16_t character expected");
781  return false;
782  }
783 
784  PyObject* bstr = PyUnicode_AsUTF16String(pyobject);
785  if (!bstr) return false;
786 
787  char16_t val = *(char16_t*)(PyBytes_AS_STRING(bstr) + sizeof(char16_t) /*BOM*/);
788  Py_DECREF(bstr);
789  para.fValue.fLong = (long)val;
790  para.fTypeCode = 'U';
791  return true;
792 }
793 
794 PyObject* CPyCppyy::Char16Converter::FromMemory(void* address)
795 {
796  return PyUnicode_DecodeUTF16((const char*)address, sizeof(char16_t), nullptr, nullptr);
797 }
798 
799 bool CPyCppyy::Char16Converter::ToMemory(PyObject* value, void* address)
800 {
801  if (!PyUnicode_Check(value) || PyUnicode_GET_SIZE(value) != 1) {
802  PyErr_SetString(PyExc_ValueError, "single char16_t character expected");
803  return false;
804  }
805 
806  PyObject* bstr = PyUnicode_AsUTF16String(value);
807  if (!bstr) return false;
808 
809  *((char16_t*)address) = *(char16_t*)(PyBytes_AS_STRING(bstr) + sizeof(char16_t) /*BOM*/);
810  Py_DECREF(bstr);
811  return true;
812 }
813 
814 //----------------------------------------------------------------------------
815 bool CPyCppyy::Char32Converter::SetArg(
816  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
817 {
818 // convert <pyobject> to C++ <char32_t>, set arg for call
819  if (!PyUnicode_Check(pyobject) || 2 < PyUnicode_GET_SIZE(pyobject)) {
820  PyErr_SetString(PyExc_ValueError, "single char32_t character expected");
821  return false;
822  }
823 
824  PyObject* bstr = PyUnicode_AsUTF32String(pyobject);
825  if (!bstr) return false;
826 
827  char32_t val = *(char32_t*)(PyBytes_AS_STRING(bstr) + sizeof(char32_t) /*BOM*/);
828  Py_DECREF(bstr);
829  para.fValue.fLong = (long)val;
830  para.fTypeCode = 'U';
831  return true;
832 }
833 
834 PyObject* CPyCppyy::Char32Converter::FromMemory(void* address)
835 {
836  return PyUnicode_DecodeUTF32((const char*)address, sizeof(char32_t), nullptr, nullptr);
837 }
838 
839 bool CPyCppyy::Char32Converter::ToMemory(PyObject* value, void* address)
840 {
841  if (!PyUnicode_Check(value) || 2 < PyUnicode_GET_SIZE(value)) {
842  PyErr_SetString(PyExc_ValueError, "single char32_t character expected");
843  return false;
844  }
845 
846  PyObject* bstr = PyUnicode_AsUTF32String(value);
847  if (!bstr) return false;
848 
849  *((char32_t*)address) = *(char32_t*)(PyBytes_AS_STRING(bstr) + sizeof(char32_t) /*BOM*/);
850  Py_DECREF(bstr);
851  return true;
852 }
853 
854 //----------------------------------------------------------------------------
856  Int8, int8_t, long, c_int8, PyInt_FromLong, CPyCppyy_PyLong_AsInt8, 'l')
860  Short, short, long, c_short, PyInt_FromLong, CPyCppyy_PyLong_AsShort, 'l')
864  Int, int, long, c_uint, PyInt_FromLong, CPyCppyy_PyLong_AsStrictInt, 'l')
865 
866 //----------------------------------------------------------------------------
867 bool CPyCppyy::ULongConverter::SetArg(
868  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
869 {
870 // convert <pyobject> to C++ unsigned long, set arg for call
871  para.fValue.fULong = PyLongOrInt_AsULong(pyobject);
872  if (para.fValue.fULong == (unsigned long)-1 && PyErr_Occurred())
873  return false;
874  para.fTypeCode = 'L';
875  return true;
876 }
877 
878 PyObject* CPyCppyy::ULongConverter::FromMemory(void* address)
879 {
880 // construct python object from C++ unsigned long read at <address>
881  return PyLong_FromUnsignedLong(*((unsigned long*)address));
882 }
883 
884 bool CPyCppyy::ULongConverter::ToMemory(PyObject* value, void* address)
885 {
886 // convert <value> to C++ unsigned long, write it at <address>
887  unsigned long u = PyLongOrInt_AsULong(value);
888  if (u == (unsigned long)-1 && PyErr_Occurred())
889  return false;
890  *((unsigned long*)address) = u;
891  return true;
892 }
893 
894 //----------------------------------------------------------------------------
895 PyObject* CPyCppyy::UIntConverter::FromMemory(void* address)
896 {
897 // construct python object from C++ unsigned int read at <address>
898  return PyLong_FromUnsignedLong(*((UInt_t*)address));
899 }
900 
901 bool CPyCppyy::UIntConverter::ToMemory(PyObject* value, void* address)
902 {
903 // convert <value> to C++ unsigned int, write it at <address>
904  ULong_t u = PyLongOrInt_AsULong(value);
905  if (u == (unsigned long)-1 && PyErr_Occurred())
906  return false;
907 
908  if (u > (ULong_t)UINT_MAX) {
909  PyErr_SetString(PyExc_OverflowError, "value too large for unsigned int");
910  return false;
911  }
912 
913  *((UInt_t*)address) = (UInt_t)u;
914  return true;
915 }
916 
917 //- floating point converters ------------------------------------------------
919  Float, float, double, c_float, PyFloat_FromDouble, PyFloat_AsDouble, 'f')
922 
924  LDouble, LongDouble_t, LongDouble_t, c_longdouble, PyFloat_FromDouble, PyFloat_AsDouble, 'g')
925 
926 CPyCppyy::ComplexDConverter::ComplexDConverter(bool keepControl) :
927  InstanceConverter(Cppyy::GetScope("std::complex<double>"), keepControl) {}
928 
929 // special case for std::complex<double>, maps it to/from Python's complex
930 bool CPyCppyy::ComplexDConverter::SetArg(
931  PyObject* pyobject, Parameter& para, CallContext* ctxt)
932 {
933  const Py_complex& pc = PyComplex_AsCComplex(pyobject);
934  if (pc.real != -1.0 || !PyErr_Occurred()) {
935  fBuffer.real(pc.real);
936  fBuffer.imag(pc.imag);
937  para.fValue.fVoidp = &fBuffer;
938  para.fTypeCode = 'V';
939  return true;
940  }
941 
942  return this->InstanceConverter::SetArg(pyobject, para, ctxt);
943 } \
944  \
945 PyObject* CPyCppyy::ComplexDConverter::FromMemory(void* address)
946 {
947  std::complex<double>* dc = (std::complex<double>*)address;
948  return PyComplex_FromDoubles(dc->real(), dc->imag());
949 }
950 
951 bool CPyCppyy::ComplexDConverter::ToMemory(PyObject* value, void* address)
952 {
953  const Py_complex& pc = PyComplex_AsCComplex(value);
954  if (pc.real != -1.0 || !PyErr_Occurred()) {
955  std::complex<double>* dc = (std::complex<double>*)address;
956  dc->real(pc.real);
957  dc->imag(pc.imag);
958  return true;
959  }
960  return this->InstanceConverter::ToMemory(value, address);
961 }
962 
963 //----------------------------------------------------------------------------
964 bool CPyCppyy::DoubleRefConverter::SetArg(
965  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
966 {
967 // convert <pyobject> to C++ double&, set arg for call
968  if (RefFloat_CheckExact(pyobject)) {
969  para.fValue.fVoidp = (void*)&((PyFloatObject*)pyobject)->ob_fval;
970  para.fTypeCode = 'V';
971  return true;
972  }
973 
974 // alternate, pass pointer from buffer
975  Py_ssize_t buflen = Utility::GetBuffer(pyobject, 'd', sizeof(double), para.fValue.fVoidp);
976  if (para.fValue.fVoidp && buflen) {
977  para.fTypeCode = 'V';
978  return true;
979  }
980 
981 #if PY_VERSION_HEX < 0x02050000
982  PyErr_SetString(PyExc_TypeError, "use cppyy.Double for pass-by-ref of doubles");
983 #else
984  PyErr_SetString(PyExc_TypeError, "use ctypes.c_double for pass-by-ref of doubles");
985 #endif
986  return false;
987 }
988 
989 //----------------------------------------------------------------------------
993 
994 //----------------------------------------------------------------------------
995 bool CPyCppyy::VoidConverter::SetArg(PyObject*, Parameter&, CallContext*)
996 {
997 // can't happen (unless a type is mapped wrongly), but implemented for completeness
998  PyErr_SetString(PyExc_SystemError, "void/unknown arguments can\'t be set");
999  return false;
1000 }
1001 
1002 //----------------------------------------------------------------------------
1003 bool CPyCppyy::LLongConverter::SetArg(
1004  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
1005 {
1006 // convert <pyobject> to C++ long long, set arg for call
1007  if (PyFloat_Check(pyobject)) {
1008  // special case: float implements nb_int, but allowing rounding conversions
1009  // interferes with overloading
1010  PyErr_SetString(PyExc_ValueError, "cannot convert float to long long");
1011  return false;
1012  }
1013 
1014  para.fValue.fLLong = PyLong_AsLongLong(pyobject);
1015  if (PyErr_Occurred())
1016  return false;
1017  para.fTypeCode = 'q';
1018  return true;
1019 }
1020 
1021 PyObject* CPyCppyy::LLongConverter::FromMemory(void* address)
1022 {
1023 // construct python object from C++ long long read at <address>
1024  return PyLong_FromLongLong(*(Long64_t*)address);
1025 }
1026 
1027 bool CPyCppyy::LLongConverter::ToMemory(PyObject* value, void* address)
1028 {
1029 // convert <value> to C++ long long, write it at <address>
1030  Long64_t ll = PyLong_AsLongLong(value);
1031  if (ll == -1 && PyErr_Occurred())
1032  return false;
1033  *((Long64_t*)address) = ll;
1034  return true;
1035 }
1036 
1037 //----------------------------------------------------------------------------
1038 bool CPyCppyy::ULLongConverter::SetArg(
1039  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
1040 {
1041 // convert <pyobject> to C++ unsigned long long, set arg for call
1042  para.fValue.fULLong = PyLongOrInt_AsULong64(pyobject);
1043  if (PyErr_Occurred())
1044  return false;
1045  para.fTypeCode = 'Q';
1046  return true;
1047 }
1048 
1049 PyObject* CPyCppyy::ULLongConverter::FromMemory(void* address)
1050 {
1051 // construct python object from C++ unsigned long long read at <address>
1052  return PyLong_FromUnsignedLongLong(*(ULong64_t*)address);
1053 }
1054 
1055 bool CPyCppyy::ULLongConverter::ToMemory(PyObject* value, void* address)
1056 {
1057 // convert <value> to C++ unsigned long long, write it at <address>
1058  Long64_t ull = PyLongOrInt_AsULong64(value);
1059  if (PyErr_Occurred())
1060  return false;
1061  *((ULong64_t*)address) = ull;
1062  return true;
1063 }
1064 
1065 //----------------------------------------------------------------------------
1066 bool CPyCppyy::CStringConverter::SetArg(
1067  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
1068 {
1069 // construct a new string and copy it in new memory
1070  Py_ssize_t len;
1071  const char* cstr = CPyCppyy_PyText_AsStringAndSize(pyobject, &len);
1072  if (!cstr) {
1073  // special case: allow ctypes c_char_p
1074  PyObject* pytype = 0, *pyvalue = 0, *pytrace = 0;
1075  PyErr_Fetch(&pytype, &pyvalue, &pytrace);
1076  if (Py_TYPE(pyobject) == GetCTypesType(ct_c_char_p)) {
1077  para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
1078  para.fTypeCode = 'V';
1079  Py_XDECREF(pytype); Py_XDECREF(pyvalue); Py_XDECREF(pytrace);
1080  return true;
1081  }
1082  PyErr_Restore(pytype, pyvalue, pytrace);
1083  return false;
1084  }
1085 
1086  fBuffer = std::string(cstr, len);
1087 
1088 // verify (too long string will cause truncation, no crash)
1089  if (fMaxSize != -1 && fMaxSize < (long)fBuffer.size())
1090  PyErr_Warn(PyExc_RuntimeWarning, (char*)"string too long for char array (truncated)");
1091  else if (fMaxSize != -1)
1092  fBuffer.resize(fMaxSize, '\0'); // padd remainder of buffer as needed
1093 
1094 // set the value and declare success
1095  para.fValue.fVoidp = (void*)fBuffer.c_str();
1096  para.fTypeCode = 'p';
1097  return true;
1098 }
1099 
1100 PyObject* CPyCppyy::CStringConverter::FromMemory(void* address)
1101 {
1102 // construct python object from C++ const char* read at <address>
1103  if (address && *(char**)address) {
1104  if (fMaxSize != -1) { // need to prevent reading beyond boundary
1105  std::string buf(*(char**)address, fMaxSize); // cut on fMaxSize
1106  return CPyCppyy_PyText_FromString(buf.c_str()); // cut on \0
1107  }
1108 
1109  return CPyCppyy_PyText_FromString(*(char**)address);
1110  }
1111 
1112 // empty string in case there's no address
1113  Py_INCREF(PyStrings::gEmptyString);
1114  return PyStrings::gEmptyString;
1115 }
1116 
1117 bool CPyCppyy::CStringConverter::ToMemory(PyObject* value, void* address)
1118 {
1119 // convert <value> to C++ const char*, write it at <address>
1120  Py_ssize_t len;
1121  const char* cstr = CPyCppyy_PyText_AsStringAndSize(value, &len);
1122  if (!cstr) return false;
1123 
1124 // verify (too long string will cause truncation, no crash)
1125  if (fMaxSize != -1 && fMaxSize < (long)len)
1126  PyErr_Warn(PyExc_RuntimeWarning, (char*)"string too long for char array (truncated)");
1127 
1128  if (fMaxSize != -1)
1129  strncpy(*(char**)address, cstr, fMaxSize); // padds remainder
1130  else
1131  // coverity[secure_coding] - can't help it, it's intentional.
1132  strcpy(*(char**)address, cstr);
1133 
1134  return true;
1135 }
1136 
1137 //----------------------------------------------------------------------------
1138 bool CPyCppyy::WCStringConverter::SetArg(
1139  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
1140 {
1141 // construct a new string and copy it in new memory
1142  Py_ssize_t len = PyUnicode_GetSize(pyobject);
1143  if (len == (Py_ssize_t)-1 && PyErr_Occurred())
1144  return false;
1145 
1146  fBuffer = (wchar_t*)realloc(fBuffer, sizeof(wchar_t)*(len+1));
1147  Py_ssize_t res = CPyCppyy_PyUnicode_AsWideChar(pyobject, fBuffer, len);
1148  if (res == -1)
1149  return false; // could free the buffer here
1150 
1151 // set the value and declare success
1152  fBuffer[len] = L'\0';
1153  para.fValue.fVoidp = (void*)fBuffer;
1154  para.fTypeCode = 'p';
1155  return true;
1156 }
1157 
1158 PyObject* CPyCppyy::WCStringConverter::FromMemory(void* address)
1159 {
1160 // construct python object from C++ wchar_t* read at <address>
1161  if (address && *(wchar_t**)address) {
1162  if (fMaxSize != -1) // need to prevent reading beyond boundary
1163  return PyUnicode_FromWideChar(*(wchar_t**)address, fMaxSize);
1164  // with unknown size
1165  return PyUnicode_FromWideChar(*(wchar_t**)address, wcslen(*(wchar_t**)address));
1166  }
1167 
1168 // empty string in case there's no valid address
1169  wchar_t w = L'\0';
1170  return PyUnicode_FromWideChar(&w, 0);
1171 }
1172 
1173 bool CPyCppyy::WCStringConverter::ToMemory(PyObject* value, void* address)
1174 {
1175 // convert <value> to C++ wchar_t*, write it at <address>
1176  Py_ssize_t len = PyUnicode_GetSize(value);
1177  if (len == (Py_ssize_t)-1 && PyErr_Occurred())
1178  return false;
1179 
1180 // verify (too long string will cause truncation, no crash)
1181  if (fMaxSize != -1 && fMaxSize < len)
1182  PyErr_Warn(PyExc_RuntimeWarning, (char*)"string too long for wchar_t array (truncated)");
1183 
1184  Py_ssize_t res = -1;
1185  if (fMaxSize != -1)
1186  res = CPyCppyy_PyUnicode_AsWideChar(value, *(wchar_t**)address, fMaxSize);
1187  else
1188  // coverity[secure_coding] - can't help it, it's intentional.
1189  res = CPyCppyy_PyUnicode_AsWideChar(value, *(wchar_t**)address, len);
1190 
1191  if (res == -1) return false;
1192  return true;
1193 }
1194 
1195 //----------------------------------------------------------------------------
1196 bool CPyCppyy::CString16Converter::SetArg(
1197  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
1198 {
1199 // construct a new string and copy it in new memory
1200  Py_ssize_t len = PyUnicode_GetSize(pyobject);
1201  if (len == (Py_ssize_t)-1 && PyErr_Occurred())
1202  return false;
1203 
1204  PyObject* bstr = PyUnicode_AsUTF16String(pyobject);
1205  if (!bstr) return false;
1206 
1207  fBuffer = (char16_t*)realloc(fBuffer, sizeof(char16_t)*(len+1));
1208  memcpy(fBuffer, PyBytes_AS_STRING(bstr) + sizeof(char16_t) /*BOM*/, len*sizeof(char16_t));
1209  Py_DECREF(bstr);
1210 
1211 // set the value and declare success
1212  fBuffer[len] = u'\0';
1213  para.fValue.fVoidp = (void*)fBuffer;
1214  para.fTypeCode = 'p';
1215  return true;
1216 }
1217 
1218 PyObject* CPyCppyy::CString16Converter::FromMemory(void* address)
1219 {
1220 // construct python object from C++ char16_t* read at <address>
1221  if (address && *(char16_t**)address) {
1222  if (fMaxSize != -1) // need to prevent reading beyond boundary
1223  return PyUnicode_DecodeUTF16(*(const char**)address, fMaxSize, nullptr, nullptr);
1224  // with unknown size
1225  return PyUnicode_DecodeUTF16(*(const char**)address,
1226  std::char_traits<char16_t>::length(*(char16_t**)address)*sizeof(char16_t), nullptr, nullptr);
1227  }
1228 
1229 // empty string in case there's no valid address
1230  char16_t w = u'\0';
1231  return PyUnicode_DecodeUTF16((const char*)&w, 0, nullptr, nullptr);
1232 }
1233 
1234 bool CPyCppyy::CString16Converter::ToMemory(PyObject* value, void* address)
1235 {
1236 // convert <value> to C++ char16_t*, write it at <address>
1237  Py_ssize_t len = PyUnicode_GetSize(value);
1238  if (len == (Py_ssize_t)-1 && PyErr_Occurred())
1239  return false;
1240 
1241 // verify (too long string will cause truncation, no crash)
1242  if (fMaxSize != -1 && fMaxSize < len) {
1243  PyErr_Warn(PyExc_RuntimeWarning, (char*)"string too long for char16_t array (truncated)");
1244  len = fMaxSize-1;
1245  }
1246 
1247  PyObject* bstr = PyUnicode_AsUTF16String(value);
1248  if (!bstr) return false;
1249 
1250  memcpy(*((void**)address), PyBytes_AS_STRING(bstr) + sizeof(char16_t) /*BOM*/, len*sizeof(char16_t));
1251  Py_DECREF(bstr);
1252  *((char16_t**)address)[len] = u'\0';
1253  return true;
1254 }
1255 
1256 //----------------------------------------------------------------------------
1257 bool CPyCppyy::CString32Converter::SetArg(
1258  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
1259 {
1260 // construct a new string and copy it in new memory
1261  Py_ssize_t len = PyUnicode_GetSize(pyobject);
1262  if (len == (Py_ssize_t)-1 && PyErr_Occurred())
1263  return false;
1264 
1265  PyObject* bstr = PyUnicode_AsUTF32String(pyobject);
1266  if (!bstr) return false;
1267 
1268  fBuffer = (char32_t*)realloc(fBuffer, sizeof(char32_t)*(len+1));
1269  memcpy(fBuffer, PyBytes_AS_STRING(bstr) + sizeof(char32_t) /*BOM*/, len*sizeof(char32_t));
1270  Py_DECREF(bstr);
1271 
1272 // set the value and declare success
1273  fBuffer[len] = U'\0';
1274  para.fValue.fVoidp = (void*)fBuffer;
1275  para.fTypeCode = 'p';
1276  return true;
1277 }
1278 
1279 PyObject* CPyCppyy::CString32Converter::FromMemory(void* address)
1280 {
1281 // construct python object from C++ char32_t* read at <address>
1282  if (address && *(char32_t**)address) {
1283  if (fMaxSize != -1) // need to prevent reading beyond boundary
1284  return PyUnicode_DecodeUTF32(*(const char**)address, fMaxSize, nullptr, nullptr);
1285  // with unknown size
1286  return PyUnicode_DecodeUTF32(*(const char**)address,
1287  std::char_traits<char32_t>::length(*(char32_t**)address)*sizeof(char32_t), nullptr, nullptr);
1288  }
1289 
1290 // empty string in case there's no valid address
1291  char32_t w = U'\0';
1292  return PyUnicode_DecodeUTF32((const char*)&w, 0, nullptr, nullptr);
1293 }
1294 
1295 bool CPyCppyy::CString32Converter::ToMemory(PyObject* value, void* address)
1296 {
1297 // convert <value> to C++ char32_t*, write it at <address>
1298  Py_ssize_t len = PyUnicode_GetSize(value);
1299  if (len == (Py_ssize_t)-1 && PyErr_Occurred())
1300  return false;
1301 
1302 // verify (too long string will cause truncation, no crash)
1303  if (fMaxSize != -1 && fMaxSize < len) {
1304  PyErr_Warn(PyExc_RuntimeWarning, (char*)"string too long for char32_t array (truncated)");
1305  len = fMaxSize-1;
1306  }
1307 
1308  PyObject* bstr = PyUnicode_AsUTF32String(value);
1309  if (!bstr) return false;
1310 
1311  memcpy(*((void**)address), PyBytes_AS_STRING(bstr) + sizeof(char32_t) /*BOM*/, len*sizeof(char32_t));
1312  Py_DECREF(bstr);
1313  *((char32_t**)address)[len] = U'\0';
1314  return true;
1315 }
1316 
1317 
1318 //----------------------------------------------------------------------------
1319 bool CPyCppyy::NonConstCStringConverter::SetArg(
1320  PyObject* pyobject, Parameter& para, CallContext* ctxt)
1321 {
1322 // attempt base class first (i.e. passing a string), but if that fails, try a buffer
1323  if (this->CStringConverter::SetArg(pyobject, para, ctxt))
1324  return true;
1325 
1326 // apparently failed, try char buffer
1327  PyErr_Clear();
1328  return CArraySetArg(pyobject, para, 'c', sizeof(char));
1329 }
1330 
1331 //----------------------------------------------------------------------------
1332 PyObject* CPyCppyy::NonConstCStringConverter::FromMemory(void* address)
1333 {
1334 // assume this is a buffer access if the size is known; otherwise assume string
1335  if (fMaxSize != -1)
1336  return CPyCppyy_PyText_FromStringAndSize(*(char**)address, fMaxSize);
1337  return this->CStringConverter::FromMemory(address);
1338 }
1339 
1340 //----------------------------------------------------------------------------
1342 {
1343 // (1): C++11 style "null pointer"
1344  if (pyobject == gNullPtrObject) {
1345  address = nullptr;
1346  return true;
1347  }
1348 
1349 // (2): allow integer zero to act as a null pointer (C NULL), no deriveds
1350  if (PyInt_CheckExact(pyobject) || PyLong_CheckExact(pyobject)) {
1351  intptr_t val = (intptr_t)PyLong_AsLongLong(pyobject);
1352  if (val == 0l) {
1353  address = (void*)val;
1354  return true;
1355  }
1356 
1357  return false;
1358  }
1359 
1360 // (3): opaque PyCapsule (CObject in older pythons) from somewhere
1361  if (CPyCppyy_PyCapsule_CheckExact(pyobject)) {
1362  address = (void*)CPyCppyy_PyCapsule_GetPointer(pyobject, nullptr);
1363  return true;
1364  }
1365 
1366  return false;
1367 }
1368 
1369 //----------------------------------------------------------------------------
1371  PyObject* pyobject, Parameter& para, CallContext* ctxt)
1372 {
1373 // just convert pointer if it is a C++ object
1374  CPPInstance* pyobj = GetCppInstance(pyobject);
1375  if (pyobj) {
1376  // depending on memory policy, some objects are no longer owned when passed to C++
1377  if (!fKeepControl && !UseStrictOwnership(ctxt))
1378  pyobj->CppOwns();
1379 
1380  // set pointer (may be null) and declare success
1381  para.fValue.fVoidp = pyobj->GetObject();
1382  para.fTypeCode = 'p';
1383  return true;
1384  }
1385 
1386 // handle special cases
1387  if (GetAddressSpecialCase(pyobject, para.fValue.fVoidp)) {
1388  para.fTypeCode = 'p';
1389  return true;
1390  }
1391 
1392 // allow ctypes voidp (which if got as a buffer will return void**, not void*); use
1393 // isintance instead of an exact check, b/c c_void_p is the type mapper for typedefs
1394 // of void* (typically opaque handles)
1395  if (PyObject_IsInstance(pyobject, (PyObject*)GetCTypesType(ct_c_void_p))) {
1396  para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
1397  para.fTypeCode = 'V';
1398  return true;
1399  }
1400 
1401 // allow any other ctypes pointer type
1402  if (IsCTypesArrayOrPointer(pyobject)) {
1403  void** payload = (void**)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
1404  if (payload) {
1405  para.fValue.fVoidp = *payload;
1406  para.fTypeCode = 'p';
1407  return true;
1408  }
1409  }
1410 
1411 // final try: attempt to get buffer
1412  Py_ssize_t buflen = Utility::GetBuffer(pyobject, '*', 1, para.fValue.fVoidp, false);
1413 
1414 // ok if buffer exists (can't perform any useful size checks)
1415  if (para.fValue.fVoidp && buflen != 0) {
1416  para.fTypeCode = 'p';
1417  return true;
1418  }
1419 
1420 // give up
1421  return false;
1422 }
1423 
1424 //----------------------------------------------------------------------------
1426 {
1427 // nothing sensible can be done, just return <address> as pylong
1428  if (!address || *(ptrdiff_t*)address == 0) {
1429  Py_INCREF(gNullPtrObject);
1430  return gNullPtrObject;
1431  }
1432  return CreatePointerView(*(ptrdiff_t**)address);
1433 }
1434 
1435 //----------------------------------------------------------------------------
1437 {
1438 // just convert pointer if it is a C++ object
1439  CPPInstance* pyobj = GetCppInstance(value);
1440  if (pyobj) {
1441  // depending on memory policy, some objects are no longer owned when passed to C++
1443  pyobj->CppOwns();
1444 
1445  // set pointer (may be null) and declare success
1446  *(void**)address = pyobj->GetObject();
1447  return true;
1448  }
1449 
1450 // handle special cases
1451  void* ptr = nullptr;
1452  if (GetAddressSpecialCase(value, ptr)) {
1453  *(void**)address = ptr;
1454  return true;
1455  }
1456 
1457 // final try: attempt to get buffer
1458  void* buf = nullptr;
1459  Py_ssize_t buflen = Utility::GetBuffer(value, '*', 1, buf, false);
1460  if (!buf || buflen == 0)
1461  return false;
1462 
1463  *(void**)address = buf;
1464  return true;
1465 }
1466 
1467 //----------------------------------------------------------------------------
1468 #define CPPYY_IMPL_ARRAY_CONVERTER(name, ctype, type, code) \
1469 CPyCppyy::name##ArrayConverter::name##ArrayConverter(dims_t dims) { \
1470  int nalloc = (dims && 0 < dims[0]) ? (int)dims[0]+1: 2; \
1471  fShape = new Py_ssize_t[nalloc]; \
1472  if (dims) { \
1473  for (int i = 0; i < nalloc; ++i) fShape[i] = (Py_ssize_t)dims[i]; \
1474  } else { \
1475  fShape[0] = 1; fShape[1] = -1; \
1476  } \
1477 } \
1478  \
1479 bool CPyCppyy::name##ArrayConverter::SetArg( \
1480  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */) \
1481 { \
1482  /* filter ctypes first b/c their buffer conversion will be wrong */ \
1483  PyTypeObject* ctypes_type = GetCTypesType(ct_##ctype); \
1484  if (Py_TYPE(pyobject) == ctypes_type) { \
1485  para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
1486  para.fTypeCode = 'p'; \
1487  return true; \
1488  } else if (Py_TYPE(pyobject) == GetCTypesPtrType(ct_##ctype)) { \
1489  para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
1490  para.fTypeCode = 'V'; \
1491  return true; \
1492  } else if (IsPyCArgObject(pyobject)) { \
1493  CPyCppyy_tagPyCArgObject* carg = (CPyCppyy_tagPyCArgObject*)pyobject;\
1494  if (carg->obj && Py_TYPE(carg->obj) == ctypes_type) { \
1495  para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)carg->obj)->b_ptr;\
1496  para.fTypeCode = 'p'; \
1497  return true; \
1498  } \
1499  } \
1500  return CArraySetArg(pyobject, para, code, sizeof(type)); \
1501 } \
1502  \
1503 PyObject* CPyCppyy::name##ArrayConverter::FromMemory(void* address) \
1504 { \
1505  if (fShape[1] == UNKNOWN_SIZE) \
1506  return CreateLowLevelView((type**)address, fShape); \
1507  return CreateLowLevelView(*(type**)address, fShape); \
1508 } \
1509  \
1510 bool CPyCppyy::name##ArrayConverter::ToMemory(PyObject* value, void* address)\
1511 { \
1512  if (fShape[0] != 1) { \
1513  PyErr_SetString(PyExc_ValueError, "only 1-dim arrays supported"); \
1514  return false; \
1515  } \
1516  void* buf = nullptr; \
1517  Py_ssize_t buflen = Utility::GetBuffer(value, code, sizeof(type), buf); \
1518  if (buflen == 0) \
1519  return false; \
1520  if (0 <= fShape[1]) { \
1521  if (fShape[1] < buflen) { \
1522  PyErr_SetString(PyExc_ValueError, "buffer too large for value"); \
1523  return false; \
1524  } \
1525  memcpy(*(type**)address, buf, (0 < buflen ? buflen : 1)*sizeof(type));\
1526  } else \
1527  *(type**)address = (type*)buf; \
1528  return true; \
1529 } \
1530  \
1531 bool CPyCppyy::name##ArrayPtrConverter::SetArg( \
1532  PyObject* pyobject, Parameter& para, CallContext* ctxt ) \
1533 { \
1534  if (Py_TYPE(pyobject) == GetCTypesPtrType(ct_##ctype)) { \
1535  para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
1536  para.fTypeCode = 'p'; \
1537  return true; \
1538  } else if (Py_TYPE(pyobject) == GetCTypesType(ct_c_void_p)) { \
1539  /* special case: pass address of c_void_p buffer to return the address */\
1540  para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
1541  para.fTypeCode = 'p'; \
1542  return true; \
1543  } \
1544  bool res = name##ArrayConverter::SetArg(pyobject, para, ctxt); \
1545  if (res && para.fTypeCode == 'p') { \
1546  para.fRef = para.fValue.fVoidp; \
1547  para.fValue.fVoidp = &para.fRef; \
1548  return true; \
1549  } \
1550  return false; \
1551 }
1552 
1553 
1554 //----------------------------------------------------------------------------
1555 CPPYY_IMPL_ARRAY_CONVERTER(Bool, c_bool, bool, '?')
1556 CPPYY_IMPL_ARRAY_CONVERTER(SChar, c_char, signed char, 'b')
1557 CPPYY_IMPL_ARRAY_CONVERTER(UChar, c_ubyte, unsigned char, 'B')
1558 #if __cplusplus > 201402L
1559 CPPYY_IMPL_ARRAY_CONVERTER(Byte, c_ubyte, std::byte, 'B')
1560 #endif
1561 CPPYY_IMPL_ARRAY_CONVERTER(Short, c_short, short, 'h')
1562 CPPYY_IMPL_ARRAY_CONVERTER(UShort, c_ushort, unsigned short, 'H')
1563 CPPYY_IMPL_ARRAY_CONVERTER(Int, c_int, int, 'i')
1564 CPPYY_IMPL_ARRAY_CONVERTER(UInt, c_uint, unsigned int, 'I')
1565 CPPYY_IMPL_ARRAY_CONVERTER(Long, c_long, long, 'l')
1566 CPPYY_IMPL_ARRAY_CONVERTER(ULong, c_ulong, unsigned long, 'L')
1567 CPPYY_IMPL_ARRAY_CONVERTER(LLong, c_longlong, long long, 'q')
1568 CPPYY_IMPL_ARRAY_CONVERTER(ULLong, c_ulonglong, unsigned long long, 'Q')
1569 CPPYY_IMPL_ARRAY_CONVERTER(Float, c_float, float, 'f')
1571 CPPYY_IMPL_ARRAY_CONVERTER(LDouble, c_longdouble, long double, 'D')
1572 CPPYY_IMPL_ARRAY_CONVERTER(ComplexD, c_complex, std::complex<double>, 'Z')
1573 
1574 
1575 //----------------------------------------------------------------------------
1576 PyObject* CPyCppyy::CStringArrayConverter::FromMemory(void* address)
1577 {
1578  if (fShape[1] == UNKNOWN_SIZE)
1579  return CreateLowLevelView((const char**)address, fShape);
1580  return CreateLowLevelView(*(const char***)address, fShape);
1581 }
1582 
1583 
1584 //- converters for special cases ---------------------------------------------
1585 bool CPyCppyy::NullptrConverter::SetArg(PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
1586 {
1587 // Only allow C++11 style nullptr to pass
1588  if (pyobject == gNullPtrObject) {
1589  para.fValue.fVoidp = nullptr;
1590  para.fTypeCode = 'p';
1591  return true;
1592  }
1593  return false;
1594 }
1595 
1596 
1597 //----------------------------------------------------------------------------
1598 #define CPPYY_IMPL_STRING_AS_PRIMITIVE_CONVERTER(name, type, F1, F2) \
1599 CPyCppyy::name##Converter::name##Converter(bool keepControl) : \
1600  InstanceConverter(Cppyy::GetScope(#type), keepControl) {} \
1601  \
1602 bool CPyCppyy::name##Converter::SetArg( \
1603  PyObject* pyobject, Parameter& para, CallContext* ctxt) \
1604 { \
1605  Py_ssize_t len; \
1606  const char* cstr = CPyCppyy_PyText_AsStringAndSize(pyobject, &len); \
1607  if (cstr) { \
1608  fBuffer = type(cstr, len); \
1609  para.fValue.fVoidp = &fBuffer; \
1610  para.fTypeCode = 'V'; \
1611  return true; \
1612  } \
1613  \
1614  PyErr_Clear(); \
1615  if (!(PyInt_Check(pyobject) || PyLong_Check(pyobject))) { \
1616  bool result = InstanceConverter::SetArg(pyobject, para, ctxt); \
1617  para.fTypeCode = 'V'; \
1618  return result; \
1619  } \
1620  return false; \
1621 } \
1622  \
1623 PyObject* CPyCppyy::name##Converter::FromMemory(void* address) \
1624 { \
1625  if (address) \
1626  return CPyCppyy_PyText_FromStringAndSize(((type*)address)->F1(), ((type*)address)->F2()); \
1627  Py_INCREF(PyStrings::gEmptyString); \
1628  return PyStrings::gEmptyString; \
1629 } \
1630  \
1631 bool CPyCppyy::name##Converter::ToMemory(PyObject* value, void* address) \
1632 { \
1633  if (CPyCppyy_PyText_Check(value)) { \
1634  *((type*)address) = CPyCppyy_PyText_AsString(value); \
1635  return true; \
1636  } \
1637  \
1638  return InstanceConverter::ToMemory(value, address); \
1639 }
1640 
1642 CPPYY_IMPL_STRING_AS_PRIMITIVE_CONVERTER(STLString, std::string, c_str, size)
1643 CPPYY_IMPL_STRING_AS_PRIMITIVE_CONVERTER(STLStringViewBase, std::string_view, data, size)
1644 bool CPyCppyy::STLStringViewConverter::SetArg(
1645  PyObject* pyobject, Parameter& para, CallContext* ctxt)
1646 {
1647  if (this->STLStringViewBaseConverter::SetArg(pyobject, para, ctxt))
1648  return true;
1649 
1650  if (!CPPInstance_Check(pyobject))
1651  return false;
1652 
1653  static Cppyy::TCppScope_t sStringID = Cppyy::GetScope("std::string");
1654  CPPInstance* pyobj = (CPPInstance*)pyobject;
1655  if (pyobj->ObjectIsA() == sStringID) {
1656  void* ptr = pyobj->GetObject();
1657  if (!ptr)
1658  return false;
1659 
1660  fBuffer = *((std::string*)ptr);
1661  para.fValue.fVoidp = &fBuffer;
1662  para.fTypeCode = 'V';
1663  return true;
1664  }
1665 
1666  return false;
1667 }
1668 
1669 CPyCppyy::STLWStringConverter::STLWStringConverter(bool keepControl) :
1670  InstanceConverter(Cppyy::GetScope("std::wstring"), keepControl) {}
1671 
1672 bool CPyCppyy::STLWStringConverter::SetArg(
1673  PyObject* pyobject, Parameter& para, CallContext* ctxt)
1674 {
1675  if (PyUnicode_Check(pyobject)) {
1676  Py_ssize_t len = PyUnicode_GET_SIZE(pyobject);
1677  fBuffer.resize(len);
1678  CPyCppyy_PyUnicode_AsWideChar(pyobject, &fBuffer[0], len);
1679  para.fValue.fVoidp = &fBuffer;
1680  para.fTypeCode = 'V';
1681  return true;
1682  }
1683 
1684  if (!(PyInt_Check(pyobject) || PyLong_Check(pyobject))) {
1685  bool result = InstancePtrConverter::SetArg(pyobject, para, ctxt);
1686  para.fTypeCode = 'V';
1687  return result;
1688  }
1689 
1690  return false;
1691 }
1692 
1693 PyObject* CPyCppyy::STLWStringConverter::FromMemory(void* address)
1694 {
1695  if (address)
1696  return PyUnicode_FromWideChar(((std::wstring*)address)->c_str(), ((std::wstring*)address)->size());
1697  wchar_t w = L'\0';
1698  return PyUnicode_FromWideChar(&w, 0);
1699 }
1700 
1701 bool CPyCppyy::STLWStringConverter::ToMemory(PyObject* value, void* address)
1702 {
1703  if (PyUnicode_Check(value)) {
1704  Py_ssize_t len = PyUnicode_GET_SIZE(value);
1705  wchar_t* buf = new wchar_t[len+1];
1706  CPyCppyy_PyUnicode_AsWideChar(value, buf, len);
1707  *((std::wstring*)address) = std::wstring(buf, len);
1708  delete[] buf;
1709  return true;
1710  }
1711  return InstanceConverter::ToMemory(value, address);
1712 }
1713 
1714 
1715 bool CPyCppyy::STLStringMoveConverter::SetArg(
1716  PyObject* pyobject, Parameter& para, CallContext* ctxt)
1717 {
1718 // convert <pyobject> to C++ std::string&&, set arg for call
1719  int moveit_reason = 3; // move on temporary fBuffer
1720  if (CPPInstance_Check(pyobject)) {
1721  CPPInstance* pyobj = (CPPInstance*)pyobject;
1722  if (pyobj->fFlags & CPPInstance::kIsRValue) {
1723  pyobj->fFlags &= ~CPPInstance::kIsRValue;
1724  moveit_reason = 2;
1725  } else if (pyobject->ob_refcnt == MOVE_REFCOUNT_CUTOFF) {
1726  moveit_reason = 1;
1727  } else
1728  moveit_reason = 0;
1729  }
1730 
1731  if (moveit_reason) {
1732  bool result = this->STLStringConverter::SetArg(pyobject, para, ctxt);
1733  if (!result && moveit_reason == 2) // restore the movability flag?
1734  ((CPPInstance*)pyobject)->fFlags |= CPPInstance::kIsRValue;
1735  return result;
1736  }
1737 
1738  PyErr_SetString(PyExc_ValueError, "object is not an rvalue");
1739  return false; // not a temporary or movable object
1740 }
1741 
1742 
1743 //----------------------------------------------------------------------------
1745  PyObject* pyobject, Parameter& para, CallContext* ctxt)
1746 {
1747 // convert <pyobject> to C++ instance*, set arg for call
1748  CPPInstance* pyobj = GetCppInstance(pyobject);
1749  if (!pyobj) {
1750  if (GetAddressSpecialCase(pyobject, para.fValue.fVoidp)) {
1751  para.fTypeCode = 'p'; // allow special cases such as nullptr
1752  return true;
1753  }
1754 
1755  // not a cppyy object (TODO: handle SWIG etc.)
1756  return false;
1757  }
1758 
1759  if (pyobj->ObjectIsA() && Cppyy::IsSubtype(pyobj->ObjectIsA(), fClass)) {
1760  // depending on memory policy, some objects need releasing when passed into functions
1761  if (!KeepControl() && !UseStrictOwnership(ctxt))
1762  pyobj->CppOwns();
1763 
1764  // calculate offset between formal and actual arguments
1765  para.fValue.fVoidp = pyobj->GetObject();
1766  if (pyobj->ObjectIsA() != fClass) {
1768  pyobj->ObjectIsA(), fClass, para.fValue.fVoidp, 1 /* up-cast */);
1769  }
1770 
1771  // set pointer (may be null) and declare success
1772  para.fTypeCode = 'p';
1773  return true;
1774  }
1775 
1776  return false;
1777 }
1778 
1779 //----------------------------------------------------------------------------
1781 {
1782 // construct python object from C++ instance read at <address>
1784 }
1785 
1786 //----------------------------------------------------------------------------
1788 {
1789 // convert <value> to C++ instance, write it at <address>
1790  CPPInstance* pyobj = GetCppInstance(value);
1791  if (!pyobj) {
1792  void* ptr = nullptr;
1793  if (GetAddressSpecialCase(value, ptr)) {
1794  *(void**)address = ptr; // allow special cases such as nullptr
1795  return true;
1796  }
1797 
1798  // not a cppyy object (TODO: handle SWIG etc.)
1799  return false;
1800  }
1801 
1802  if (Cppyy::IsSubtype(pyobj->ObjectIsA(), fClass)) {
1803  // depending on memory policy, some objects need releasing when passed into functions
1804  if (!KeepControl() && CallContext::sMemoryPolicy != CallContext::kUseStrict)
1805  ((CPPInstance*)value)->CppOwns();
1806 
1807  *(void**)address = pyobj->GetObject();
1808  return true;
1809  }
1810 
1811  return false;
1812 }
1813 
1814 // TODO: CONSOLIDATE Instance, InstanceRef, InstancePtr ...
1815 
1816 //----------------------------------------------------------------------------
1817 bool CPyCppyy::InstanceConverter::SetArg(
1818  PyObject* pyobject, Parameter& para, CallContext* ctxt)
1819 {
1820 // convert <pyobject> to C++ instance, set arg for call
1821  CPPInstance* pyobj = GetCppInstance(pyobject);
1822  if (pyobj) {
1823  if (pyobj->ObjectIsA() && Cppyy::IsSubtype(pyobj->ObjectIsA(), fClass)) {
1824  // calculate offset between formal and actual arguments
1825  para.fValue.fVoidp = pyobj->GetObject();
1826  if (!para.fValue.fVoidp)
1827  return false;
1828 
1829  if (pyobj->ObjectIsA() != fClass) {
1831  pyobj->ObjectIsA(), fClass, para.fValue.fVoidp, 1 /* up-cast */);
1832  }
1833 
1834  para.fTypeCode = 'V';
1835  return true;
1836  }
1837  }
1838 
1839  return ConvertImplicit(fClass, pyobject, para, ctxt);
1840 }
1841 
1842 //----------------------------------------------------------------------------
1843 PyObject* CPyCppyy::InstanceConverter::FromMemory(void* address)
1844 {
1846 }
1847 
1848 //----------------------------------------------------------------------------
1849 bool CPyCppyy::InstanceConverter::ToMemory(PyObject* value, void* address)
1850 {
1851 // assign value to C++ instance living at <address> through assignment operator
1852  PyObject* pyobj = BindCppObjectNoCast(address, fClass);
1853  PyObject* result = PyObject_CallMethod(pyobj, (char*)"__assign__", (char*)"O", value);
1854  Py_DECREF(pyobj);
1855 
1856  if (result) {
1857  Py_DECREF(result);
1858  return true;
1859  }
1860  return false;
1861 }
1862 
1863 
1864 //----------------------------------------------------------------------------
1865 bool CPyCppyy::InstanceRefConverter::SetArg(
1866  PyObject* pyobject, Parameter& para, CallContext* ctxt)
1867 {
1868 // convert <pyobject> to C++ instance&, set arg for call
1869  CPPInstance* pyobj = GetCppInstance(pyobject);
1870  if (pyobj) {
1871 
1872  // reject moves
1873  if (pyobj->fFlags & CPPInstance::kIsRValue)
1874  return false;
1875 
1876  if (pyobj->ObjectIsA() && Cppyy::IsSubtype(pyobj->ObjectIsA(), fClass)) {
1877  // calculate offset between formal and actual arguments
1878  para.fValue.fVoidp = pyobj->GetObject();
1879  if (pyobj->ObjectIsA() != fClass) {
1881  pyobj->ObjectIsA(), fClass, para.fValue.fVoidp, 1 /* up-cast */);
1882  }
1883 
1884  para.fTypeCode = 'V';
1885  return true;
1886  }
1887  }
1888 
1889  if (!fIsConst) // no implicit conversion possible
1890  return false;
1891 
1892  return ConvertImplicit(fClass, pyobject, para, ctxt);
1893 }
1894 
1895 //----------------------------------------------------------------------------
1896 PyObject* CPyCppyy::InstanceRefConverter::FromMemory(void* address)
1897 {
1899 }
1900 
1901 //----------------------------------------------------------------------------
1902 bool CPyCppyy::InstanceMoveConverter::SetArg(
1903  PyObject* pyobject, Parameter& para, CallContext* ctxt)
1904 {
1905 // convert <pyobject> to C++ instance&&, set arg for call
1906  CPPInstance* pyobj = GetCppInstance(pyobject);
1907  if (!pyobj) {
1908  // implicit conversion is fine as it the temporary by definition is moveable
1909  return ConvertImplicit(fClass, pyobject, para, ctxt);
1910  }
1911 
1912 // moving is same as by-ref, but have to check that move is allowed
1913  int moveit_reason = 0;
1914  if (pyobj->fFlags & CPPInstance::kIsRValue) {
1915  pyobj->fFlags &= ~CPPInstance::kIsRValue;
1916  moveit_reason = 2;
1917  } else if (pyobject->ob_refcnt == MOVE_REFCOUNT_CUTOFF) {
1918  moveit_reason = 1;
1919  }
1920 
1921  if (moveit_reason) {
1922  bool result = this->InstanceRefConverter::SetArg(pyobject, para, ctxt);
1923  if (!result && moveit_reason == 2) // restore the movability flag?
1924  ((CPPInstance*)pyobject)->fFlags |= CPPInstance::kIsRValue;
1925  return result;
1926  }
1927 
1928  PyErr_SetString(PyExc_ValueError, "object is not an rvalue");
1929  return false; // not a temporary or movable object
1930 }
1931 
1932 //----------------------------------------------------------------------------
1933 template <bool ISREFERENCE>
1934 bool CPyCppyy::InstancePtrPtrConverter<ISREFERENCE>::SetArg(
1935  PyObject* pyobject, Parameter& para, CallContext* ctxt)
1936 {
1937 // convert <pyobject> to C++ instance**, set arg for call
1938  CPPInstance* pyobj = GetCppInstance(pyobject);
1939  if (!pyobj)
1940  return false; // not a cppyy object (TODO: handle SWIG etc.)
1941 
1942  if (Cppyy::IsSubtype(pyobj->ObjectIsA(), fClass)) {
1943  // depending on memory policy, some objects need releasing when passed into functions
1944  if (!KeepControl() && !UseStrictOwnership(ctxt))
1945  pyobj->CppOwns();
1946 
1947  // set pointer (may be null) and declare success
1948  if (pyobj->fFlags & CPPInstance::kIsReference) // already a ptr to object?
1949  para.fValue.fVoidp = pyobj->GetObjectRaw();
1950  else
1951  para.fValue.fVoidp = &pyobj->GetObjectRaw();
1952  para.fTypeCode = ISREFERENCE ? 'V' : 'p';
1953  return true;
1954  }
1955 
1956  return false;
1957 }
1958 
1959 //----------------------------------------------------------------------------
1960 template <bool ISREFERENCE>
1961 PyObject* CPyCppyy::InstancePtrPtrConverter<ISREFERENCE>::FromMemory(void* address)
1962 {
1963 // construct python object from C++ instance* read at <address>
1965 }
1966 
1967 //----------------------------------------------------------------------------
1968 template <bool ISREFERENCE>
1969 bool CPyCppyy::InstancePtrPtrConverter<ISREFERENCE>::ToMemory(PyObject* value, void* address)
1970 {
1971 // convert <value> to C++ instance*, write it at <address>
1972  CPPInstance* pyobj = GetCppInstance(value);
1973  if (!pyobj)
1974  return false; // not a cppyy object (TODO: handle SWIG etc.)
1975 
1976  if (Cppyy::IsSubtype(pyobj->ObjectIsA(), fClass)) {
1977  // depending on memory policy, some objects need releasing when passed into functions
1978  if (!KeepControl() && CallContext::sMemoryPolicy != CallContext::kUseStrict)
1979  pyobj->CppOwns();
1980 
1981  // register the value for potential recycling
1983 
1984  // set pointer (may be null) and declare success
1985  *(void**)address = pyobj->GetObject();
1986  return true;
1987  }
1988 
1989  return false;
1990 }
1991 
1992 
1993 namespace CPyCppyy {
1994 // Instantiate the templates
1995  template class CPyCppyy::InstancePtrPtrConverter<true>;
1996  template class CPyCppyy::InstancePtrPtrConverter<false>;
1997 }
1998 
1999 //----------------------------------------------------------------------------
2000 bool CPyCppyy::InstanceArrayConverter::SetArg(
2001  PyObject* pyobject, Parameter& para, CallContext* /* txt */)
2002 {
2003 // convert <pyobject> to C++ instance**, set arg for call
2004  if (!TupleOfInstances_CheckExact(pyobject))
2005  return false; // no guarantee that the tuple is okay
2006 
2007 // treat the first instance of the tuple as the start of the array, and pass it
2008 // by pointer (TODO: store and check sizes)
2009  if (PyTuple_Size(pyobject) < 1)
2010  return false;
2011 
2012  PyObject* first = PyTuple_GetItem(pyobject, 0);
2013  if (!CPPInstance_Check(first))
2014  return false; // should not happen
2015 
2016  if (Cppyy::IsSubtype(((CPPInstance*)first)->ObjectIsA(), fClass)) {
2017  // no memory policies supported; set pointer (may be null) and declare success
2018  para.fValue.fVoidp = ((CPPInstance*)first)->GetObject();
2019  para.fTypeCode = 'p';
2020  return true;
2021  }
2022 
2023  return false;
2024 }
2025 
2026 //----------------------------------------------------------------------------
2027 PyObject* CPyCppyy::InstanceArrayConverter::FromMemory(void* address)
2028 {
2029 // construct python tuple of instances from C++ array read at <address>
2030  return BindCppObjectArray(*(char**)address, fClass, m_dims);
2031 }
2032 
2033 //----------------------------------------------------------------------------
2034 bool CPyCppyy::InstanceArrayConverter::ToMemory(PyObject* /* value */, void* /* address */)
2035 {
2036 // convert <value> to C++ array of instances, write it at <address>
2037 
2038 // TODO: need to have size both for the array and from the input
2039  PyErr_SetString(PyExc_NotImplementedError,
2040  "access to C-arrays of objects not yet implemented!");
2041  return false;
2042 }
2043 
2044 //___________________________________________________________________________
2045 // CLING WORKAROUND -- classes for STL iterators are completely undefined in that
2046 // they come in a bazillion different guises, so just do whatever
2047 bool CPyCppyy::STLIteratorConverter::SetArg(
2048  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
2049 {
2050  if (!CPPInstance_Check(pyobject))
2051  return false;
2052 
2053 // just set the pointer value, no check
2054  CPPInstance* pyobj = (CPPInstance*)pyobject;
2055  para.fValue.fVoidp = pyobj->GetObject();
2056  para.fTypeCode = 'V';
2057  return true;
2058 }
2059 // -- END CLING WORKAROUND
2060 
2061 //----------------------------------------------------------------------------
2062 bool CPyCppyy::VoidPtrRefConverter::SetArg(
2063  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
2064 {
2065 // convert <pyobject> to C++ void*&, set arg for call
2066  CPPInstance* pyobj = GetCppInstance(pyobject);
2067  if (pyobj) {
2068  para.fValue.fVoidp = &pyobj->GetObjectRaw();
2069  para.fTypeCode = 'V';
2070  return true;
2071  }
2072 
2073  return false;
2074 }
2075 
2076 //----------------------------------------------------------------------------
2077 bool CPyCppyy::VoidPtrPtrConverter::SetArg(
2078  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
2079 {
2080 // convert <pyobject> to C++ void**, set arg for call
2081  CPPInstance* pyobj = GetCppInstance(pyobject);
2082  if (pyobj) {
2083  // this is a C++ object, take and set its address
2084  para.fValue.fVoidp = &pyobj->GetObjectRaw();
2085  para.fTypeCode = 'p';
2086  return true;
2087  } else if (IsPyCArgObject(pyobject)) {
2088  CPyCppyy_tagPyCArgObject* carg = (CPyCppyy_tagPyCArgObject*)pyobject;
2089  if (carg->obj) {
2090  para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)carg->obj)->b_ptr;
2091  para.fTypeCode = 'p';
2092  return true;
2093  }
2094  }
2095 
2096 // buffer objects are allowed under "user knows best" (this includes the buffer
2097 // interface to ctypes.c_void_p, which results in a void**)
2098  Py_ssize_t buflen = Utility::GetBuffer(pyobject, '*', 1, para.fValue.fVoidp, false);
2099 
2100 // ok if buffer exists (can't perform any useful size checks)
2101  if (para.fValue.fVoidp && buflen != 0) {
2102  para.fTypeCode = 'p';
2103  return true;
2104  }
2105 
2106  return false;
2107 }
2108 
2109 //----------------------------------------------------------------------------
2110 PyObject* CPyCppyy::VoidPtrPtrConverter::FromMemory(void* address)
2111 {
2112 // read a void** from address; since this is unknown, long is used (user can cast)
2113  if (!address || *(ptrdiff_t*)address == 0) {
2114  Py_INCREF(gNullPtrObject);
2115  return gNullPtrObject;
2116  }
2117  return CreatePointerView(*(ptrdiff_t**)address, fSize);
2118 }
2119 
2120 //----------------------------------------------------------------------------
2121 bool CPyCppyy::PyObjectConverter::SetArg(
2122  PyObject* pyobject, Parameter& para, CallContext* /* ctxt */)
2123 {
2124 // by definition: set and declare success
2125  para.fValue.fVoidp = pyobject;
2126  para.fTypeCode = 'p';
2127  return true;
2128 }
2129 
2130 PyObject* CPyCppyy::PyObjectConverter::FromMemory(void* address)
2131 {
2132 // construct python object from C++ PyObject* read at <address>
2133  PyObject* pyobject = *((PyObject**)address);
2134 
2135  if (!pyobject) {
2137  }
2138 
2139  Py_INCREF(pyobject);
2140  return pyobject;
2141 }
2142 
2143 bool CPyCppyy::PyObjectConverter::ToMemory(PyObject* value, void* address)
2144 {
2145 // no conversion needed, write <value> at <address>
2146  Py_INCREF(value);
2147  Py_XDECREF(*((PyObject**)address));
2148  *((PyObject**)address) = value;
2149  return true;
2150 }
2151 
2152 
2153 //- function pointer converter -----------------------------------------------
2154 static unsigned int sWrapperCounter = 0;
2155 // cache mapping signature/return type to python callable and corresponding wrapper
2156 typedef std::pair<std::string, std::string> RetSigKey_t;
2157 static std::map<RetSigKey_t, std::vector<void*>> sWrapperFree;
2158 static std::map<RetSigKey_t, std::map<PyObject*, void*>> sWrapperLookup;
2159 static std::map<PyObject*, std::pair<void*, RetSigKey_t>> sWrapperWeakRefs;
2160 static std::map<void*, PyObject**> sWrapperReference;
2161 
2163 {
2164  auto ipos = sWrapperWeakRefs.find(pyref);
2165  if (ipos != sWrapperWeakRefs.end()) {
2166  // disable this callback and store for possible re-use
2167  void* wpraddress = ipos->second.first;
2168  *sWrapperReference[wpraddress] = nullptr;
2169  sWrapperFree[ipos->second.second].push_back(wpraddress);
2170  }
2171 
2173 }
2174 static PyMethodDef gWrapperCacheEraserMethodDef = {
2175  const_cast<char*>("interal_WrapperCacheEraser"),
2176  (PyCFunction)WrapperCacheEraser,
2177  METH_O, nullptr
2178 };
2179 
2180 static void* PyFunction_AsCPointer(PyObject* pyobject,
2181  const std::string& rettype, const std::string& signature)
2182 {
2183 // Convert a bound C++ function pointer or callable python object to a C-style
2184 // function pointer. The former is direct, the latter involves a JIT-ed wrapper.
2185  static PyObject* sWrapperCacheEraser = PyCFunction_New(&gWrapperCacheEraserMethodDef, nullptr);
2186 
2187  using namespace CPyCppyy;
2188 
2189  if (CPPOverload_Check(pyobject)) {
2190  CPPOverload* ol = (CPPOverload*)pyobject;
2191  if (!ol->fMethodInfo || ol->fMethodInfo->fMethods.empty())
2192  return nullptr;
2193 
2194  // find the overload with matching signature
2195  for (auto& m : ol->fMethodInfo->fMethods) {
2196  PyObject* sig = m->GetSignature(false);
2197  bool found = signature == CPyCppyy_PyText_AsString(sig);
2198  Py_DECREF(sig);
2199  if (found) {
2200  void* fptr = (void*)m->GetFunctionAddress();
2201  if (fptr) return fptr;
2202  break; // fall-through, with calling through Python
2203  }
2204  }
2205  }
2206 
2207  if (TemplateProxy_Check(pyobject)) {
2208  // get the actual underlying template matching the signature
2209  TemplateProxy* pytmpl = (TemplateProxy*)pyobject;
2210  std::string fullname = CPyCppyy_PyText_AsString(pytmpl->fTI->fCppName);
2211  if (pytmpl->fTemplateArgs)
2212  fullname += CPyCppyy_PyText_AsString(pytmpl->fTemplateArgs);
2213  Cppyy::TCppScope_t scope = ((CPPClass*)pytmpl->fTI->fPyClass)->fCppType;
2214  Cppyy::TCppMethod_t cppmeth = Cppyy::GetMethodTemplate(scope, fullname, signature);
2215  if (cppmeth) {
2216  void* fptr = (void*)Cppyy::GetFunctionAddress(cppmeth, false);
2217  if (fptr) return fptr;
2218  }
2219  // fall-through, with calling through Python
2220  }
2221 
2222  if (PyCallable_Check(pyobject)) {
2223  // generic python callable: create a C++ wrapper function
2224  void* wpraddress = nullptr;
2225 
2226  // re-use existing wrapper if possible
2227  auto key = std::make_pair(rettype, signature);
2228  const auto& lookup = sWrapperLookup.find(key);
2229  if (lookup != sWrapperLookup.end()) {
2230  const auto& existing = lookup->second.find(pyobject);
2231  if (existing != lookup->second.end() && *sWrapperReference[existing->second] == pyobject)
2232  wpraddress = existing->second;
2233  }
2234 
2235  // check for a pre-existing, unused, wrapper if not found
2236  if (!wpraddress) {
2237  const auto& freewrap = sWrapperFree.find(key);
2238  if (freewrap != sWrapperFree.end() && !freewrap->second.empty()) {
2239  wpraddress = freewrap->second.back();
2240  freewrap->second.pop_back();
2241  *sWrapperReference[wpraddress] = pyobject;
2242  PyObject* wref = PyWeakref_NewRef(pyobject, sWrapperCacheEraser);
2243  if (wref) sWrapperWeakRefs[wref] = std::make_pair(wpraddress, key);
2244  else PyErr_Clear(); // happens for builtins which don't need this
2245  }
2246  }
2247 
2248  // create wrapper if no re-use possible
2249  if (!wpraddress) {
2250  if (!Utility::IncludePython())
2251  return nullptr;
2252 
2253  // extract argument types
2254  const std::vector<std::string>& argtypes = TypeManip::extract_arg_types(signature);
2255  int nArgs = (int)argtypes.size();
2256 
2257  // wrapper name
2258  std::ostringstream wname;
2259  wname << "fptr_wrap" << ++sWrapperCounter;
2260 
2261  // build wrapper function code
2262  std::ostringstream code;
2263  code << "namespace __cppyy_internal {\n "
2264  << rettype << " " << wname.str() << "(";
2265  for (int i = 0; i < nArgs; ++i) {
2266  code << argtypes[i] << " arg" << i;
2267  if (i != nArgs-1) code << ", ";
2268  }
2269  code << ") {\n";
2270 
2271  // start function body
2272  Utility::ConstructCallbackPreamble(rettype, argtypes, code);
2273 
2274  // create a referencable pointer
2275  PyObject** ref = new PyObject*{pyobject};
2276 
2277  // function call itself and cleanup
2278  code << " PyObject** ref = (PyObject**)" << (intptr_t)ref << ";\n"
2279  " PyObject* pyresult = nullptr;\n"
2280  " if (*ref) pyresult = PyObject_CallFunctionObjArgs(*ref";
2281  for (int i = 0; i < nArgs; ++i)
2282  code << ", pyargs[" << i << "]";
2283  code << ", NULL);\n"
2284  " else PyErr_SetString(PyExc_TypeError, \"callable was deleted\");\n";
2285 
2286  // close
2287  Utility::ConstructCallbackReturn(rettype, nArgs, code);
2288 
2289  // end of namespace
2290  code << "}";
2291 
2292  // finally, compile the code
2293  if (!Cppyy::Compile(code.str()))
2294  return nullptr;
2295 
2296  // TODO: is there no easier way?
2297  static Cppyy::TCppScope_t scope = Cppyy::GetScope("__cppyy_internal");
2298  const auto& idx = Cppyy::GetMethodIndicesFromName(scope, wname.str());
2299  wpraddress = Cppyy::GetFunctionAddress(Cppyy::GetMethod(scope, idx[0]), false);
2300  sWrapperReference[wpraddress] = ref;
2301 
2302  // cache the new wrapper
2303  sWrapperLookup[key][pyobject] = wpraddress;
2304  PyObject* wref = PyWeakref_NewRef(pyobject, sWrapperCacheEraser);
2305  if (wref) sWrapperWeakRefs[wref] = std::make_pair(wpraddress, key);
2306  else PyErr_Clear(); // happens for builtins which don't need this
2307  }
2308 
2309  // now pass the pointer to the wrapper function (may be null)
2310  return wpraddress;
2311  }
2312 
2313  return nullptr;
2314 }
2315 
2316 bool CPyCppyy::FunctionPointerConverter::SetArg(
2317  PyObject* pyobject, Parameter& para, CallContext* /*ctxt*/)
2318 {
2319 // special case: allow nullptr singleton:
2320  if (gNullPtrObject == pyobject) {
2321  para.fValue.fVoidp = nullptr;
2322  para.fTypeCode = 'p';
2323  return true;
2324  }
2325 
2326 // normal case, get a function pointer
2327  void* fptr = PyFunction_AsCPointer(pyobject, fRetType, fSignature);
2328  if (fptr) {
2329  para.fValue.fVoidp = fptr;
2330  para.fTypeCode = 'p';
2331  return true;
2332  }
2333 
2334  return false;
2335 }
2336 
2337 static std::map<void*, std::string> sFuncWrapperLookup;
2338 static const char* FPCFM_ERRMSG = "conversion to std::function failed";
2339 PyObject* CPyCppyy::FunctionPointerConverter::FromMemory(void* address)
2340 {
2341 // A function pointer in clang is represented by a Type, not a FunctionDecl and it's
2342 // not possible to get the latter from the former: the backend will need to support
2343 // both. Since that is far in the future, we'll use a std::function instead.
2344  static int func_count = 0;
2345 
2346  if (!(address && *(void**)address)) {
2347  PyErr_SetString(PyExc_TypeError, FPCFM_ERRMSG);
2348  return nullptr;
2349  }
2350 
2351  void* faddr = *(void**)address;
2352  auto cached = sFuncWrapperLookup.find(faddr);
2353  if (cached == sFuncWrapperLookup.end()) {
2354  std::ostringstream fname;
2355  fname << "ptr2func" << ++func_count;
2356 
2357  std::ostringstream code;
2358  code << "namespace __cppyy_internal {\n std::function<"
2359  << fRetType << fSignature << "> " << fname.str()
2360  << " = (" << fRetType << "(*)" << fSignature << ")" << (intptr_t)faddr
2361  << ";\n}";
2362 
2363  if (!Cppyy::Compile(code.str())) {
2364  PyErr_SetString(PyExc_TypeError, FPCFM_ERRMSG);
2365  return nullptr;
2366  }
2367 
2368  // cache the new wrapper (TODO: does it make sense to use weakrefs on the data
2369  // member?)
2370  sFuncWrapperLookup[faddr] = fname.str();
2371  cached = sFuncWrapperLookup.find(faddr);
2372  }
2373 
2374  static Cppyy::TCppScope_t scope = Cppyy::GetScope("__cppyy_internal");
2375  PyObject* pyscope = CreateScopeProxy(scope);
2376  PyObject* func = PyObject_GetAttrString(pyscope, cached->second.c_str());
2377  Py_DECREF(pyscope);
2378 
2379  return func;
2380 }
2381 
2382 bool CPyCppyy::FunctionPointerConverter::ToMemory(PyObject* pyobject, void* address)
2383 {
2384 // special case: allow nullptr singleton:
2385  if (gNullPtrObject == pyobject) {
2386  *((void**)address) = nullptr;
2387  return true;
2388  }
2389 
2390 // normal case, get a function pointer
2391  void* fptr = PyFunction_AsCPointer(pyobject, fRetType, fSignature);
2392  if (fptr) {
2393  *((void**)address) = fptr;
2394  return true;
2395  }
2396 
2397  return false;
2398 }
2399 
2400 
2401 //- std::function converter --------------------------------------------------
2402 bool CPyCppyy::StdFunctionConverter::SetArg(
2403  PyObject* pyobject, Parameter& para, CallContext* ctxt)
2404 {
2405 // prefer normal "object" conversion
2406  bool rf = ctxt->fFlags & CallContext::kNoImplicit;
2408  if (fConverter->SetArg(pyobject, para, ctxt)) {
2409  if (!rf) ctxt->fFlags &= ~CallContext::kNoImplicit;
2410  return true;
2411  }
2412 
2413  PyErr_Clear();
2414 
2415 // else create a wrapper function
2416  if (this->FunctionPointerConverter::SetArg(pyobject, para, ctxt)) {
2417  // retrieve the wrapper pointer and capture it in a temporary std::function,
2418  // then try normal conversion a second time
2419  PyObject* func = this->FunctionPointerConverter::FromMemory(&para.fValue.fVoidp);
2420  if (func) {
2421  Py_XDECREF(fFuncWrap); fFuncWrap = func;
2422  bool result = fConverter->SetArg(fFuncWrap, para, ctxt);
2423  if (!rf) ctxt->fFlags &= ~CallContext::kNoImplicit;
2424  return result;
2425  }
2426  }
2427 
2428  if (!rf) ctxt->fFlags &= ~CallContext::kNoImplicit;
2429  return false;
2430 }
2431 
2432 PyObject* CPyCppyy::StdFunctionConverter::FromMemory(void* address)
2433 {
2434  return fConverter->FromMemory(address);
2435 }
2436 
2437 bool CPyCppyy::StdFunctionConverter::ToMemory(PyObject* value, void* address)
2438 {
2439  return fConverter->ToMemory(value, address);
2440 }
2441 
2442 
2443 //- smart pointer converters -------------------------------------------------
2444 bool CPyCppyy::SmartPtrConverter::SetArg(
2445  PyObject* pyobject, Parameter& para, CallContext* ctxt)
2446 {
2447  char typeCode = fIsRef ? 'p' : 'V';
2448 
2449  if (!CPPInstance_Check(pyobject)) {
2450  // TODO: not sure how this is correct for pass-by-ref nor does it help with
2451  // implicit conversions for pass-by-value
2452  if (fIsRef && GetAddressSpecialCase(pyobject, para.fValue.fVoidp)) {
2453  para.fTypeCode = typeCode; // allow special cases such as nullptr
2454  return true;
2455  }
2456 
2457  return false;
2458  }
2459 
2460  CPPInstance* pyobj = (CPPInstance*)pyobject;
2461 
2462 // for the case where we have a 'hidden' smart pointer:
2463  if (Cppyy::TCppType_t tsmart = pyobj->GetSmartIsA()) {
2464  if (Cppyy::IsSubtype(tsmart, fSmartPtrType)) {
2465  // depending on memory policy, some objects need releasing when passed into functions
2466  if (fKeepControl && !UseStrictOwnership(ctxt))
2467  ((CPPInstance*)pyobject)->CppOwns();
2468 
2469  // calculate offset between formal and actual arguments
2470  para.fValue.fVoidp = pyobj->GetSmartObject();
2471  if (tsmart != fSmartPtrType) {
2473  tsmart, fSmartPtrType, para.fValue.fVoidp, 1 /* up-cast */);
2474  }
2475 
2476  // set pointer (may be null) and declare success
2477  para.fTypeCode = typeCode;
2478  return true;
2479  }
2480  }
2481 
2482 // for the case where we have an 'exposed' smart pointer:
2483  if (!pyobj->IsSmart() && Cppyy::IsSubtype(pyobj->ObjectIsA(), fSmartPtrType)) {
2484  // calculate offset between formal and actual arguments
2485  para.fValue.fVoidp = pyobj->GetObject();
2486  if (pyobj->ObjectIsA() != fSmartPtrType) {
2488  pyobj->ObjectIsA(), fSmartPtrType, para.fValue.fVoidp, 1 /* up-cast */);
2489  }
2490 
2491  // set pointer (may be null) and declare success
2492  para.fTypeCode = typeCode;
2493  return true;
2494  }
2495 
2496 // final option, try mapping pointer types held (TODO: do not allow for non-const ref)
2497  if (pyobj->IsSmart() && Cppyy::IsSubtype(pyobj->ObjectIsA(), fUnderlyingType)) {
2498  para.fValue.fVoidp = ((CPPInstance*)pyobject)->GetSmartObject();
2499  para.fTypeCode = 'V';
2500  return true;
2501  }
2502 
2503  return false;
2504 }
2505 
2506 PyObject* CPyCppyy::SmartPtrConverter::FromMemory(void* address)
2507 {
2508  if (!address || !fSmartPtrType)
2509  return nullptr;
2510 
2511  return BindCppObjectNoCast(address, fSmartPtrType);
2512 }
2513 
2514 
2515 //----------------------------------------------------------------------------
2516 namespace {
2517 
2518 // clang libcpp and gcc use the same structure (ptr, size)
2519 #if defined (_LIBCPP_INITIALIZER_LIST) || defined(__GNUC__)
2520 struct faux_initlist
2521 {
2522  typedef size_t size_type;
2523  typedef void* iterator;
2524  iterator _M_array;
2525  size_type _M_len;
2526 };
2527 #elif defined (_MSC_VER)
2528 struct faux_initlist
2529 {
2530  typedef char* iterator;
2531  iterator _M_array; // ie. _First;
2532  iterator _Last;
2533 };
2534 #else
2535 #define NO_KNOWN_INITIALIZER_LIST 1
2536 #endif
2537 
2538 } // unnamed namespace
2539 
2540 CPyCppyy::InitializerListConverter::~InitializerListConverter()
2541 {
2542  if (fConverter && fConverter->HasState()) delete fConverter;
2543 }
2544 
2545 bool CPyCppyy::InitializerListConverter::SetArg(
2546  PyObject* pyobject, Parameter& para, CallContext* /*ctxt*/)
2547 {
2548 #ifdef NO_KNOWN_INITIALIZER_LIST
2549  return false;
2550 #else
2551 // convert the given argument to an initializer list temporary; this is purely meant
2552 // to be a syntactic thing, so only _python_ sequences are allowed; bound C++ proxies
2553 // are therefore rejected (should go through eg. a copy constructor etc.)
2554  if (CPPInstance_Check(pyobject) || !PySequence_Check(pyobject) || CPyCppyy_PyText_Check(pyobject)
2555 #if PY_VERSION_HEX >= 0x03000000
2556  || PyBytes_Check(pyobject)
2557 #endif
2558  )
2559  return false;
2560 
2561  void* buf;
2562  Py_ssize_t buflen = Utility::GetBuffer(pyobject, '*', (int)fValueSize, buf, true);
2563  faux_initlist* fake = nullptr;
2564  if (buf && buflen) {
2565  // dealing with an array here, pass on whole-sale
2566  fake = (faux_initlist*)malloc(sizeof(faux_initlist));
2567  fake->_M_array = (faux_initlist::iterator)buf;
2568 #if defined (_LIBCPP_INITIALIZER_LIST) || defined(__GNUC__)
2569  fake->_M_len = (faux_initlist::size_type)buflen;
2570 #elif defined (_MSC_VER)
2571  fake->_Last = fake->_M_array+buflen*fValueSize;
2572 #endif
2573  } else {
2574  // can only construct empty lists, so use a fake initializer list
2575  size_t len = (size_t)PySequence_Size(pyobject);
2576  fake = (faux_initlist*)malloc(sizeof(faux_initlist)+fValueSize*len);
2577  fake->_M_array = (faux_initlist::iterator)((char*)fake+sizeof(faux_initlist));
2578 #if defined (_LIBCPP_INITIALIZER_LIST) || defined(__GNUC__)
2579  fake->_M_len = (faux_initlist::size_type)len;
2580  for (faux_initlist::size_type i = 0; i < fake->_M_len; ++i) {
2581 #elif defined (_MSC_VER)
2582  fake->_Last = fake->_M_array+len*fValueSize;
2583  for (size_t i = 0; (fake->_M_array+i*fValueSize) != fake->_Last; ++i) {
2584 #endif
2585  PyObject* item = PySequence_GetItem(pyobject, i);
2586  bool convert_ok = false;
2587  if (item) {
2588  if (!fConverter) {
2589  if (CPPInstance_Check(item)) {
2590  // by convention, use byte copy
2591  memcpy((char*)fake->_M_array + i*fValueSize,
2592  ((CPPInstance*)item)->GetObject(), fValueSize);
2593  convert_ok = true;
2594  }
2595  } else
2596  convert_ok = fConverter->ToMemory(item, (char*)fake->_M_array + i*fValueSize);
2597 
2598  Py_DECREF(item);
2599  } else
2600  PyErr_Format(PyExc_TypeError, "failed to get item %d from sequence", (int)i);
2601 
2602  if (!convert_ok) {
2603  free((void*)fake);
2604  return false;
2605  }
2606  }
2607  }
2608 
2609  para.fValue.fVoidp = (void*)fake;
2610  para.fTypeCode = 'X'; // means ptr that backend has to free after call
2611  return true;
2612 #endif
2613 }
2614 
2615 //----------------------------------------------------------------------------
2616 bool CPyCppyy::NotImplementedConverter::SetArg(PyObject*, Parameter&, CallContext*)
2617 {
2618 // raise a NotImplemented exception to take a method out of overload resolution
2619  PyErr_SetString(PyExc_NotImplementedError, "this method cannot (yet) be called");
2620  return false;
2621 }
2622 
2623 
2624 //- helper to refactor some code from CreateConverter ------------------------
2626  Cppyy::TCppScope_t klass, const std::string& cpd, long size, dims_t dims, bool isConst, bool control)
2627 {
2628  using namespace CPyCppyy;
2629  Converter* result = nullptr;
2630 
2631  if (cpd == "**" || cpd == "*[]" || cpd == "&*")
2632  result = new InstancePtrPtrConverter<false>(klass, control);
2633  else if (cpd == "*&")
2634  result = new InstancePtrPtrConverter<true>(klass, control);
2635  else if (cpd == "*" && size <= 0)
2636  result = new InstancePtrConverter(klass, control);
2637  else if (cpd == "&")
2638  result = new InstanceRefConverter(klass, isConst);
2639  else if (cpd == "&&")
2640  result = new InstanceMoveConverter(klass);
2641  else if (cpd == "[]" || size > 0)
2642  result = new InstanceArrayConverter(klass, dims, false);
2643  else if (cpd == "") // by value
2644  result = new InstanceConverter(klass, true);
2645 
2646  return result;
2647 }
2648 
2649 //- factories ----------------------------------------------------------------
2651 CPyCppyy::Converter* CPyCppyy::CreateConverter(const std::string& fullType, dims_t dims)
2652 {
2653 // The matching of the fulltype to a converter factory goes through up to five levels:
2654 // 1) full, exact match
2655 // 2) match of decorated, unqualified type
2656 // 3) accept const ref as by value
2657 // 4) accept ref as pointer
2658 // 5) generalized cases (covers basically all C++ classes)
2659 //
2660 // If all fails, void is used, which will generate a run-time warning when used.
2661 
2662  dim_t size = (dims && dims[0] != -1) ? dims[1] : -1;
2663 
2664 // an exactly matching converter is best
2665  ConvFactories_t::iterator h = gConvFactories.find(fullType);
2666  if (h != gConvFactories.end())
2667  return (h->second)(dims);
2668 
2669 // resolve typedefs etc.
2670  const std::string& resolvedType = Cppyy::ResolveName(fullType);
2671 
2672 // a full, qualified matching converter is preferred
2673  if (resolvedType != fullType) {
2674  h = gConvFactories.find(resolvedType);
2675  if (h != gConvFactories.end())
2676  return (h->second)(dims);
2677  }
2678 
2679 //-- nothing? ok, collect information about the type and possible qualifiers/decorators
2680  bool isConst = strncmp(resolvedType.c_str(), "const", 5) == 0;
2681  const std::string& cpd = Utility::Compound(resolvedType);
2682  std::string realType = TypeManip::clean_type(resolvedType, false, true);
2683 
2684 // accept unqualified type (as python does not know about qualifiers)
2685  h = gConvFactories.find(realType + cpd);
2686  if (h != gConvFactories.end())
2687  return (h->second)(dims);
2688 
2689 // drop const, as that is mostly meaningless to python (with the exception
2690 // of c-strings, but those are specialized in the converter map)
2691  if (isConst) {
2692  realType = TypeManip::remove_const(realType);
2693  h = gConvFactories.find(realType + cpd);
2694  if (h != gConvFactories.end())
2695  return (h->second)(dims);
2696  }
2697 
2698 //-- still nothing? try pointer instead of array (for builtins)
2699  if (cpd == "[]") {
2700  // simple array
2701  h = gConvFactories.find(realType + "*");
2702  if (h != gConvFactories.end()) {
2703  if (dims && dims[1] == UNKNOWN_SIZE) dims[1] = UNKNOWN_ARRAY_SIZE;
2704  return (h->second)(dims);
2705  }
2706  } else if (cpd == "*[]") {
2707  // array of pointers
2708  h = gConvFactories.find(realType + "*");
2709  if (h != gConvFactories.end()) {
2710  // upstream treats the pointer type as the array element type, but that pointer is
2711  // treated as a low-level view as well, so adjust the dims
2712  dim_t newdim = (dims && 0 < dims[0]) ? dims[0]+1 : 2;
2713  dims_t newdims = new dim_t[newdim+1];
2714  newdims[0] = newdim;
2715  newdims[1] = (0 < size ? size : UNKNOWN_ARRAY_SIZE); // the array
2716  newdims[2] = UNKNOWN_SIZE; // the pointer
2717  if (dims && 2 < newdim) {
2718  for (int i = 2; i < (newdim-1); ++i)
2719  newdims[i+1] = dims[i];
2720  }
2721  Converter* cnv = (h->second)(newdims);
2722  delete [] newdims;
2723  return cnv;
2724  }
2725  }
2726 
2727 //-- special case: initializer list
2728  if (realType.compare(0, 16, "initializer_list") == 0) {
2729  // get the type of the list and create a converter (TODO: get hold of value_type?)
2730  auto pos = realType.find('<');
2731  std::string value_type = realType.substr(pos+1, realType.size()-pos-2);
2732  Converter* cnv = nullptr; bool use_byte_cnv = false;
2733  if (cpd == "" && Cppyy::GetScope(value_type)) {
2734  // initializer list of object values does not work as the target is raw
2735  // memory; simply use byte copies
2736 
2737  // by convention, leave cnv as nullptr
2738  use_byte_cnv = true;
2739  } else
2740  cnv = CreateConverter(value_type);
2741  if (cnv || use_byte_cnv)
2742  return new InitializerListConverter(cnv, Cppyy::SizeOf(value_type));
2743  }
2744 
2745 //-- still nothing? use a generalized converter
2746  bool control = cpd == "&" || isConst;
2747 
2748 //-- special case: std::function
2749  auto pos = resolvedType.find("function<");
2750  if (pos == 0 /* no std:: */ || pos == 5 /* with std:: */ ||
2751  pos == 6 /* const no std:: */ || pos == 11 /* const with std:: */ ) {
2752 
2753  // get actual converter for normal passing
2755  Cppyy::GetScope(realType), cpd, size, dims, isConst, control);
2756 
2757  if (cnv) {
2758  // get the type of the underlying (TODO: use target_type?)
2759  auto pos1 = resolvedType.find("(", pos+9);
2760  auto pos2 = resolvedType.rfind(")");
2761  if (pos1 != std::string::npos && pos2 != std::string::npos) {
2762  auto sz1 = pos1-pos-9;
2763  if (resolvedType[pos+9+sz1-1] == ' ') sz1 -= 1;
2764 
2765  return new StdFunctionConverter(cnv,
2766  resolvedType.substr(pos+9, sz1), resolvedType.substr(pos1, pos2-pos1+1));
2767  }
2768  }
2769  }
2770 
2771 // converters for known C++ classes and default (void*)
2772  Converter* result = nullptr;
2773  if (Cppyy::TCppScope_t klass = Cppyy::GetScope(realType)) {
2774  Cppyy::TCppType_t raw{0};
2775  if (Cppyy::GetSmartPtrInfo(realType, &raw, nullptr)) {
2776  if (cpd == "") {
2777  result = new SmartPtrConverter(klass, raw, control);
2778  } else if (cpd == "&") {
2779  result = new SmartPtrConverter(klass, raw);
2780  } else if (cpd == "*" && size <= 0) {
2781  result = new SmartPtrConverter(klass, raw, control, true);
2782  }
2783  }
2784 
2785  if (!result) {
2786  // CLING WORKAROUND -- special case for STL iterators
2787  if (realType.rfind("__gnu_cxx::__normal_iterator", 0) /* vector */ == 0
2788 #ifdef __APPLE__
2789  || realType.rfind("__wrap_iter", 0) == 0
2790 #endif
2791  // TODO: Windows?
2792  ) {
2793  static STLIteratorConverter c;
2794  result = &c;
2795  } else
2796  // -- CLING WORKAROUND
2797  result = selectInstanceCnv(klass, cpd, size, dims, isConst, control);
2798  }
2799  } else if (resolvedType.find("(*)") != std::string::npos ||
2800  (resolvedType.find("::*)") != std::string::npos)) {
2801  // this is a function function pointer
2802  // TODO: find better way of finding the type
2803  auto pos1 = resolvedType.find('(');
2804  auto pos2 = resolvedType.find("*)");
2805  auto pos3 = resolvedType.rfind(')');
2806  result = new FunctionPointerConverter(
2807  resolvedType.substr(0, pos1), resolvedType.substr(pos2+2, pos3-pos2-1));
2808  }
2809 
2810  if (!result && cpd == "&&") {
2811  // for builtin, can use const-ref for r-ref
2812  h = gConvFactories.find("const " + realType + "&");
2813  if (h != gConvFactories.end())
2814  return (h->second)(dims);
2815  // else, unhandled moves
2816  result = new NotImplementedConverter();
2817  }
2818 
2819  if (!result && h != gConvFactories.end())
2820  // converter factory available, use it to create converter
2821  result = (h->second)(dims);
2822  else if (!result) {
2823  // default to something reasonable, assuming "user knows best"
2824  if (cpd.size() == 2 && cpd != "&&") // "**", "*[]", "*&"
2825  result = new VoidPtrPtrConverter(size);
2826  else if (!cpd.empty())
2827  result = new VoidArrayConverter(); // "user knows best"
2828  else
2829  result = new NotImplementedConverter(); // fails on use
2830  }
2831 
2832  return result;
2833 }
2834 
2835 //----------------------------------------------------------------------------
2838 {
2839  if (p && p->HasState())
2840  delete p; // state-less converters are always shared
2841 }
2842 
2843 //----------------------------------------------------------------------------
2845 bool CPyCppyy::RegisterConverter(const std::string& name, cf_t fac)
2846 {
2847 // register a custom converter
2848  auto f = gConvFactories.find(name);
2849  if (f != gConvFactories.end())
2850  return false;
2851 
2852  gConvFactories[name] = fac;
2853  return true;
2854 }
2855 
2856 //----------------------------------------------------------------------------
2858 bool CPyCppyy::UnregisterConverter(const std::string& name)
2859 {
2860 // remove a custom converter
2861  auto f = gConvFactories.find(name);
2862  if (f != gConvFactories.end()) {
2863  gConvFactories.erase(f);
2864  return true;
2865  }
2866  return false;
2867 }
2868 
2869 
2870 //----------------------------------------------------------------------------
2871 namespace {
2872 
2873 using namespace CPyCppyy;
2874 
2875 #define STRINGVIEW "basic_string_view<char,char_traits<char> >"
2876 #define WSTRING "basic_string<wchar_t,char_traits<wchar_t>,allocator<wchar_t> >"
2877 
2878 static struct InitConvFactories_t {
2879 public:
2880  InitConvFactories_t() {
2881  // load all converter factories in the global map 'gConvFactories'
2883 
2884  // factories for built-ins
2885  gf["bool"] = (cf_t)+[](dims_t) { static BoolConverter c{}; return &c; };
2886  gf["const bool&"] = (cf_t)+[](dims_t) { static ConstBoolRefConverter c{}; return &c; };
2887  gf["bool&"] = (cf_t)+[](dims_t) { static BoolRefConverter c{}; return &c; };
2888  gf["char"] = (cf_t)+[](dims_t) { static CharConverter c{}; return &c; };
2889  gf["const char&"] = (cf_t)+[](dims_t) { static ConstCharRefConverter c{}; return &c; };
2890  gf["char&"] = (cf_t)+[](dims_t) { static CharRefConverter c{}; return &c; };
2891  gf["signed char&"] = (cf_t)+[](dims_t) { static SCharRefConverter c{}; return &c; };
2892  gf["unsigned char"] = (cf_t)+[](dims_t) { static UCharConverter c{}; return &c; };
2893  gf["const unsigned char&"] = (cf_t)+[](dims_t) { static ConstUCharRefConverter c{}; return &c; };
2894  gf["unsigned char&"] = (cf_t)+[](dims_t) { static UCharRefConverter c{}; return &c; };
2895  gf["UCharAsInt"] = (cf_t)+[](dims_t) { static UCharAsIntConverter c{}; return &c; };
2896  gf["wchar_t"] = (cf_t)+[](dims_t) { static WCharConverter c{}; return &c; };
2897  gf["char16_t"] = (cf_t)+[](dims_t) { static Char16Converter c{}; return &c; };
2898  gf["char32_t"] = (cf_t)+[](dims_t) { static Char32Converter c{}; return &c; };
2899  gf["wchar_t&"] = (cf_t)+[](dims_t) { static WCharRefConverter c{}; return &c; };
2900  gf["char16_t&"] = (cf_t)+[](dims_t) { static Char16RefConverter c{}; return &c; };
2901  gf["char32_t&"] = (cf_t)+[](dims_t) { static Char32RefConverter c{}; return &c; };
2902  gf["int8_t"] = (cf_t)+[](dims_t) { static Int8Converter c{}; return &c; };
2903  gf["int8_t&"] = (cf_t)+[](dims_t) { static Int8RefConverter c{}; return &c; };
2904  gf["const int8_t&"] = (cf_t)+[](dims_t) { static ConstInt8RefConverter c{}; return &c; };
2905  gf["uint8_t"] = (cf_t)+[](dims_t) { static UInt8Converter c{}; return &c; };
2906  gf["const uint8_t&"] = (cf_t)+[](dims_t) { static ConstUInt8RefConverter c{}; return &c; };
2907  gf["uint8_t&"] = (cf_t)+[](dims_t) { static UInt8RefConverter c{}; return &c; };
2908  gf["short"] = (cf_t)+[](dims_t) { static ShortConverter c{}; return &c; };
2909  gf["const short&"] = (cf_t)+[](dims_t) { static ConstShortRefConverter c{}; return &c; };
2910  gf["short&"] = (cf_t)+[](dims_t) { static ShortRefConverter c{}; return &c; };
2911  gf["unsigned short"] = (cf_t)+[](dims_t) { static UShortConverter c{}; return &c; };
2912  gf["const unsigned short&"] = (cf_t)+[](dims_t) { static ConstUShortRefConverter c{}; return &c; };
2913  gf["unsigned short&"] = (cf_t)+[](dims_t) { static UShortRefConverter c{}; return &c; };
2914  gf["int"] = (cf_t)+[](dims_t) { static IntConverter c{}; return &c; };
2915  gf["int&"] = (cf_t)+[](dims_t) { static IntRefConverter c{}; return &c; };
2916  gf["const int&"] = (cf_t)+[](dims_t) { static ConstIntRefConverter c{}; return &c; };
2917  gf["unsigned int"] = (cf_t)+[](dims_t) { static UIntConverter c{}; return &c; };
2918  gf["const unsigned int&"] = (cf_t)+[](dims_t) { static ConstUIntRefConverter c{}; return &c; };
2919  gf["unsigned int&"] = (cf_t)+[](dims_t) { static UIntRefConverter c{}; return &c; };
2920  gf["long"] = (cf_t)+[](dims_t) { static LongConverter c{}; return &c; };
2921  gf["long&"] = (cf_t)+[](dims_t) { static LongRefConverter c{}; return &c; };
2922  gf["const long&"] = (cf_t)+[](dims_t) { static ConstLongRefConverter c{}; return &c; };
2923  gf["unsigned long"] = (cf_t)+[](dims_t) { static ULongConverter c{}; return &c; };
2924  gf["const unsigned long&"] = (cf_t)+[](dims_t) { static ConstULongRefConverter c{}; return &c; };
2925  gf["unsigned long&"] = (cf_t)+[](dims_t) { static ULongRefConverter c{}; return &c; };
2926  gf["long long"] = (cf_t)+[](dims_t) { static LLongConverter c{}; return &c; };
2927  gf["const long long&"] = (cf_t)+[](dims_t) { static ConstLLongRefConverter c{}; return &c; };
2928  gf["long long&"] = (cf_t)+[](dims_t) { static LLongRefConverter c{}; return &c; };
2929  gf["unsigned long long"] = (cf_t)+[](dims_t) { static ULLongConverter c{}; return &c; };
2930  gf["const unsigned long long&"] = (cf_t)+[](dims_t) { static ConstULLongRefConverter c{}; return &c; };
2931  gf["unsigned long long&"] = (cf_t)+[](dims_t) { static ULLongRefConverter c{}; return &c; };
2932 
2933  gf["float"] = (cf_t)+[](dims_t) { static FloatConverter c{}; return &c; };
2934  gf["const float&"] = (cf_t)+[](dims_t) { static ConstFloatRefConverter c{}; return &c; };
2935  gf["float&"] = (cf_t)+[](dims_t) { static FloatRefConverter c{}; return &c; };
2936  gf["double"] = (cf_t)+[](dims_t) { static DoubleConverter c{}; return &c; };
2937  gf["double&"] = (cf_t)+[](dims_t) { static DoubleRefConverter c{}; return &c; };
2938  gf["const double&"] = (cf_t)+[](dims_t) { static ConstDoubleRefConverter c{}; return &c; };
2939  gf["long double"] = (cf_t)+[](dims_t) { static LDoubleConverter c{}; return &c; };
2940  gf["const long double&"] = (cf_t)+[](dims_t) { static ConstLDoubleRefConverter c{}; return &c; };
2941  gf["long double&"] = (cf_t)+[](dims_t) { static LDoubleRefConverter c{}; return &c; };
2942  gf["std::complex<double>"] = (cf_t)+[](dims_t) { return new ComplexDConverter{}; };
2943  gf["complex<double>"] = (cf_t)+[](dims_t) { return new ComplexDConverter{}; };
2944  gf["const std::complex<double>&"] = (cf_t)+[](dims_t) { return new ComplexDConverter{}; };
2945  gf["const complex<double>&"] = (cf_t)+[](dims_t) { return new ComplexDConverter{}; };
2946  gf["void"] = (cf_t)+[](dims_t) { static VoidConverter c{}; return &c; };
2947 
2948  // pointer/array factories
2949  gf["bool*"] = (cf_t)+[](dims_t d) { return new BoolArrayConverter{d}; };
2950  gf["bool**"] = (cf_t)+[](dims_t d) { return new BoolArrayPtrConverter{d}; };
2951  gf["const signed char[]"] = (cf_t)+[](dims_t d) { return new SCharArrayConverter{d}; };
2952  gf["signed char[]"] = (cf_t)+[](dims_t d) { return new SCharArrayConverter{d}; };
2953  gf["signed char**"] = (cf_t)+[](dims_t d) { return new SCharArrayPtrConverter{d}; };
2954  gf["const unsigned char*"] = (cf_t)+[](dims_t d) { return new UCharArrayConverter{d}; };
2955  gf["unsigned char*"] = (cf_t)+[](dims_t d) { return new UCharArrayConverter{d}; };
2956  gf["UCharAsInt*"] = (cf_t)+[](dims_t d) { return new UCharArrayConverter{d}; };
2957  gf["unsigned char**"] = (cf_t)+[](dims_t d) { return new UCharArrayPtrConverter{d}; };
2958 #if __cplusplus > 201402L
2959  gf["byte*"] = (cf_t)+[](dims_t d) { return new ByteArrayConverter{d}; };
2960  gf["byte**"] = (cf_t)+[](dims_t d) { return new ByteArrayPtrConverter{d}; };
2961 #endif
2962  gf["short*"] = (cf_t)+[](dims_t d) { return new ShortArrayConverter{d}; };
2963  gf["short**"] = (cf_t)+[](dims_t d) { return new ShortArrayPtrConverter{d}; };
2964  gf["unsigned short*"] = (cf_t)+[](dims_t d) { return new UShortArrayConverter{d}; };
2965  gf["unsigned short**"] = (cf_t)+[](dims_t d) { return new UShortArrayPtrConverter{d}; };
2966  gf["int*"] = (cf_t)+[](dims_t d) { return new IntArrayConverter{d}; };
2967  gf["int**"] = (cf_t)+[](dims_t d) { return new IntArrayPtrConverter{d}; };
2968  gf["unsigned int*"] = (cf_t)+[](dims_t d) { return new UIntArrayConverter{d}; };
2969  gf["unsigned int**"] = (cf_t)+[](dims_t d) { return new UIntArrayPtrConverter{d}; };
2970  gf["long*"] = (cf_t)+[](dims_t d) { return new LongArrayConverter{d}; };
2971  gf["long**"] = (cf_t)+[](dims_t d) { return new LongArrayPtrConverter{d}; };
2972  gf["unsigned long*"] = (cf_t)+[](dims_t d) { return new ULongArrayConverter{d}; };
2973  gf["unsigned long**"] = (cf_t)+[](dims_t d) { return new ULongArrayPtrConverter{d}; };
2974  gf["long long*"] = (cf_t)+[](dims_t d) { return new LLongArrayConverter{d}; };
2975  gf["long long**"] = (cf_t)+[](dims_t d) { return new LLongArrayPtrConverter{d}; };
2976  gf["unsigned long long*"] = (cf_t)+[](dims_t d) { return new ULLongArrayConverter{d}; };
2977  gf["unsigned long long**"] = (cf_t)+[](dims_t d) { return new ULLongArrayPtrConverter{d}; };
2978  gf["float*"] = (cf_t)+[](dims_t d) { return new FloatArrayConverter{d}; };
2979  gf["float**"] = (cf_t)+[](dims_t d) { return new FloatArrayPtrConverter{d}; };
2980  gf["double*"] = (cf_t)+[](dims_t d) { return new DoubleArrayConverter{d}; };
2981  gf["double**"] = (cf_t)+[](dims_t d) { return new DoubleArrayPtrConverter{d}; };
2982  gf["long double*"] = (cf_t)+[](dims_t d) { return new LDoubleArrayConverter{d}; };
2983  gf["long double**"] = (cf_t)+[](dims_t d) { return new LDoubleArrayPtrConverter{d}; };
2984  gf["std::complex<double>*"] = (cf_t)+[](dims_t d) { return new ComplexDArrayConverter{d}; };
2985  gf["complex<double>*"] = (cf_t)+[](dims_t d) { return new ComplexDArrayConverter{d}; };
2986  gf["std::complex<double>**"] = (cf_t)+[](dims_t d) { return new ComplexDArrayPtrConverter{d}; };
2987  gf["void*"] = (cf_t)+[](dims_t d) { return new VoidArrayConverter{(bool)d}; };
2988 
2989  // aliases
2990  gf["signed char"] = gf["char"];
2991  gf["const signed char&"] = gf["const char&"];
2992 #if __cplusplus > 201402L
2993  gf["byte"] = gf["uint8_t"];
2994  gf["const byte&"] = gf["const uint8_t&"];
2995  gf["byte&"] = gf["uint8&"];
2996 #endif
2997  gf["internal_enum_type_t"] = gf["int"];
2998  gf["internal_enum_type_t&"] = gf["int&"];
2999  gf["const internal_enum_type_t&"] = gf["const int&"];
3000  gf["Long64_t"] = gf["long long"];
3001  gf["Long64_t*"] = gf["long long*"];
3002  gf["Long64_t&"] = gf["long long&"];
3003  gf["const Long64_t&"] = gf["const long long&"];
3004  gf["ULong64_t"] = gf["unsigned long long"];
3005  gf["ULong64_t*"] = gf["unsigned long long*"];
3006  gf["ULong64_t&"] = gf["unsigned long long&"];
3007  gf["const ULong64_t&"] = gf["const unsigned long long&"];
3008  gf["Float16_t"] = gf["float"];
3009  gf["const Float16_t&"] = gf["const float&"];
3010  gf["Double32_t"] = gf["double"];
3011  gf["Double32_t&"] = gf["double&"];
3012  gf["const Double32_t&"] = gf["const double&"];
3013 
3014  // factories for special cases
3015  gf["TString"] = (cf_t)+[](dims_t) { return new TStringConverter{}; };
3016  gf["TString&"] = gf["TString"];
3017  gf["const TString&"] = gf["TString"];
3018  gf["nullptr_t"] = (cf_t)+[](dims_t) { static NullptrConverter c{}; return &c;};
3019  gf["const char*"] = (cf_t)+[](dims_t) { return new CStringConverter{}; };
3020  gf["const signed char*"] = gf["const char*"];
3021  gf["const char[]"] = (cf_t)+[](dims_t) { return new CStringConverter{}; };
3022  gf["char*"] = (cf_t)+[](dims_t) { return new NonConstCStringConverter{}; };
3023  gf["signed char*"] = gf["char*"];
3024  gf["wchar_t*"] = (cf_t)+[](dims_t) { return new WCStringConverter{}; };
3025  gf["char16_t*"] = (cf_t)+[](dims_t) { return new CString16Converter{}; };
3026  gf["char32_t*"] = (cf_t)+[](dims_t) { return new CString32Converter{}; };
3027  // TODO: the following are handled incorrectly upstream (char16_t** where char16_t* intended)?!
3028  gf["char16_t**"] = gf["char16_t*"];
3029  gf["char32_t**"] = gf["char32_t*"];
3030  gf["const char**"] = (cf_t)+[](dims_t d) { return new CStringArrayConverter{d}; };
3031  gf["char**"] = gf["const char**"];
3032  gf["const char*[]"] = gf["const char**"];
3033  gf["char*[]"] = gf["const char*[]"];
3034  gf["std::string"] = (cf_t)+[](dims_t) { return new STLStringConverter{}; };
3035  gf["string"] = gf["std::string"];
3036  gf["const std::string&"] = gf["std::string"];
3037  gf["const string&"] = gf["std::string"];
3038  gf["string&&"] = (cf_t)+[](dims_t) { return new STLStringMoveConverter{}; };
3039  gf["std::string&&"] = gf["string&&"];
3040  gf["std::string_view"] = (cf_t)+[](dims_t) { return new STLStringViewConverter{}; };
3041  gf["string_view"] = gf["std::string_view"];
3042  gf[STRINGVIEW] = gf["std::string_view"];
3043  gf["experimental::" STRINGVIEW] = gf["std::string_view"];
3044  gf["std::string_view&"] = gf["std::string_view"];
3045  gf["const string_view&"] = gf["std::string_view"];
3046  gf["const " STRINGVIEW "&"] = gf["std::string_view"];
3047  gf["std::wstring"] = (cf_t)+[](dims_t) { return new STLWStringConverter{}; };
3048  gf[WSTRING] = gf["std::wstring"];
3049  gf["std::" WSTRING] = gf["std::wstring"];
3050  gf["const std::wstring&"] = gf["std::wstring"];
3051  gf["const std::" WSTRING "&"] = gf["std::wstring"];
3052  gf["const " WSTRING "&"] = gf["std::wstring"];
3053  gf["void*&"] = (cf_t)+[](dims_t) { static VoidPtrRefConverter c{}; return &c; };
3054  gf["void**"] = (cf_t)+[](dims_t d) { return new VoidPtrPtrConverter{size_t((d && d[0] != -1) ? d[1] : -1)}; };
3055  gf["void*[]"] = (cf_t)+[](dims_t d) { return new VoidPtrPtrConverter{size_t((d && d[0] != -1) ? d[1] : -1)}; };
3056  gf["PyObject*"] = (cf_t)+[](dims_t) { static PyObjectConverter c{}; return &c; };
3057  gf["_object*"] = gf["PyObject*"];
3058  gf["FILE*"] = (cf_t)+[](dims_t) { return new VoidArrayConverter{}; };
3059  }
3060 } initConvFactories_;
3061 
3062 } // unnamed namespace
CPyCppyy
Set of helper functions that are invoked from the pythonizors, on the Python side.
Definition: TPyClassGenerator.cxx:31
c
#define c(i)
Definition: RSha256.hxx:119
l
auto * l
Definition: textangle.C:4
CPyCppyy::CreatePointerView
PyObject * CreatePointerView(void *ptr, size_t size=(size_t) -1)
Definition: LowLevelViews.h:56
PyFloat_FromDouble
PyFloat_FromDouble
Definition: Converters.cxx:921
CPyCppyy::CallContext::fCurScope
Cppyy::TCppScope_t fCurScope
Definition: CallContext.h:98
m
auto * m
Definition: textangle.C:8
CPPYY_IMPL_ARRAY_CONVERTER
#define CPPYY_IMPL_ARRAY_CONVERTER(name, ctype, type, code)
Definition: Converters.cxx:1468
sqlio::Bool
const char * Bool
Definition: TSQLStructure.cxx:69
CPyCppyy::PyLongOrInt_AsULong64
ULong64_t PyLongOrInt_AsULong64(PyObject *pyobject)
Definition: Utility.cxx:150
CPyCppyy::VoidArrayConverter
Definition: Converters.h:33
CPyCppyy::Converter::ToMemory
virtual bool ToMemory(PyObject *value, void *address)
Definition: Converters.cxx:430
CPPInstance.h
first
Definition: first.py:1
CPyCppyy::Parameter::Value::fLLong
long long fLLong
Definition: callcontext.h:25
selectInstanceCnv
static CPyCppyy::Converter * selectInstanceCnv(Cppyy::TCppScope_t klass, const std::string &cpd, long size, dims_t dims, bool isConst, bool control)
Definition: Converters.cxx:2625
CPyCppyy::CallContext
Definition: CallContext.h:45
H
#define H(x, y, z)
f
#define f(i)
Definition: RSha256.hxx:122
CPPYY_IMPL_BASIC_CONST_REFCONVERTER
#define CPPYY_IMPL_BASIC_CONST_REFCONVERTER(name, type, ctype, F1)
Definition: Converters.cxx:520
RetSigKey_t
std::pair< std::string, std::string > RetSigKey_t
Definition: Converters.cxx:2156
CPyCppyy::RefFloat_CheckExact
bool RefFloat_CheckExact(T *object)
Definition: CustomPyTypes.h:20
PyObject
_object PyObject
Definition: PyMethodBase.h:42
CPyCppyy::CPPInstance::fFlags
int fFlags
Definition: CPPInstance.h:45
IsPyCArgObject
static bool IsPyCArgObject(PyObject *pyobject)
Definition: Converters.cxx:161
Cppyy::GetMethodTemplate
RPY_EXPORTED TCppMethod_t GetMethodTemplate(TCppScope_t scope, const std::string &name, const std::string &proto)
Definition: clingwrapper.cxx:1633
CPyCppyy_PyLong_AsInt8
static int8_t CPyCppyy_PyLong_AsInt8(PyObject *pyobject)
Definition: Converters.cxx:246
Cppyy::Compile
RPY_EXPORTED bool Compile(const std::string &code)
Definition: clingwrapper.cxx:374
CPyCppyy_PyLong_AsStrictInt
static int CPyCppyy_PyLong_AsStrictInt(PyObject *pyobject)
Definition: Converters.cxx:298
TupleOfInstances.h
STRINGVIEW
#define STRINGVIEW
Definition: Converters.cxx:2875
Cppyy::GetSmartPtrInfo
RPY_EXPORTED bool GetSmartPtrInfo(const std::string &, TCppType_t *raw, TCppMethod_t *deref)
Definition: clingwrapper.cxx:1243
CPyCppyy::Converter::~Converter
virtual ~Converter()
Definition: Converters.cxx:416
CPyCppyy::PyStrings::gEmptyString
PyObject * gEmptyString
Definition: PyStrings.cxx:15
PyFloat_AsDouble
PyFloat_AsDouble
Definition: Converters.cxx:921
WSTRING
#define WSTRING
Definition: Converters.cxx:2876
Cppyy::SizeOf
RPY_EXPORTED size_t SizeOf(TCppType_t klass)
Definition: clingwrapper.cxx:618
MOVE_REFCOUNT_CUTOFF
const size_t MOVE_REFCOUNT_CUTOFF
Definition: Converters.cxx:45
CPyCppyy::gConvFactories
static ConvFactories_t gConvFactories
Definition: Converters.cxx:39
Utility.h
c_ushort
l unsigned c_ushort
Definition: Converters.cxx:862
Cppyy
Definition: cpp_cppyy.h:17
CPyCppyy::CPPInstance::GetObjectRaw
void *& GetObjectRaw()
Definition: CPPInstance.h:60
Cppyy::TCppScope_t
size_t TCppScope_t
Definition: cpp_cppyy.h:18
Long64_t
long long Long64_t
Definition: RtypesCore.h:73
fBuffer
std::string fBuffer
Definition: DeclareConverters.h:140
Cppyy::GetFunctionAddress
RPY_EXPORTED TCppFuncAddr_t GetFunctionAddress(TCppMethod_t method, bool check_enabled=true)
Definition: clingwrapper.cxx:892
string_view
basic_string_view< char > string_view
Definition: libcpp_string_view.h:785
TemplateProxy.h
CPyCppyy_PyLong_AsStrictLong
static long CPyCppyy_PyLong_AsStrictLong(PyObject *pyobject)
Definition: Converters.cxx:318
Cppyy::IsSubtype
RPY_EXPORTED bool IsSubtype(TCppType_t derived, TCppType_t base)
Definition: clingwrapper.cxx:1225
GetCTypesPtrType
static PyTypeObject * GetCTypesPtrType(int nidx)
Definition: Converters.cxx:134
CPyCppyy::InstancePtrConverter::SetArg
virtual bool SetArg(PyObject *, Parameter &, CallContext *=nullptr)
Definition: Converters.cxx:1744
PyFunction_AsCPointer
static void * PyFunction_AsCPointer(PyObject *pyobject, const std::string &rettype, const std::string &signature)
Definition: Converters.cxx:2180
CPPYY_IMPL_REFCONVERTER_FROM_MEMORY
#define CPPYY_IMPL_REFCONVERTER_FROM_MEMORY(name, ctype)
Definition: Converters.cxx:504
CPyCppyy::CPPInstance
Definition: CPPInstance.h:26
gCTypesTypes
static std::array< PyTypeObject *, NTYPES > gCTypesTypes
Definition: Converters.cxx:108
CPyCppyy::cf_t
Converter *(* cf_t)(dims_t d)
Definition: Converters.h:27
CPyCppyy::InstancePtrConverter::FromMemory
virtual PyObject * FromMemory(void *address)
Definition: Converters.cxx:1780
Cppyy::ResolveName
RPY_EXPORTED std::string ResolveName(const std::string &cppitem_name)
Definition: clingwrapper.cxx:381
PyBytes_Check
#define PyBytes_Check
Definition: CPyCppyy.h:83
CPyCppyy::Utility::GetBuffer
Py_ssize_t GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, bool check=true)
Definition: Utility.cxx:614
c_uint8
c_uint8
Definition: Converters.cxx:858
fRetType
std::string fRetType
Definition: DeclareConverters.h:391
gWrapperCacheEraserMethodDef
static PyMethodDef gWrapperCacheEraserMethodDef
Definition: Converters.cxx:2174
uint8_t
uint8_t
Definition: Converters.cxx:858
TGeant4Unit::pc
static constexpr double pc
Definition: TGeant4SystemOfUnits.h:136
CPyCppyy_PyText_Check
#define CPyCppyy_PyText_Check
Definition: CPyCppyy.h:95
CPyCppyy_PyText_AsChar
static char CPyCppyy_PyText_AsChar(PyObject *pyobject)
Definition: Converters.cxx:224
long
long
Definition: Converters.cxx:858
CPyCppyy::Parameter::Value::fLong
long fLong
Definition: callcontext.h:22
sqlio::UInt
const char * UInt
Definition: TSQLStructure.cxx:79
CPyCppyy::RefInt_CheckExact
bool RefInt_CheckExact(T *object)
Definition: CustomPyTypes.h:35
CPyCppyy::gNullPtrObject
PyObject * gNullPtrObject
Definition: CPyCppyyModule.cxx:165
sWrapperFree
static std::map< RetSigKey_t, std::vector< void * > > sWrapperFree
Definition: Converters.cxx:2157
CPyCppyy::AllowImplicit
bool AllowImplicit(CallContext *ctxt)
Definition: CallContext.h:125
sFuncWrapperLookup
static std::map< void *, std::string > sFuncWrapperLookup
Definition: Converters.cxx:2337
TString
Definition: TString.h:136
CPyCppyy::Parameter::Value::fIntPtr
intptr_t fIntPtr
Definition: callcontext.h:23
CPyCppyy_PyLong_AsBool
static bool CPyCppyy_PyLong_AsBool(PyObject *pyobject)
Definition: Converters.cxx:212
CPyCppyy::CPPInstance::GetObject
void * GetObject()
Definition: CPPInstance.h:93
CPyCppyy::CPPExcInstance
Definition: CPPExcInstance.h:14
CPyCppyy_PyText_FromString
#define CPyCppyy_PyText_FromString
Definition: CPyCppyy.h:102
CPyCppyy::UnregisterConverter
CPYCPPYY_EXTERN bool UnregisterConverter(const std::string &name)
Definition: Converters.cxx:2858
MemoryRegulator.h
b
#define b(i)
Definition: RSha256.hxx:118
CPPExcInstance.h
bool
CPyCppyy::VoidArrayConverter::GetAddressSpecialCase
virtual bool GetAddressSpecialCase(PyObject *pyobject, void *&address)
Definition: Converters.cxx:1341
CPyCppyy::Converter::SetArg
virtual bool SetArg(PyObject *, Parameter &, CallContext *=nullptr)=0
CPyCppyy_PyCapsule_GetPointer
static void * CPyCppyy_PyCapsule_GetPointer(PyObject *capsule, const char *)
Definition: CPyCppyy.h:123
q
float * q
Definition: THbookFile.cxx:89
fFuncWrap
PyObject * fFuncWrap
Definition: DeclareConverters.h:411
TGeant4Unit::L
static constexpr double L
Definition: TGeant4SystemOfUnits.h:123
CPyCppyy::CallContext::AddTemporary
void AddTemporary(PyObject *pyobj)
Definition: CallContext.cxx:16
sqlio::Double
const char * Double
Definition: TSQLStructure.cxx:76
CPyCppyy::CPPOverload_Check
bool CPPOverload_Check(T *object)
Definition: CPPOverload.h:79
Cppyy::GetScope
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
Definition: clingwrapper.cxx:497
CPyCppyy::PyStrings::gNoImplicit
PyObject * gNoImplicit
Definition: PyStrings.cxx:55
sWrapperWeakRefs
static std::map< PyObject *, std::pair< void *, RetSigKey_t > > sWrapperWeakRefs
Definition: Converters.cxx:2159
ct_c_char_p
#define ct_c_char_p
Definition: Converters.cxx:97
CPyCppyy::InstancePtrConverter
Definition: Converters.h:51
CPyCppyy::BindCppObject
PyObject * BindCppObject(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
Definition: ProxyWrappers.cxx:870
sqlio::Int
const char * Int
Definition: TSQLStructure.cxx:72
CPyCppyy::Utility::ConstructCallbackReturn
void ConstructCallbackReturn(const std::string &retType, int nArgs, std::ostringstream &code)
Definition: Utility.cxx:561
CPyCppyy::BindCppObjectArray
PyObject * BindCppObjectArray(Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, Py_ssize_t *dims)
Cppyy::GetMethodIndicesFromName
RPY_EXPORTED std::vector< TCppIndex_t > GetMethodIndicesFromName(TCppScope_t scope, const std::string &name)
Definition: clingwrapper.cxx:1349
GetCppInstance
static CPyCppyy::CPPInstance * GetCppInstance(PyObject *pyobject)
Definition: Converters.cxx:200
malloc
#define malloc
Definition: civetweb.c:1536
PyBytes_AS_STRING
#define PyBytes_AS_STRING
Definition: CPyCppyy.h:85
CPyCppyy_PyText_GET_SIZE
#define CPyCppyy_PyText_GET_SIZE
Definition: CPyCppyy.h:99
CPyCppyy::Utility::IncludePython
bool IncludePython()
Definition: Utility.cxx:935
gCTypesNames
static std::array< const char *, NTYPES > gCTypesNames
Definition: Converters.cxx:103
sqlio::UShort
const char * UShort
Definition: TSQLStructure.cxx:78
ProxyWrappers.h
CPyCppyy::TemplateProxy
Definition: TemplateProxy.h:50
h
#define h(i)
Definition: RSha256.hxx:124
CPyCppyy_PyText_FromStringAndSize
#define CPyCppyy_PyText_FromStringAndSize
Definition: CPyCppyy.h:106
gCTypesPtrTypes
static std::array< PyTypeObject *, NTYPES > gCTypesPtrTypes
Definition: Converters.cxx:109
CPyCppyy_PyLong_AsShort
static short CPyCppyy_PyLong_AsShort(PyObject *pyobject)
Definition: Converters.cxx:281
sqlio::Short
const char * Short
Definition: TSQLStructure.cxx:71
CPyCppyy::CPPInstance::kIsRValue
@ kIsRValue
Definition: CPPInstance.h:34
CPyCppyy::CreateScopeProxy
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
Definition: ProxyWrappers.cxx:487
CPyCppyy_PyLong_AsUInt8
CPyCppyy_PyLong_AsUInt8
Definition: Converters.cxx:858
sWrapperReference
static std::map< void *, PyObject ** > sWrapperReference
Definition: Converters.cxx:2160
RStringView.hxx
c_double
c_double
Definition: Converters.cxx:921
UNKNOWN_ARRAY_SIZE
#define UNKNOWN_ARRAY_SIZE
Definition: Converters.cxx:31
CPyCppyy::IsConstructor
bool IsConstructor(uint64_t flags)
Definition: CallContext.h:117
sqlio::Long
const char * Long
Definition: TSQLStructure.cxx:73
m_dims
dims_t m_dims
Definition: DeclareConverters.h:302
CPyCppyy::RegisterConverter
CPYCPPYY_EXTERN bool RegisterConverter(const std::string &name, ConverterFactory_t)
CPyCppyy::CPPScope_Check
bool CPPScope_Check(T *object)
Definition: CPPScope.h:76
ct_c_long
#define ct_c_long
Definition: Converters.cxx:90
IsCTypesArrayOrPointer
static bool IsCTypesArrayOrPointer(PyObject *pyobject)
Definition: Converters.cxx:181
CPyCppyy::Converter::FromMemory
virtual PyObject * FromMemory(void *address)
Definition: Converters.cxx:422
CPyCppyy::CreateConverter
CPYCPPYY_EXTERN Converter * CreateConverter(const std::string &name, Py_ssize_t *dims=nullptr)
CPyCppyy::TypeManip::remove_const
std::string remove_const(const std::string &cppname)
Definition: TypeManip.cxx:71
CPPYY_IMPL_BASIC_CHAR_CONVERTER
#define CPPYY_IMPL_BASIC_CHAR_CONVERTER(name, type, low, high)
Definition: Converters.cxx:551
CallContext.h
fIsConst
bool fIsConst
Definition: DeclareConverters.h:260
CPPYY_IMPL_BASIC_CONVERTER
#define CPPYY_IMPL_BASIC_CONVERTER(name, type, stype, ctype, F1, F2, tc)
Definition: Converters.cxx:439
CPyCppyy::NoImplicit
bool NoImplicit(CallContext *ctxt)
Definition: CallContext.h:129
WrapperCacheEraser
static PyObject * WrapperCacheEraser(PyObject *, PyObject *pyref)
Definition: Converters.cxx:2162
CPPYY_IMPL_BASIC_CONST_CHAR_REFCONVERTER
#define CPPYY_IMPL_BASIC_CONST_CHAR_REFCONVERTER(name, type, ctype, low, high)
Definition: Converters.cxx:535
CPyCppyy::CallContext::kUseStrict
@ kUseStrict
Definition: CallContext.h:60
CPyCppyy.h
CPyCppyy::InstancePtrConverter::ToMemory
virtual bool ToMemory(PyObject *value, void *address)
Definition: Converters.cxx:1787
UInt_t
unsigned int UInt_t
Definition: RtypesCore.h:46
ct_c_void_p
#define ct_c_void_p
Definition: Converters.cxx:99
CPyCppyy_PyCapsule_CheckExact
#define CPyCppyy_PyCapsule_CheckExact
Definition: CPyCppyy.h:122
ULong_t
unsigned long ULong_t
Definition: RtypesCore.h:55
CPyCppyy::PyLongOrInt_AsULong
unsigned long PyLongOrInt_AsULong(PyObject *pyobject)
Definition: Utility.cxx:130
UNKNOWN_SIZE
#define UNKNOWN_SIZE
Definition: Converters.cxx:30
CPyCppyy::VoidArrayConverter::ToMemory
virtual bool ToMemory(PyObject *value, void *address)
Definition: Converters.cxx:1436
realloc
#define realloc
Definition: civetweb.c:1538
CPyCppyy::Parameter::fTypeCode
char fTypeCode
Definition: callcontext.h:35
CPyCppyy::ConvFactories_t
std::map< std::string, cf_t > ConvFactories_t
Definition: Converters.cxx:38
CPyCppyy::CPPInstance::GetSmartObject
void * GetSmartObject()
Definition: CPPInstance.h:69
fClass
Cppyy::TCppType_t fClass
Definition: DeclareConverters.h:259
byte
unsigned char byte
Definition: gifdecode.c:10
unsigned int
CPyCppyy::CallContext::kNoImplicit
@ kNoImplicit
Definition: CallContext.h:58
CPyCppyy::VoidArrayConverter::KeepControl
bool KeepControl()
Definition: Converters.h:45
ConvertImplicit
static bool ConvertImplicit(Cppyy::TCppType_t klass, PyObject *pyobject, CPyCppyy::Parameter &para, CPyCppyy::CallContext *ctxt)
Definition: Converters.cxx:356
CPyCppyy::Utility::ConstructCallbackPreamble
void ConstructCallbackPreamble(const std::string &retType, const std::vector< std::string > &argtypes, std::ostringstream &code)
Definition: Utility.cxx:517
CPyCppyy::CallContext::sMemoryPolicy
static ECallFlags sMemoryPolicy
Definition: CallContext.h:70
CPyCppyy_PyText_AsString
#define CPyCppyy_PyText_AsString
Definition: CPyCppyy.h:97
CPyCppyy::CPPScope
Definition: CPPScope.h:37
fKeepControl
bool fKeepControl
Definition: DeclareConverters.h:436
Cppyy::TCppType_t
TCppScope_t TCppType_t
Definition: cpp_cppyy.h:19
Cppyy::TCppObject_t
void * TCppObject_t
Definition: cpp_cppyy.h:21
sqlio::UChar
const char * UChar
Definition: TSQLStructure.cxx:77
TypeManip.h
CPyCppyy_PyLong_AsUShort
l unsigned CPyCppyy_PyLong_AsUShort
Definition: Converters.cxx:862
CPPYY_IMPL_STRING_AS_PRIMITIVE_CONVERTER
#define CPPYY_IMPL_STRING_AS_PRIMITIVE_CONVERTER(name, type, F1, F2)
Definition: Converters.cxx:1598
sqlio::Float
const char * Float
Definition: TSQLStructure.cxx:75
PyInt_FromLong
PyInt_FromLong
Definition: Converters.cxx:858
ULong64_t
unsigned long long ULong64_t
Definition: RtypesCore.h:74
Cppyy::TCppMethod_t
intptr_t TCppMethod_t
Definition: cpp_cppyy.h:22
DeclareConverters.h
LongDouble_t
long double LongDouble_t
Definition: RtypesCore.h:61
fConverter
Converter * fConverter
Definition: DeclareConverters.h:410
CPyCppyy::UseStrictOwnership
bool UseStrictOwnership(CallContext *ctxt)
Definition: CallContext.h:137
sqlio::ULong
const char * ULong
Definition: TSQLStructure.cxx:80
CPyCppyy::CreateLowLevelView
PyObject * CreateLowLevelView(const char **, Py_ssize_t *shape=nullptr)
Definition: LowLevelViews.cxx:853
sWrapperCounter
static unsigned int sWrapperCounter
Definition: Converters.cxx:2154
CPyCppyy_PyText_AsStringAndSize
static const char * CPyCppyy_PyText_AsStringAndSize(PyObject *pystr, Py_ssize_t *size)
Definition: CPyCppyy.h:108
Cppyy::GetMethod
RPY_EXPORTED TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
Definition: clingwrapper.cxx:1384
fUnderlyingType
Cppyy::TCppType_t fUnderlyingType
Definition: DeclareConverters.h:435
PY_SSIZE_T_FORMAT
#define PY_SSIZE_T_FORMAT
Definition: CPyCppyy.h:231
CPyCppyy::CallContext::fFlags
uint64_t fFlags
Definition: CallContext.h:97
fIsRef
bool fIsRef
Definition: DeclareConverters.h:437
fSmartPtrType
Cppyy::TCppType_t fSmartPtrType
Definition: DeclareConverters.h:434
CPyCppyy::TupleOfInstances_CheckExact
bool TupleOfInstances_CheckExact(T *object)
Definition: TupleOfInstances.h:23
sWrapperLookup
static std::map< RetSigKey_t, std::map< PyObject *, void * > > sWrapperLookup
Definition: Converters.cxx:2158
Cppyy::GetBaseOffset
RPY_EXPORTED ptrdiff_t GetBaseOffset(TCppType_t derived, TCppType_t base, TCppObject_t address, int direction, bool rerror=false)
Definition: clingwrapper.cxx:1276
CPyCppyy::VoidArrayConverter::SetArg
virtual bool SetArg(PyObject *, Parameter &, CallContext *=nullptr)
Definition: Converters.cxx:1370
CPyCppyy::Converter
Definition: API.h:91
CPPOverload.h
CPyCppyy::Parameter::Value::fVoidp
void * fVoidp
Definition: callcontext.h:32
fValueSize
size_t fValueSize
Definition: DeclareConverters.h:456
name
char name[80]
Definition: TGX11.cxx:110
CPyCppyy::Parameter::fValue
union CPyCppyy::Parameter::Value fValue
CPyCppyy::DestroyConverter
CPYCPPYY_EXTERN void DestroyConverter(Converter *p)
Definition: Converters.cxx:2837
d
#define d(i)
Definition: RSha256.hxx:120
CPyCppyy::TemplateProxy::fTI
TP_TInfo_t fTI
Definition: TemplateProxy.h:61
I
#define I(x, y, z)
LowLevelViews.h
CPyCppyy::MemoryRegulator::RegisterPyObject
static bool RegisterPyObject(CPPInstance *pyobj, void *cppobj)
Definition: MemoryRegulator.cxx:173
CPyCppyy::VoidArrayConverter::FromMemory
virtual PyObject * FromMemory(void *address)
Definition: Converters.cxx:1425
fSize
size_t fSize
Definition: DeclareConverters.h:342
CPyCppyy::CPPOverload
Definition: CPPOverload.h:36
CPyCppyy::Utility::Compound
const std::string Compound(const std::string &name)
Definition: Utility.cxx:782
CPyCppyy::Converter::HasState
virtual bool HasState()
Definition: API.h:105
fSignature
std::string fSignature
Definition: DeclareConverters.h:392
CPyCppyy::CallContext::GetSize
size_t GetSize()
Definition: CallContext.h:93
CPyCppyy::TemplateProxy::fTemplateArgs
PyObject * fTemplateArgs
Definition: TemplateProxy.h:59
CPyCppyy_PyUnicode_AsWideChar
static Py_ssize_t CPyCppyy_PyUnicode_AsWideChar(PyObject *pyobj, wchar_t *w, Py_ssize_t size)
Definition: CPyCppyy.h:214
CustomPyTypes.h
CPyCppyy::CPPExcInstance_Check
bool CPPExcInstance_Check(T *object)
Definition: CPPExcInstance.h:26
sqlio::Char
const char * Char
Definition: TSQLStructure.cxx:70
CPyCppyy::CPPInstance::GetSmartIsA
Cppyy::TCppType_t GetSmartIsA() const
Definition: CPPInstance.cxx:177
free
#define free
Definition: civetweb.c:1539
ROOT::Math::Cephes::B
static double B[]
Definition: SpecFuncCephes.cxx:178
CPyCppyy::CPPInstance::ObjectIsA
Cppyy::TCppType_t ObjectIsA(bool check_smart=true) const
Definition: CPPInstance.h:106
fMaxSize
long fMaxSize
Definition: DeclareConverters.h:141
CPyCppyy::CPPInstance::CppOwns
void CppOwns()
Definition: CPPInstance.cxx:160
Py_TYPE
#define Py_TYPE(ob)
Definition: CPyCppyy.h:209
CPyCppyy::CPPInstance::kIsReference
@ kIsReference
Definition: CPPInstance.h:33
CPYCPPYY_EXPORT
#define CPYCPPYY_EXPORT
Definition: CommonDefs.h:25
CPyCppyy::TemplateProxy_Check
bool TemplateProxy_Check(T *object)
Definition: TemplateProxy.h:79
CPyCppyy::CPPInstance_Check
bool CPPInstance_Check(T *object)
Definition: CPPInstance.h:118
CPyCppyy::CPPOverload::MethodInfo_t::fMethods
CPPOverload::Methods_t fMethods
Definition: CPPOverload.h:47
CPyCppyy::Parameter::Value::fULLong
unsigned long long fULLong
Definition: callcontext.h:26
CPyCppyy::CallContext::kHaveImplicit
@ kHaveImplicit
Definition: CallContext.h:56
CPyCppyy::Parameter
Definition: callcontext.h:13
CPyCppyy::BindCppObjectNoCast
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
Definition: ProxyWrappers.cxx:799
CPPYY_IMPL_REFCONVERTER
#define CPPYY_IMPL_REFCONVERTER(name, ctype, type, code)
Definition: Converters.cxx:679
CPyCppyy::CPPOverload::fMethodInfo
MethodInfo_t * fMethodInfo
Definition: CPPOverload.h:68
GetCTypesType
static PyTypeObject * GetCTypesType(int nidx)
Definition: Converters.cxx:115
CPyCppyy::TypeManip::clean_type
std::string clean_type(const std::string &cppname, bool template_strip=true, bool const_strip=true)
Definition: TypeManip.cxx:98
CPyCppyy::InstancePtrConverter::fClass
Cppyy::TCppType_t fClass
Definition: Converters.h:62
ExtractChar
static int ExtractChar(PyObject *pyobject, const char *tname, int low, int high)
Definition: Converters.cxx:479
PyStrings.h
CArraySetArg
static bool CArraySetArg(PyObject *pyobject, CPyCppyy::Parameter &para, char tc, int size)
Definition: Converters.cxx:332
Py_RETURN_NONE
#define Py_RETURN_NONE
Definition: CPyCppyy.h:281
FPCFM_ERRMSG
static const char * FPCFM_ERRMSG
Definition: Converters.cxx:2338
int
CPyCppyy::CPPInstance::IsSmart
bool IsSmart() const
Definition: CPPInstance.h:56
ROOT::Math::Cephes::Q
static double Q[]
Definition: SpecFuncCephes.cxx:294
CPyCppyy::TypeManip::extract_arg_types
std::vector< std::string > extract_arg_types(const std::string &sig)
Definition: TypeManip.cxx:187
ct_c_int
#define ct_c_int
Definition: Converters.cxx:87
g
#define g(i)
Definition: RSha256.hxx:123