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