Logo ROOT   master
Reference Guide
Executors.cxx
Go to the documentation of this file.
1 // Bindings
2 #include "CPyCppyy.h"
3 #include "DeclareExecutors.h"
4 #include "CPPInstance.h"
5 #include "LowLevelViews.h"
6 #include "ProxyWrappers.h"
7 #include "PyStrings.h"
8 #include "TypeManip.h"
9 #include "Utility.h"
10 
11 // Standard
12 #include <cstring>
13 #include <map>
14 #include <new>
15 #include <sstream>
16 #include <utility>
17 #include <sys/types.h>
18 
19 
20 //- data _____________________________________________________________________
21 namespace CPyCppyy {
22  typedef Executor* (*ef_t) ();
23  typedef std::map<std::string, ef_t> ExecFactories_t;
25 
26  extern PyObject* gNullPtrObject;
27 
28  extern std::set<std::string> gIteratorTypes;
29 }
30 
31 
32 //- helpers ------------------------------------------------------------------
33 namespace {
34 
35 #ifdef WITH_THREAD
36  class GILControl {
37  public:
38  GILControl() : fSave(PyEval_SaveThread()) { }
39  ~GILControl() {
40  PyEval_RestoreThread(fSave);
41  }
42  private:
43  PyThreadState* fSave;
44  };
45 #endif
46 
47 } // unnamed namespace
48 
49 #ifdef WITH_THREAD
50 #define CPPYY_IMPL_GILCALL(rtype, tcode) \
51 static inline rtype GILCall##tcode( \
52  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, CPyCppyy::CallContext* ctxt)\
53 { \
54  if (!ReleasesGIL(ctxt)) \
55  return Cppyy::Call##tcode(method, self, ctxt->GetSize(), ctxt->GetArgs());\
56  GILControl gc{}; \
57  return Cppyy::Call##tcode(method, self, ctxt->GetSize(), ctxt->GetArgs());\
58 }
59 #else
60 #define CPPYY_IMPL_GILCALL(rtype, tcode) \
61 static inline rtype GILCall##tcode( \
62  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, CPyCppyy::CallContext* ctxt)\
63 { \
64  return Cppyy::Call##tcode(method, self, ctxt->GetSize(), ctxt->GetArgs());\
65 }
66 #endif
67 
68 CPPYY_IMPL_GILCALL(void, V)
69 CPPYY_IMPL_GILCALL(unsigned char, B)
70 CPPYY_IMPL_GILCALL(char, C)
71 CPPYY_IMPL_GILCALL(short, H)
75 CPPYY_IMPL_GILCALL(float, F)
76 CPPYY_IMPL_GILCALL(double, D)
78 CPPYY_IMPL_GILCALL(void*, R)
79 
80 static inline Cppyy::TCppObject_t GILCallO(Cppyy::TCppMethod_t method,
81  Cppyy::TCppObject_t self, CPyCppyy::CallContext* ctxt, Cppyy::TCppType_t klass)
82 {
83 #ifdef WITH_THREAD
84  if (!ReleasesGIL(ctxt))
85 #endif
86  return Cppyy::CallO(method, self, ctxt->GetSize(), ctxt->GetArgs(), klass);
87 #ifdef WITH_THREAD
88  GILControl gc{};
89  return Cppyy::CallO(method, self, ctxt->GetSize(), ctxt->GetArgs(), klass);
90 #endif
91 }
92 
95 {
96 #ifdef WITH_THREAD
97  if (!ReleasesGIL(ctxt))
98 #endif
99  return Cppyy::CallConstructor(method, klass, ctxt->GetSize(), ctxt->GetArgs());
100 #ifdef WITH_THREAD
101  GILControl gc{};
102  return Cppyy::CallConstructor(method, klass, ctxt->GetSize(), ctxt->GetArgs());
103 #endif
104 }
105 
106 static inline PyObject* CPyCppyy_PyText_FromLong(long cl)
107 {
108 // python chars are range(256)
109  if (cl < -256 || cl > 255) {
110  PyErr_SetString(PyExc_ValueError, "char conversion out of range");
111  return nullptr;
112  }
113  int c = (int)cl;
114  if (c < 0) return CPyCppyy_PyText_FromFormat("%c", 256 - std::abs(c));
115  return CPyCppyy_PyText_FromFormat("%c", c);
116 }
117 
118 static inline PyObject* CPyCppyy_PyText_FromULong(unsigned long uc)
119 {
120 // TODO: range check here?
121  if (255 < uc) {
122  PyErr_SetString(PyExc_ValueError, "char conversion out of range");
123  return nullptr;
124  }
125  int c = (int)uc;
126  return CPyCppyy_PyText_FromFormat("%c", c);
127 }
128 
129 static inline PyObject* CPyCppyy_PyBool_FromLong(long b)
130 {
131  PyObject* result = (bool)b ? Py_True : Py_False;
132  Py_INCREF(result);
133  return result;
134 }
135 
136 
137 //- base executor implementation ---------------------------------------------
139 {
140  /* empty */
141 }
142 
143 //- executors for built-ins --------------------------------------------------
144 PyObject* CPyCppyy::BoolExecutor::Execute(
146 {
147 // execute <method> with argument <self, ctxt>, construct python bool return value
148  bool retval = GILCallB(method, self, ctxt);
149  PyObject* result = retval ? Py_True : Py_False;
150  Py_INCREF(result);
151  return result;
152 }
153 
154 //----------------------------------------------------------------------------
155 PyObject* CPyCppyy::BoolConstRefExecutor::Execute(
157 {
158 // execute <method> with argument <self, ctxt>, construct python bool return value
159  return CPyCppyy_PyBool_FromLong(*((bool*)GILCallR(method, self, ctxt)));
160 }
161 
162 //----------------------------------------------------------------------------
163 PyObject* CPyCppyy::CharExecutor::Execute(
165 {
166 // execute <method with argument <self, ctxt>, construct python string return value
167 // with the single char
168  return CPyCppyy_PyText_FromLong((int)GILCallC(method, self, ctxt));
169 }
170 
171 //----------------------------------------------------------------------------
172 PyObject* CPyCppyy::CharConstRefExecutor::Execute(
174 {
175 // execute <method> with argument <self, ctxt>, construct python string return value
176 // with the single char
177  return CPyCppyy_PyText_FromLong(*((char*)GILCallR(method, self, ctxt)));
178 }
179 
180 //----------------------------------------------------------------------------
181 PyObject* CPyCppyy::UCharExecutor::Execute(
183 {
184 // execute <method> with argument <self, args>, construct python string return value
185 // with the single char
186  return CPyCppyy_PyText_FromLong((unsigned char)GILCallB(method, self, ctxt));
187 }
188 
189 //----------------------------------------------------------------------------
190 PyObject* CPyCppyy::UCharConstRefExecutor::Execute(
192 {
193 // execute <method> with argument <self, ctxt>, construct python string return value
194 // with the single char from the pointer return
195  return CPyCppyy_PyText_FromLong(*((unsigned char*)GILCallR(method, self, ctxt)));
196 }
197 
198 //----------------------------------------------------------------------------
199 PyObject* CPyCppyy::WCharExecutor::Execute(
201 {
202 // execute <method> with argument <self, args>, construct python string return value
203 // with the single wide char
204  wchar_t res = (wchar_t)GILCallL(method, self, ctxt);
205  return PyUnicode_FromWideChar(&res, 1);
206 }
207 
208 //----------------------------------------------------------------------------
209 PyObject* CPyCppyy::Char16Executor::Execute(
211 {
212 // execute <method> with argument <self, args>, construct python string return value
213 // with the single char16
214  char16_t res = (char16_t)GILCallL(method, self, ctxt);
215  return PyUnicode_DecodeUTF16((const char*)&res, sizeof(char16_t), nullptr, nullptr);
216 }
217 
218 //----------------------------------------------------------------------------
219 PyObject* CPyCppyy::Char32Executor::Execute(
221 {
222 // execute <method> with argument <self, args>, construct python string return value
223 // with the single char32
224  char32_t res = (char32_t)GILCallL(method, self, ctxt);
225  return PyUnicode_DecodeUTF32((const char*)&res, sizeof(char32_t), nullptr, nullptr);
226 }
227 
228 //----------------------------------------------------------------------------
229 PyObject* CPyCppyy::IntExecutor::Execute(
231 {
232 // execute <method> with argument <self, ctxt>, construct python int return value
233  return PyInt_FromLong((int)GILCallI(method, self, ctxt));
234 }
235 
236 //----------------------------------------------------------------------------
237 PyObject* CPyCppyy::Int8Executor::Execute(
239 {
240 // execute <method> with argument <self, ctxt>, construct python int return value
241  return PyInt_FromLong((int8_t)GILCallC(method, self, ctxt));
242 }
243 
244 //----------------------------------------------------------------------------
245 PyObject* CPyCppyy::UInt8Executor::Execute(
247 {
248 // execute <method> with argument <self, ctxt>, construct python int return value
249  return PyInt_FromLong((uint8_t)GILCallB(method, self, ctxt));
250 }
251 
252 //----------------------------------------------------------------------------
253 PyObject* CPyCppyy::ShortExecutor::Execute(
255 {
256 // execute <method> with argument <self, ctxt>, construct python int return value
257  return PyInt_FromLong((short)GILCallH(method, self, ctxt));
258 }
259 
260 //----------------------------------------------------------------------------
261 PyObject* CPyCppyy::LongExecutor::Execute(
263 {
264 // execute <method> with argument <self, ctxt>, construct python long return value
265  return PyLong_FromLong((Long_t)GILCallL(method, self, ctxt));
266 }
267 
268 //----------------------------------------------------------------------------
269 PyObject* CPyCppyy::ULongExecutor::Execute(
271 {
272 // execute <method> with argument <self, ctxt>, construct python unsigned long return value
273  return PyLong_FromUnsignedLong((ULong_t)GILCallLL(method, self, ctxt));
274 }
275 
276 //----------------------------------------------------------------------------
277 PyObject* CPyCppyy::LongLongExecutor::Execute(
279 {
280 // execute <method> with argument <self, ctxt>, construct python long long return value
281  Long64_t result = GILCallLL(method, self, ctxt);
282  return PyLong_FromLongLong(result);
283 }
284 
285 //----------------------------------------------------------------------------
286 PyObject* CPyCppyy::ULongLongExecutor::Execute(
288 {
289 // execute <method> with argument <self, ctxt>, construct python unsigned long long return value
290  ULong64_t result = (ULong64_t)GILCallLL(method, self, ctxt);
291  return PyLong_FromUnsignedLongLong(result);
292 }
293 
294 //----------------------------------------------------------------------------
295 PyObject* CPyCppyy::FloatExecutor::Execute(
297 {
298 // execute <method> with argument <self, ctxt>, construct python float return value
299  return PyFloat_FromDouble((double)GILCallF(method, self, ctxt));
300 }
301 
302 //----------------------------------------------------------------------------
303 PyObject* CPyCppyy::DoubleExecutor::Execute(
305 {
306 // execute <method> with argument <self, ctxt>, construct python float return value
307  return PyFloat_FromDouble((double)GILCallD(method, self, ctxt));
308 }
309 
310 //----------------------------------------------------------------------------
311 PyObject* CPyCppyy::LongDoubleExecutor::Execute(
313 {
314 // execute <method> with argument <self, ctxt>, construct python float return value
315  return PyFloat_FromDouble((double)GILCallLD(method, self, ctxt));
316 }
317 
318 //----------------------------------------------------------------------------
320 {
321 // prepare "buffer" for by-ref returns, used with __setitem__
322  if (pyobject) {
323  Py_INCREF(pyobject);
324  fAssignable = pyobject;
325  return true;
326  }
327 
328  fAssignable = nullptr;
329  return false;
330 }
331 
332 //----------------------------------------------------------------------------
333 #define CPPYY_IMPL_REFEXEC(name, type, stype, F1, F2) \
334 PyObject* CPyCppyy::name##RefExecutor::Execute( \
335  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, CallContext* ctxt) \
336 { \
337  type* ref = (type*)GILCallR(method, self, ctxt); \
338  if (!ref) { /* can happen if wrapper compilation fails */ \
339  PyErr_SetString(PyExc_ReferenceError, "attempt to access a null-pointer");\
340  return nullptr; \
341  } \
342  if (!fAssignable) \
343  return F1((stype)*ref); \
344  else { \
345  *ref = (type)F2(fAssignable); \
346  Py_DECREF(fAssignable); \
347  fAssignable = nullptr; \
348  if (*ref == (type)-1 && PyErr_Occurred()) \
349  return nullptr; \
350  Py_INCREF(Py_None); \
351  return Py_None; \
352  } \
353 }
354 
358 CPPYY_IMPL_REFEXEC(Int8, int8_t, Long_t, PyInt_FromLong, PyLong_AsLong)
360 CPPYY_IMPL_REFEXEC(Short, short, Long_t, PyInt_FromLong, PyLong_AsLong)
363 CPPYY_IMPL_REFEXEC(UInt, UInt_t, ULong_t, PyLong_FromUnsignedLong, PyLongOrInt_AsULong)
364 CPPYY_IMPL_REFEXEC(Long, Long_t, Long_t, PyLong_FromLong, PyLong_AsLong)
365 CPPYY_IMPL_REFEXEC(ULong, ULong_t, ULong_t, PyLong_FromUnsignedLong, PyLongOrInt_AsULong)
366 CPPYY_IMPL_REFEXEC(LongLong, Long64_t, Long64_t, PyLong_FromLongLong, PyLong_AsLongLong)
367 CPPYY_IMPL_REFEXEC(ULongLong, ULong64_t, ULong64_t, PyLong_FromUnsignedLongLong, PyLongOrInt_AsULong64)
371 
372 template<typename T>
373 static inline PyObject* PyComplex_FromComplex(const std::complex<T>& c) {
374  return PyComplex_FromDoubles(c.real(), c.imag());
375 }
376 
377 template<typename T>
378 static inline std::complex<T> PyComplex_AsComplex(PyObject* pycplx) {
379  Py_complex cplx = PyComplex_AsCComplex(pycplx);
380  return std::complex<T>(cplx.real, cplx.imag);
381 }
382 
383 CPPYY_IMPL_REFEXEC(ComplexD, std::complex<double>,
384  std::complex<double>, PyComplex_FromComplex<double>, PyComplex_AsComplex<double>)
385 
386 
387 //----------------------------------------------------------------------------
388 PyObject* CPyCppyy::STLStringRefExecutor::Execute(
390 {
391 // execute <method> with argument <self, ctxt>, return python string return value
392  std::string* result = (std::string*)GILCallR(method, self, ctxt);
393  if (!fAssignable)
394  return CPyCppyy_PyText_FromStringAndSize(result->c_str(), result->size());
395 
396  *result = std::string(
397  CPyCppyy_PyText_AsString(fAssignable), CPyCppyy_PyText_GET_SIZE(fAssignable));
398 
399  Py_DECREF(fAssignable);
400  fAssignable = nullptr;
401 
403 }
404 
405 //----------------------------------------------------------------------------
406 PyObject* CPyCppyy::VoidExecutor::Execute(
408 {
409 // execute <method> with argument <self, ctxt>, return None
410  GILCallV(method, self, ctxt);
412 }
413 
414 //----------------------------------------------------------------------------
415 PyObject* CPyCppyy::CStringExecutor::Execute(
417 {
418 // execute <method> with argument <self, ctxt>, construct python string return value
419  char* result = (char*)GILCallR(method, self, ctxt);
420  if (!result) {
421  Py_INCREF(PyStrings::gEmptyString);
423  }
424 
425  return CPyCppyy_PyText_FromString(result);
426 }
427 
428 //----------------------------------------------------------------------------
429 PyObject* CPyCppyy::WCStringExecutor::Execute(
431 {
432 // execute <method> with argument <self, ctxt>, construct python unicode return value
433  wchar_t* result = (wchar_t*)GILCallR(method, self, ctxt);
434  if (!result) {
435  wchar_t w = L'\0';
436  return PyUnicode_FromWideChar(&w, 0);
437  }
438 
439  return PyUnicode_FromWideChar(result, wcslen(result));
440 }
441 
442 //----------------------------------------------------------------------------
443 PyObject* CPyCppyy::CString16Executor::Execute(
445 {
446 // execute <method> with argument <self, ctxt>, construct python unicode return value
447  char16_t* result = (char16_t*)GILCallR(method, self, ctxt);
448  if (!result) {
449  char16_t w = u'\0';
450  return PyUnicode_DecodeUTF16((const char*)&w, 0, nullptr, nullptr);
451  }
452 
453  return PyUnicode_DecodeUTF16((const char*)result,
454  std::char_traits<char16_t>::length(result)*sizeof(char16_t), nullptr, nullptr);
455 }
456 
457 //----------------------------------------------------------------------------
458 PyObject* CPyCppyy::CString32Executor::Execute(
460 {
461 // execute <method> with argument <self, ctxt>, construct python unicode return value
462  char32_t* result = (char32_t*)GILCallR(method, self, ctxt);
463  if (!result) {
464  char32_t w = U'\0';
465  return PyUnicode_DecodeUTF32((const char*)&w, 0, nullptr, nullptr);
466  }
467 
468  return PyUnicode_DecodeUTF32((const char*)result,
469  std::char_traits<char32_t>::length(result)*sizeof(char32_t), nullptr, nullptr);
470 }
471 
472 
473 //- pointer/array executors --------------------------------------------------
474 PyObject* CPyCppyy::VoidArrayExecutor::Execute(
476 {
477 // execute <method> with argument <self, ctxt>, construct python long return value
478  Long_t* result = (Long_t*)GILCallR(method, self, ctxt);
479  if (!result) {
480  Py_INCREF(gNullPtrObject);
481  return gNullPtrObject;
482  }
483  return CreatePointerView(result);
484 }
485 
486 //----------------------------------------------------------------------------
487 #define CPPYY_IMPL_ARRAY_EXEC(name, type) \
488 PyObject* CPyCppyy::name##ArrayExecutor::Execute( \
489  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, CallContext* ctxt) \
490 { \
491  return CreateLowLevelView((type*)GILCallR(method, self, ctxt)); \
492 }
493 
495 CPPYY_IMPL_ARRAY_EXEC(UChar, unsigned char)
496 #if __cplusplus > 201402L
498 #endif
500 CPPYY_IMPL_ARRAY_EXEC(UShort, unsigned short)
502 CPPYY_IMPL_ARRAY_EXEC(UInt, unsigned int)
504 CPPYY_IMPL_ARRAY_EXEC(ULong, unsigned long)
505 CPPYY_IMPL_ARRAY_EXEC(LLong, long long)
506 CPPYY_IMPL_ARRAY_EXEC(ULLong, unsigned long long)
509 CPPYY_IMPL_ARRAY_EXEC(ComplexF, std::complex<float>)
510 CPPYY_IMPL_ARRAY_EXEC(ComplexD, std::complex<double>)
511 CPPYY_IMPL_ARRAY_EXEC(ComplexI, std::complex<int>)
512 CPPYY_IMPL_ARRAY_EXEC(ComplexL, std::complex<long>)
513 
514 
515 //- special cases ------------------------------------------------------------
516 #define CPPYY_COMPLEX_EXEC(code, type) \
517 PyObject* CPyCppyy::Complex##code##Executor::Execute( \
518  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, CallContext* ctxt) \
519 { \
520  static Cppyy::TCppScope_t scopeid = Cppyy::GetScope("std::complex<"#type">");\
521  std::complex<type>* result = \
522  (std::complex<type>*)GILCallO(method, self, ctxt, scopeid); \
523  if (!result) { \
524  PyErr_SetString(PyExc_ValueError, "NULL result where temporary expected");\
525  return nullptr; \
526  } \
527  \
528  PyObject* pyres = PyComplex_FromDoubles(result->real(), result->imag()); \
529  ::operator delete(result); /* Cppyy::CallO calls ::operator new */ \
530  return pyres; \
531 }
532 
533 CPPYY_COMPLEX_EXEC(D, double)
534 
535 //----------------------------------------------------------------------------
536 PyObject* CPyCppyy::STLStringExecutor::Execute(
538 {
539 // execute <method> with argument <self, ctxt>, construct python string return value
540 
541 // TODO: make use of GILLCallS (?!)
542  static Cppyy::TCppScope_t sSTLStringScope = Cppyy::GetScope("std::string");
543  std::string* result = (std::string*)GILCallO(method, self, ctxt, sSTLStringScope);
544  if (!result) {
545  Py_INCREF(PyStrings::gEmptyString);
547  }
548 
549  PyObject* pyresult =
550  CPyCppyy_PyText_FromStringAndSize(result->c_str(), result->size());
551  ::operator delete(result); // calls Cppyy::CallO which calls ::operator new
552 
553  return pyresult;
554 }
555 
556 //----------------------------------------------------------------------------
557 PyObject* CPyCppyy::STLWStringExecutor::Execute(
559 {
560 // execute <method> with argument <self, ctxt>, construct python string return value
561  static Cppyy::TCppScope_t sSTLWStringScope = Cppyy::GetScope("std::wstring");
562  std::wstring* result = (std::wstring*)GILCallO(method, self, ctxt, sSTLWStringScope);
563  if (!result) {
564  wchar_t w = L'\0';
565  return PyUnicode_FromWideChar(&w, 0);
566  }
567 
568  PyObject* pyresult = PyUnicode_FromWideChar(result->c_str(), result->size());
569  ::operator delete(result); // calls Cppyy::CallO which calls ::operator new
570 
571  return pyresult;
572 }
573 
574 //----------------------------------------------------------------------------
575 PyObject* CPyCppyy::InstancePtrExecutor::Execute(
577 {
578 // execute <method> with argument <self, ctxt>, construct python proxy object return value
579  return BindCppObject((void*)GILCallR(method, self, ctxt), fClass);
580 }
581 
582 //----------------------------------------------------------------------------
583 CPyCppyy::InstanceExecutor::InstanceExecutor(Cppyy::TCppType_t klass) :
584  fClass(klass), fFlags(CPPInstance::kIsValue)
585 {
586  /* empty */
587 }
588 
589 //----------------------------------------------------------------------------
590 PyObject* CPyCppyy::InstanceExecutor::Execute(
592 {
593 // execution will bring a temporary in existence
594  Cppyy::TCppObject_t value = GILCallO(method, self, ctxt, fClass);
595 
596  if (!value) {
597  if (!PyErr_Occurred()) // callee may have set a python error itself
598  PyErr_SetString(PyExc_ValueError, "nullptr result where temporary expected");
599  return nullptr;
600  }
601 
602 // the result can then be bound
603  PyObject* pyobj = BindCppObjectNoCast(value, fClass, fFlags);
604  if (!pyobj)
605  return nullptr;
606 
607 // python ref counting will now control this object's life span
608  ((CPPInstance*)pyobj)->PythonOwns();
609  return pyobj;
610 }
611 
612 
613 //----------------------------------------------------------------------------
614 CPyCppyy::IteratorExecutor::IteratorExecutor(Cppyy::TCppType_t klass) :
615  InstanceExecutor(klass)
616 {
617  fFlags = CPPInstance::kNoWrapConv;
618 }
619 
620 
621 //----------------------------------------------------------------------------
622 PyObject* CPyCppyy::InstanceRefExecutor::Execute(
624 {
625 // executor binds the result to the left-hand side, overwriting if an old object
626  PyObject* result = BindCppObject((void*)GILCallR(method, self, ctxt), fClass);
627  if (!result || !fAssignable)
628  return result;
629  else {
630  // this generic code is quite slow compared to its C++ equivalent ...
631  PyObject* assign = PyObject_GetAttr(result, PyStrings::gAssign);
632  if (!assign) {
633  PyErr_Clear();
634  PyObject* descr = PyObject_Str(result);
635  if (descr && CPyCppyy_PyText_CheckExact(descr)) {
636  PyErr_Format(PyExc_TypeError, "cannot assign to return object (%s)",
637  CPyCppyy_PyText_AsString(descr));
638  } else {
639  PyErr_SetString(PyExc_TypeError, "cannot assign to result");
640  }
641  Py_XDECREF(descr);
642  Py_DECREF(result);
643  Py_DECREF(fAssignable); fAssignable = nullptr;
644  return nullptr;
645  }
646 
647  PyObject* res2 = PyObject_CallFunction(assign, const_cast<char*>("O"), fAssignable);
648 
649  Py_DECREF(assign);
650  Py_DECREF(result);
651  Py_DECREF(fAssignable); fAssignable = nullptr;
652 
653  if (res2) {
654  Py_DECREF(res2); // typically, *this from operator=()
656  }
657 
658  return nullptr;
659  }
660 }
661 
662 //----------------------------------------------------------------------------
663 static inline PyObject* SetInstanceCheckError(PyObject* pyobj) {
664  PyObject* pystr = PyObject_Str(pyobj);
665  if (pystr) {
666  PyErr_Format(PyExc_TypeError,
667  "C++ object expected, got %s", CPyCppyy_PyText_AsString(pystr));
668  Py_DECREF(pystr);
669  } else
670  PyErr_SetString(PyExc_TypeError, "C++ object expected");
671  return nullptr;
672 }
673 
674 PyObject* CPyCppyy::InstancePtrPtrExecutor::Execute(
676 {
677 // execute <method> with argument <self, ctxt>, construct python C++ proxy object
678 // return ptr value
679  if (fAssignable && !CPPInstance_Check(fAssignable))
680  return SetInstanceCheckError(fAssignable);
681 
682  void** result = (void**)GILCallR(method, self, ctxt);
683  if (!fAssignable)
684  return BindCppObject((void*)result, fClass,
685  CPPInstance::kIsPtrPtr | CPPInstance::kIsReference);
686 
687  CPPInstance* cppinst = (CPPInstance*)fAssignable;
688  *result = cppinst->GetObject();
689 
690  Py_DECREF(fAssignable);
691  fAssignable = nullptr;
692 
694 }
695 
696 //----------------------------------------------------------------------------
697 PyObject* CPyCppyy::InstancePtrRefExecutor::Execute(
699 {
700 // execute <method> with argument <self, ctxt>, construct python C++ proxy object
701 // ignoring ref) return ptr value
702  if (fAssignable && !CPPInstance_Check(fAssignable))
703  return SetInstanceCheckError(fAssignable);
704 
705  void** result = (void**)GILCallR(method, self, ctxt);
706  if (!fAssignable)
707  return BindCppObject(*result, fClass);
708 
709  CPPInstance* cppinst = (CPPInstance*)fAssignable;
710  *result = cppinst->GetObject();;
711 
712  Py_DECREF(fAssignable);
713  fAssignable = nullptr;
714 
716 }
717 
718 
719 //----------------------------------------------------------------------------
720 PyObject* CPyCppyy::InstanceArrayExecutor::Execute(
722 {
723 // execute <method> with argument <self, ctxt>, construct TupleOfInstances from
724 // return value
725  dim_t dims[] = {1, (dim_t)fArraySize};
726  return BindCppObjectArray((void*)GILCallR(method, self, ctxt), fClass, dims);
727 }
728 
729 //----------------------------------------------------------------------------
730 PyObject* CPyCppyy::ConstructorExecutor::Execute(
732 {
733 // package return address in PyObject* for caller to handle appropriately (see
734 // CPPConstructor for the actual build of the PyObject)
735  return (PyObject*)GILCallConstructor(method, (Cppyy::TCppType_t)klass, ctxt);
736 }
737 
738 //----------------------------------------------------------------------------
739 PyObject* CPyCppyy::PyObjectExecutor::Execute(
741 {
742 // execute <method> with argument <self, ctxt>, return python object
743  return (PyObject*)GILCallR(method, self, ctxt);
744 }
745 
746 
747 //- factories ----------------------------------------------------------------
748 CPyCppyy::Executor* CPyCppyy::CreateExecutor(const std::string& fullType)
749 {
750 // The matching of the fulltype to an executor factory goes through up to 4 levels:
751 // 1) full, qualified match
752 // 2) drop '&' as by ref/full type is often pretty much the same python-wise
753 // 3) C++ classes, either by ref/ptr or by value
754 // 4) additional special case for enums
755 //
756 // If all fails, void is used, which will cause the return type to be ignored on use
757 
758 // an exactly matching executor is best
759  ExecFactories_t::iterator h = gExecFactories.find(fullType);
760  if (h != gExecFactories.end())
761  return (h->second)();
762 
763 // resolve typedefs etc.
764  const std::string& resolvedType = Cppyy::ResolveName(fullType);
765 
766 // a full, qualified matching executor is preferred
767  if (resolvedType != fullType) {
768  h = gExecFactories.find(resolvedType);
769  if (h != gExecFactories.end())
770  return (h->second)();
771  }
772 
773 //-- nothing? ok, collect information about the type and possible qualifiers/decorators
774  bool isConst = strncmp(resolvedType.c_str(), "const", 5) == 0;
775  const std::string& cpd = Utility::Compound(resolvedType);
776  std::string realType = TypeManip::clean_type(resolvedType, false);
777 
778 // accept unqualified type (as python does not know about qualifiers)
779  h = gExecFactories.find(realType + cpd);
780  if (h != gExecFactories.end())
781  return (h->second)();
782 
783 // drop const, as that is mostly meaningless to python (with the exception
784 // of c-strings, but those are specialized in the converter map)
785  if (isConst) {
786  realType = TypeManip::remove_const(realType);
787  h = gExecFactories.find(realType + cpd);
788  if (h != gExecFactories.end())
789  return (h->second)();
790  }
791 
792 //-- still nothing? try pointer instead of array (for builtins)
793  if (cpd == "[]") {
794  h = gExecFactories.find(realType + "*");
795  if (h != gExecFactories.end())
796  return (h->second)(); // TODO: use array size
797  }
798 
799 // C++ classes and special cases
800  Executor* result = 0;
801  if (Cppyy::TCppType_t klass = Cppyy::GetScope(realType)) {
802  if (resolvedType.find("iterator") != std::string::npos || gIteratorTypes.find(fullType) != gIteratorTypes.end()) {
803  if (cpd == "")
804  return new IteratorExecutor(klass);
805  }
806 
807  if (cpd == "")
808  result = new InstanceExecutor(klass);
809  else if (cpd == "&")
810  result = new InstanceRefExecutor(klass);
811  else if (cpd == "**" || cpd == "*[]" || cpd == "&*")
812  result = new InstancePtrPtrExecutor(klass);
813  else if (cpd == "*&")
814  result = new InstancePtrRefExecutor(klass);
815  else if (cpd == "[]") {
816  Py_ssize_t asize = Utility::ArraySize(resolvedType);
817  if (0 < asize)
818  result = new InstanceArrayExecutor(klass, asize);
819  else
820  result = new InstancePtrRefExecutor(klass);
821  } else
822  result = new InstancePtrExecutor(klass);
823  } else {
824  // unknown: void* may work ("user knows best"), void will fail on use of return value
825  h = (cpd == "") ? gExecFactories.find("void") : gExecFactories.find("void*");
826  }
827 
828  if (!result && h != gExecFactories.end())
829  // executor factory available, use it to create executor
830  result = (h->second)();
831 
832  return result; // may still be null
833 }
834 
835 //----------------------------------------------------------------------------
838 {
839  if (p && p->HasState())
840  delete p; // state-less executors are always shared
841 }
842 
843 //----------------------------------------------------------------------------
845 bool CPyCppyy::RegisterExecutor(const std::string& name, ef_t fac)
846 {
847 // register a custom executor
848  auto f = gExecFactories.find(name);
849  if (f != gExecFactories.end())
850  return false;
851 
852  gExecFactories[name] = fac;
853  return true;
854 }
855 
856 //----------------------------------------------------------------------------
858 bool CPyCppyy::UnregisterExecutor(const std::string& name)
859 {
860 // remove a custom executor
861  auto f = gExecFactories.find(name);
862  if (f != gExecFactories.end()) {
863  gExecFactories.erase(f);
864  return true;
865  }
866  return false;
867 }
868 
869 //----------------------------------------------------------------------------
872 {
873  return GILCallR(meth, obj, ctxt);
874 }
875 
876 
877 //----------------------------------------------------------------------------
878 namespace {
879 
880 using namespace CPyCppyy;
881 
882 #define WSTRING "basic_string<wchar_t,char_traits<wchar_t>,allocator<wchar_t> >"
883 
884 struct InitExecFactories_t {
885 public:
886  InitExecFactories_t() {
887  // load all executor factories in the global map 'gExecFactories'
889 
890  // factories for built-ins
891  gf["bool"] = (ef_t)+[]() { static BoolExecutor e{}; return &e; };
892  gf["bool&"] = (ef_t)+[]() { return new BoolRefExecutor{}; };
893  gf["const bool&"] = (ef_t)+[]() { static BoolConstRefExecutor e{}; return &e; };
894  gf["char"] = (ef_t)+[]() { static CharExecutor e{}; return &e; };
895  gf["signed char"] = gf["char"];
896  gf["unsigned char"] = (ef_t)+[]() { static UCharExecutor e{}; return &e; };
897  gf["char&"] = (ef_t)+[]() { return new CharRefExecutor{}; };
898  gf["signed char&"] = gf["char&"];
899  gf["unsigned char&"] = (ef_t)+[]() { return new UCharRefExecutor{}; };
900  gf["const char&"] = (ef_t)+[]() { static CharConstRefExecutor e{}; return &e; };
901  gf["const signed char&"] = gf["const char&"];
902  gf["const unsigned char&"] = (ef_t)+[]() { static UCharConstRefExecutor e{}; return &e; };
903  gf["wchar_t"] = (ef_t)+[]() { static WCharExecutor e{}; return &e; };
904  gf["char16_t"] = (ef_t)+[]() { static Char16Executor e{}; return &e; };
905  gf["char32_t"] = (ef_t)+[]() { static Char32Executor e{}; return &e; };
906  gf["int8_t"] = (ef_t)+[]() { static Int8Executor e{}; return &e; };
907  gf["int8_t&"] = (ef_t)+[]() { return new Int8RefExecutor{}; };
908  gf["const int8_t&"] = (ef_t)+[]() { static Int8RefExecutor e{}; return &e; };
909  gf["uint8_t"] = (ef_t)+[]() { static UInt8Executor e{}; return &e; };
910  gf["uint8_t&"] = (ef_t)+[]() { return new UInt8RefExecutor{}; };
911  gf["const uint8_t&"] = (ef_t)+[]() { static UInt8RefExecutor e{}; return &e; };
912  gf["short"] = (ef_t)+[]() { static ShortExecutor e{}; return &e; };
913  gf["short&"] = (ef_t)+[]() { return new ShortRefExecutor{}; };
914  gf["int"] = (ef_t)+[]() { static IntExecutor e{}; return &e; };
915  gf["int&"] = (ef_t)+[]() { return new IntRefExecutor{}; };
916  gf["unsigned short"] = gf["int"];
917  gf["unsigned short&"] = (ef_t)+[]() { return new UShortRefExecutor{}; };
918  gf["unsigned long"] = (ef_t)+[]() { static ULongExecutor e{}; return &e; };
919  gf["unsigned long&"] = (ef_t)+[]() { return new ULongRefExecutor{}; };
920  gf["unsigned int"] = gf["unsigned long"];
921  gf["unsigned int&"] = (ef_t)+[]() { return new UIntRefExecutor{}; };
922  gf["long"] = (ef_t)+[]() { static LongExecutor e{}; return &e; };
923  gf["long&"] = (ef_t)+[]() { return new LongRefExecutor{}; };
924  gf["unsigned long"] = (ef_t)+[]() { static ULongExecutor e{}; return &e; };
925  gf["unsigned long&"] = (ef_t)+[]() { return new ULongRefExecutor{}; };
926  gf["long long"] = (ef_t)+[]() { static LongLongExecutor e{}; return &e; };
927  gf["long long&"] = (ef_t)+[]() { return new LongLongRefExecutor{}; };
928  gf["unsigned long long"] = (ef_t)+[]() { static ULongLongExecutor e{}; return &e; };
929  gf["unsigned long long&"] = (ef_t)+[]() { return new ULongLongRefExecutor{}; };
930 
931  gf["float"] = (ef_t)+[]() { static FloatExecutor e{}; return &e; };
932  gf["float&"] = (ef_t)+[]() { return new FloatRefExecutor{}; };
933  gf["double"] = (ef_t)+[]() { static DoubleExecutor e{}; return &e; };
934  gf["double&"] = (ef_t)+[]() { return new DoubleRefExecutor{}; };
935  gf["long double"] = (ef_t)+[]() { static LongDoubleExecutor e{}; return &e; }; // TODO: lost precision
936  gf["long double&"] = (ef_t)+[]() { return new LongDoubleRefExecutor{}; };
937  gf["void"] = (ef_t)+[]() { static VoidExecutor e{}; return &e; };
938 
939  // pointer/array factories
940  gf["void*"] = (ef_t)+[]() { static VoidArrayExecutor e{}; return &e; };
941  gf["bool*"] = (ef_t)+[]() { static BoolArrayExecutor e{}; return &e; };
942  gf["unsigned char*"] = (ef_t)+[]() { static UCharArrayExecutor e{}; return &e; };
943  gf["const unsigned char*"] = gf["unsigned char*"];
944 #if __cplusplus > 201402L
945  gf["byte*"] = (ef_t)+[]() { static ByteArrayExecutor e{}; return &e; };
946  gf["const byte*"] = gf["byte*"];
947 #endif
948  gf["short*"] = (ef_t)+[]() { static ShortArrayExecutor e{}; return &e; };
949  gf["unsigned short*"] = (ef_t)+[]() { static UShortArrayExecutor e{}; return &e; };
950  gf["int*"] = (ef_t)+[]() { static IntArrayExecutor e{}; return &e; };
951  gf["unsigned int*"] = (ef_t)+[]() { static UIntArrayExecutor e{}; return &e; };
952  gf["long*"] = (ef_t)+[]() { static LongArrayExecutor e{}; return &e; };
953  gf["unsigned long*"] = (ef_t)+[]() { static ULongArrayExecutor e{}; return &e; };
954  gf["long long*"] = (ef_t)+[]() { static LLongArrayExecutor e{}; return &e; };
955  gf["unsigned long long*"] = (ef_t)+[]() { static ULLongArrayExecutor e{}; return &e; };
956  gf["float*"] = (ef_t)+[]() { static FloatArrayExecutor e{}; return &e; };
957  gf["double*"] = (ef_t)+[]() { static DoubleArrayExecutor e{}; return &e; };
958  gf["complex<float>*"] = (ef_t)+[]() { static ComplexFArrayExecutor e{}; return &e; };
959  gf["complex<double>*"] = (ef_t)+[]() { static ComplexDArrayExecutor e{}; return &e; };
960  gf["complex<int>*"] = (ef_t)+[]() { static ComplexIArrayExecutor e{}; return &e; };
961  gf["complex<long>*"] = (ef_t)+[]() { static ComplexLArrayExecutor e{}; return &e; };
962 
963  // aliases
964  gf["internal_enum_type_t"] = gf["int"];
965  gf["internal_enum_type_t&"] = gf["int&"];
966  gf["internal_enum_type_t*"] = gf["int*"];
967 #if __cplusplus > 201402L
968  gf["byte"] = gf["uint8_t"];
969  gf["byte&"] = gf["uint8_t&"];
970  gf["const byte&"] = gf["const uint8_t&"];
971 #endif
972  gf["Long64_t"] = gf["long long"];
973  gf["Long64_t&"] = gf["long long&"];
974  gf["Long64_t*"] = gf["long long*"];
975  gf["ULong64_t"] = gf["unsigned long long"];
976  gf["ULong64_t&"] = gf["unsigned long long&"];
977  gf["ULong64_t*"] = gf["unsigned long long*"];
978  gf["Float16_t"] = gf["float"];
979  gf["Float16_t&"] = gf["float&"];
980  gf["Double32_t"] = gf["double"];
981  gf["Double32_t&"] = gf["double&"];
982 
983  // factories for special cases
984  gf["const char*"] = (ef_t)+[]() { static CStringExecutor e{}; return &e; };
985  gf["char*"] = gf["const char*"];
986  gf["const signed char*"] = gf["const char*"];
987  gf["signed char*"] = gf["char*"];
988  gf["wchar_t*"] = (ef_t)+[]() { static WCStringExecutor e{}; return &e;};
989  gf["char16_t*"] = (ef_t)+[]() { static CString16Executor e{}; return &e;};
990  gf["char32_t*"] = (ef_t)+[]() { static CString32Executor e{}; return &e;};
991  gf["std::string"] = (ef_t)+[]() { static STLStringExecutor e{}; return &e; };
992  gf["string"] = gf["std::string"];
993  gf["std::string&"] = (ef_t)+[]() { return new STLStringRefExecutor{}; };
994  gf["string&"] = gf["std::string&"];
995  gf["std::wstring"] = (ef_t)+[]() { static STLWStringExecutor e{}; return &e; };
996  gf["std::" WSTRING] = gf["std::wstring"];
997  gf[WSTRING] = gf["std::wstring"];
998  gf["complex<double>"] = (ef_t)+[]() { static ComplexDExecutor e{}; return &e; };
999  gf["complex<double>&"] = (ef_t)+[]() { return new ComplexDRefExecutor{}; };
1000  gf["__init__"] = (ef_t)+[]() { static ConstructorExecutor e{}; return &e; };
1001  gf["PyObject*"] = (ef_t)+[]() { static PyObjectExecutor e{}; return &e; };
1002  gf["_object*"] = gf["PyObject*"];
1003  gf["FILE*"] = gf["void*"];
1004  }
1005 } initExecvFactories_;
1006 
1007 } // unnamed namespace
Py_ssize_t dim_t
Definition: CPyCppyy.h:64
TCppScope_t TCppType_t
Definition: cpp_cppyy.h:19
static double B[]
unsigned long ULong_t
Definition: CPyCppyy.h:51
PyObject * BindCppObjectArray(Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, Py_ssize_t *dims)
PyInt_FromLong
Definition: Converters.cxx:858
CPYCPPYY_EXTERN bool RegisterExecutor(const std::string &name, ExecutorFactory_t)
Definition: Executors.cxx:845
bool CPPInstance_Check(T *object)
Definition: CPPInstance.h:118
ULong64_t PyLongOrInt_AsULong64(PyObject *pyobject)
Definition: Utility.cxx:150
Parameter * GetArgs(size_t sz)
Definition: CallContext.h:80
static PyObject * PyComplex_FromComplex(const std::complex< T > &c)
Definition: Executors.cxx:373
unsigned int UInt_t
Definition: CPyCppyy.h:44
size_t TCppScope_t
Definition: cpp_cppyy.h:18
const char * Int
static Cppyy::TCppObject_t GILCallO(Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, CPyCppyy::CallContext *ctxt, Cppyy::TCppType_t klass)
Definition: Executors.cxx:80
CPYCPPYY_EXTERN Executor * CreateExecutor(const std::string &name)
Definition: Executors.cxx:748
Cppyy::TCppType_t fClass
static PyObject * SetInstanceCheckError(PyObject *pyobj)
Definition: Executors.cxx:663
RPY_EXPORTED TCppObject_t CallConstructor(TCppMethod_t method, TCppType_t type, size_t nargs, void *args)
static ExecFactories_t gExecFactories
Definition: Executors.cxx:24
#define H(x, y, z)
const char * Long
#define f(i)
Definition: RSha256.hxx:104
const char * Char
Py_ssize_t ArraySize(const std::string &name)
Definition: Utility.cxx:806
const char * UShort
const char * UInt
RPY_EXPORTED TCppObject_t CallO(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args, TCppType_t result_type)
Executor *(* ef_t)()
Definition: Executors.cxx:22
#define R(a, b, c, d, e, f, g, h, i)
Definition: RSha256.hxx:110
CPYCPPYY_EXPORT void DestroyExecutor(Executor *p)
Definition: Executors.cxx:837
std::map< std::string, ef_t > ExecFactories_t
Definition: Executors.cxx:23
static Cppyy::TCppObject_t GILCallConstructor(Cppyy::TCppMethod_t method, Cppyy::TCppType_t klass, CPyCppyy::CallContext *ctxt)
Definition: Executors.cxx:93
#define CPPYY_IMPL_ARRAY_EXEC(name, type)
Definition: Executors.cxx:487
unsigned int fFlags
PyFloat_FromDouble
Definition: Converters.cxx:921
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
#define WSTRING
Definition: Executors.cxx:882
static PyObject * CPyCppyy_PyText_FromLong(long cl)
Definition: Executors.cxx:106
static PyObject * CPyCppyy_PyBool_FromLong(long b)
Definition: Executors.cxx:129
#define CPyCppyy_PyText_FromStringAndSize
Definition: CPyCppyy.h:106
const char * UChar
#define Py_RETURN_NONE
Definition: CPyCppyy.h:281
const char * Float
unsigned char byte
Definition: gifdecode.c:10
std::set< std::string > gIteratorTypes
Definition: Pythonize.cxx:998
static PyObject * CPyCppyy_PyText_FromULong(unsigned long uc)
Definition: Executors.cxx:118
#define F(x, y, z)
virtual bool HasState()
Definition: API.h:132
static std::complex< T > PyComplex_AsComplex(PyObject *pycplx)
Definition: Executors.cxx:378
static double C[]
RPY_EXPORTED std::string ResolveName(const std::string &cppitem_name)
#define CPPYY_IMPL_GILCALL(rtype, tcode)
Definition: Executors.cxx:60
CPYCPPYY_EXTERN bool UnregisterExecutor(const std::string &name)
Definition: Executors.cxx:858
long double LongDouble_t
Definition: cpp_cppyy.h:15
intptr_t TCppMethod_t
Definition: cpp_cppyy.h:22
const char * ULong
uint8_t
Definition: Converters.cxx:858
PyFloat_AsDouble
Definition: Converters.cxx:921
virtual ~Executor()
Definition: Executors.cxx:138
const char * Double
#define h(i)
Definition: RSha256.hxx:106
PyObject * BindCppObject(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
#define CPyCppyy_PyText_GET_SIZE
Definition: CPyCppyy.h:99
#define CPyCppyy_PyText_FromString
Definition: CPyCppyy.h:102
#define CPyCppyy_PyText_FromFormat
Definition: CPyCppyy.h:101
std::string clean_type(const std::string &cppname, bool template_strip=true, bool const_strip=true)
Definition: TypeManip.cxx:98
static constexpr double L
CPYCPPYY_EXTERN void * CallVoidP(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, CallContext *)
Definition: Executors.cxx:871
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
virtual bool SetAssignable(PyObject *)
Definition: Executors.cxx:319
#define CPPYY_COMPLEX_EXEC(code, type)
Definition: Executors.cxx:516
unsigned long PyLongOrInt_AsULong(PyObject *pyobject)
Definition: Utility.cxx:130
const char * Bool
#define CPYCPPYY_EXPORT
Definition: CommonDefs.h:25
PyObject * gAssign
Definition: PyStrings.cxx:7
void * TCppObject_t
Definition: cpp_cppyy.h:21
PyObject * gEmptyString
Definition: PyStrings.cxx:15
const std::string Compound(const std::string &name)
Definition: Utility.cxx:782
long Long_t
Definition: CPyCppyy.h:50
unsigned long long ULong64_t
Definition: cpp_cppyy.h:14
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
PyObject * CreatePointerView(void *ptr, size_t size=(size_t) -1)
Definition: LowLevelViews.h:56
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
#define c(i)
Definition: RSha256.hxx:101
Py_ssize_t fArraySize
bool ReleasesGIL(CallContext *ctxt)
Definition: CallContext.h:133
#define CPyCppyy_PyText_CheckExact
Definition: CPyCppyy.h:96
std::string remove_const(const std::string &cppname)
Definition: TypeManip.cxx:71
#define I(x, y, z)
PyObject * gNullPtrObject
char name[80]
Definition: TGX11.cxx:109
#define CPPYY_IMPL_REFEXEC(name, type, stype, F1, F2)
Definition: Executors.cxx:333
_object PyObject
Definition: PyResult.h:13
const char * Short
long long Long64_t
Definition: cpp_cppyy.h:13
#define CPyCppyy_PyText_AsString
Definition: CPyCppyy.h:97