Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 _____________________________________________________________________
21namespace CPyCppyy {
22 typedef Executor* (*ef_t) ();
23 typedef std::map<std::string, ef_t> ExecFactories_t;
25
27
28 extern std::set<std::string> gIteratorTypes;
29}
30
31
32//- helpers ------------------------------------------------------------------
33namespace {
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) \
51static 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) \
61static 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
68CPPYY_IMPL_GILCALL(void, V)
69CPPYY_IMPL_GILCALL(unsigned char, B)
70CPPYY_IMPL_GILCALL(char, C)
75CPPYY_IMPL_GILCALL(float, F)
76CPPYY_IMPL_GILCALL(double, D)
79
80static 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
106static 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
118static 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
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 --------------------------------------------------
144PyObject* 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//----------------------------------------------------------------------------
155PyObject* 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//----------------------------------------------------------------------------
163PyObject* 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//----------------------------------------------------------------------------
172PyObject* 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//----------------------------------------------------------------------------
181PyObject* 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//----------------------------------------------------------------------------
190PyObject* 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//----------------------------------------------------------------------------
199PyObject* 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//----------------------------------------------------------------------------
209PyObject* 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//----------------------------------------------------------------------------
219PyObject* 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//----------------------------------------------------------------------------
229PyObject* 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//----------------------------------------------------------------------------
237PyObject* 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//----------------------------------------------------------------------------
245PyObject* 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//----------------------------------------------------------------------------
253PyObject* 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//----------------------------------------------------------------------------
261PyObject* 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//----------------------------------------------------------------------------
269PyObject* 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//----------------------------------------------------------------------------
277PyObject* 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//----------------------------------------------------------------------------
286PyObject* 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//----------------------------------------------------------------------------
295PyObject* 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//----------------------------------------------------------------------------
303PyObject* 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//----------------------------------------------------------------------------
311PyObject* 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) \
334PyObject* 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
355CPPYY_IMPL_REFEXEC(Bool, bool, Long_t, CPyCppyy_PyBool_FromLong, PyLong_AsLong)
356CPPYY_IMPL_REFEXEC(Char, char, Long_t, CPyCppyy_PyText_FromLong, PyLong_AsLong)
358CPPYY_IMPL_REFEXEC(Int8, int8_t, Long_t, PyInt_FromLong, PyLong_AsLong)
360CPPYY_IMPL_REFEXEC(Short, short, Long_t, PyInt_FromLong, PyLong_AsLong)
362CPPYY_IMPL_REFEXEC(Int, Int_t, Long_t, PyInt_FromLong, PyLong_AsLong)
363CPPYY_IMPL_REFEXEC(UInt, UInt_t, ULong_t, PyLong_FromUnsignedLong, PyLongOrInt_AsULong)
364CPPYY_IMPL_REFEXEC(Long, Long_t, Long_t, PyLong_FromLong, PyLong_AsLong)
365CPPYY_IMPL_REFEXEC(ULong, ULong_t, ULong_t, PyLong_FromUnsignedLong, PyLongOrInt_AsULong)
366CPPYY_IMPL_REFEXEC(LongLong, Long64_t, Long64_t, PyLong_FromLongLong, PyLong_AsLongLong)
367CPPYY_IMPL_REFEXEC(ULongLong, ULong64_t, ULong64_t, PyLong_FromUnsignedLongLong, PyLongOrInt_AsULong64)
371
372template<typename T>
373static inline PyObject* PyComplex_FromComplex(const std::complex<T>& c) {
374 return PyComplex_FromDoubles(c.real(), c.imag());
375}
376
377template<typename T>
378static 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
383CPPYY_IMPL_REFEXEC(ComplexD, std::complex<double>,
384 std::complex<double>, PyComplex_FromComplex<double>, PyComplex_AsComplex<double>)
385
386
387//----------------------------------------------------------------------------
388PyObject* 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//----------------------------------------------------------------------------
406PyObject* CPyCppyy::VoidExecutor::Execute(
408{
409// execute <method> with argument <self, ctxt>, return None
410 GILCallV(method, self, ctxt);
412}
413
414//----------------------------------------------------------------------------
415PyObject* 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//----------------------------------------------------------------------------
429PyObject* 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//----------------------------------------------------------------------------
443PyObject* 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//----------------------------------------------------------------------------
458PyObject* 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 --------------------------------------------------
474PyObject* 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) \
488PyObject* 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
494CPPYY_IMPL_ARRAY_EXEC(Bool, bool)
495CPPYY_IMPL_ARRAY_EXEC(UChar, unsigned char)
496#if __cplusplus > 201402L
497CPPYY_IMPL_ARRAY_EXEC(Byte, std::byte)
498#endif
499CPPYY_IMPL_ARRAY_EXEC(Short, short)
500CPPYY_IMPL_ARRAY_EXEC(UShort, unsigned short)
501CPPYY_IMPL_ARRAY_EXEC(Int, int)
502CPPYY_IMPL_ARRAY_EXEC(UInt, unsigned int)
503CPPYY_IMPL_ARRAY_EXEC(Long, long)
504CPPYY_IMPL_ARRAY_EXEC(ULong, unsigned long)
505CPPYY_IMPL_ARRAY_EXEC(LLong, long long)
506CPPYY_IMPL_ARRAY_EXEC(ULLong, unsigned long long)
507CPPYY_IMPL_ARRAY_EXEC(Float, float)
508CPPYY_IMPL_ARRAY_EXEC(Double, double)
509CPPYY_IMPL_ARRAY_EXEC(ComplexF, std::complex<float>)
510CPPYY_IMPL_ARRAY_EXEC(ComplexD, std::complex<double>)
511CPPYY_IMPL_ARRAY_EXEC(ComplexI, std::complex<int>)
512CPPYY_IMPL_ARRAY_EXEC(ComplexL, std::complex<long>)
513
514
515//- special cases ------------------------------------------------------------
516#define CPPYY_COMPLEX_EXEC(code, type) \
517PyObject* 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
533CPPYY_COMPLEX_EXEC(D, double)
534
535//----------------------------------------------------------------------------
536PyObject* 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//----------------------------------------------------------------------------
557PyObject* 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//----------------------------------------------------------------------------
575PyObject* 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//----------------------------------------------------------------------------
583CPyCppyy::InstanceExecutor::InstanceExecutor(Cppyy::TCppType_t klass) :
584 fClass(klass), fFlags(CPPInstance::kIsValue | CPPInstance::kIsOwner)
585{
586 /* empty */
587}
588
589//----------------------------------------------------------------------------
590PyObject* 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; it will be
608// deleted b/c it is marked as a by-value object (unless C++ ownership is set)
609 return pyobj;
610}
611
612
613//----------------------------------------------------------------------------
614CPyCppyy::IteratorExecutor::IteratorExecutor(Cppyy::TCppType_t klass) :
615 InstanceExecutor(klass)
616{
617 fFlags |= CPPInstance::kNoWrapConv; // adds to flags from base class
618}
619
620
621//----------------------------------------------------------------------------
622PyObject* 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)",
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//----------------------------------------------------------------------------
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
674PyObject* 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,
686
687 CPPInstance* cppinst = (CPPInstance*)fAssignable;
688 *result = cppinst->GetObject();
689
690 Py_DECREF(fAssignable);
691 fAssignable = nullptr;
692
694}
695
696//----------------------------------------------------------------------------
697PyObject* 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//----------------------------------------------------------------------------
720PyObject* 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//----------------------------------------------------------------------------
730PyObject* 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//----------------------------------------------------------------------------
739PyObject* 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 ----------------------------------------------------------------
748CPyCppyy::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//----------------------------------------------------------------------------
845bool 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//----------------------------------------------------------------------------
858bool 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//----------------------------------------------------------------------------
878namespace {
879
880using namespace CPyCppyy;
881
882#define WSTRING "basic_string<wchar_t,char_traits<wchar_t>,allocator<wchar_t> >"
883
884struct InitExecFactories_t {
885public:
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
#define CPyCppyy_PyText_FromStringAndSize
Definition CPyCppyy.h:106
#define CPyCppyy_PyText_AsString
Definition CPyCppyy.h:97
#define CPyCppyy_PyText_GET_SIZE
Definition CPyCppyy.h:99
#define CPyCppyy_PyText_FromFormat
Definition CPyCppyy.h:101
Py_ssize_t dim_t
Definition CPyCppyy.h:64
#define Py_RETURN_NONE
Definition CPyCppyy.h:289
#define CPyCppyy_PyText_CheckExact
Definition CPyCppyy.h:96
#define CPyCppyy_PyText_FromString
Definition CPyCppyy.h:102
PyFloat_FromDouble
PyFloat_AsDouble
PyInt_FromLong
Cppyy::TCppType_t fClass
unsigned int fFlags
Py_ssize_t fArraySize
static PyObject * PyComplex_FromComplex(const std::complex< T > &c)
static PyObject * CPyCppyy_PyText_FromLong(long cl)
static PyObject * SetInstanceCheckError(PyObject *pyobj)
static std::complex< T > PyComplex_AsComplex(PyObject *pycplx)
static Cppyy::TCppObject_t GILCallO(Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, CPyCppyy::CallContext *ctxt, Cppyy::TCppType_t klass)
Definition Executors.cxx:80
#define CPPYY_IMPL_GILCALL(rtype, tcode)
Definition Executors.cxx:60
static Cppyy::TCppObject_t GILCallConstructor(Cppyy::TCppMethod_t method, Cppyy::TCppType_t klass, CPyCppyy::CallContext *ctxt)
Definition Executors.cxx:93
#define CPPYY_COMPLEX_EXEC(code, type)
static PyObject * CPyCppyy_PyText_FromULong(unsigned long uc)
static PyObject * CPyCppyy_PyBool_FromLong(long b)
#define CPPYY_IMPL_REFEXEC(name, type, stype, F1, F2)
#define CPPYY_IMPL_ARRAY_EXEC(name, type)
#define WSTRING
_object PyObject
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
unsigned long ULong_t
Definition RtypesCore.h:55
long Long_t
Definition RtypesCore.h:54
long double LongDouble_t
Definition RtypesCore.h:61
long long Long64_t
Definition RtypesCore.h:80
unsigned long long ULong64_t
Definition RtypesCore.h:81
char name[80]
Definition TGX11.cxx:110
#define CPYCPPYY_EXPORT
Definition CommonDefs.h:25
virtual bool HasState()
Definition API.h:132
virtual bool SetAssignable(PyObject *)
#define I(x, y, z)
#define H(x, y, z)
PyObject * gAssign
Definition PyStrings.cxx:7
PyObject * gEmptyString
Definition PyStrings.cxx:15
std::string remove_const(const std::string &cppname)
Definition TypeManip.cxx:71
std::string clean_type(const std::string &cppname, bool template_strip=true, bool const_strip=true)
Definition TypeManip.cxx:98
Py_ssize_t ArraySize(const std::string &name)
Definition Utility.cxx:806
const std::string Compound(const std::string &name)
Definition Utility.cxx:782
Set of helper functions that are invoked from the pythonizors, on the Python side.
unsigned long PyLongOrInt_AsULong(PyObject *pyobject)
Definition Utility.cxx:130
CPYCPPYY_EXTERN bool UnregisterExecutor(const std::string &name)
PyObject * CreatePointerView(void *ptr, size_t size=(size_t) -1)
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
CPYCPPYY_EXPORT void DestroyExecutor(Executor *p)
CPYCPPYY_EXTERN bool RegisterExecutor(const std::string &name, ExecutorFactory_t)
CPYCPPYY_EXTERN Executor * CreateExecutor(const std::string &name)
std::map< std::string, ef_t > ExecFactories_t
Definition Executors.cxx:23
bool CPPInstance_Check(T *object)
PyObject * gNullPtrObject
static ExecFactories_t gExecFactories
Definition Executors.cxx:24
std::set< std::string > gIteratorTypes
PyObject * BindCppObject(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
Executor *(* ef_t)()
Definition Executors.cxx:22
CPYCPPYY_EXTERN void * CallVoidP(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, CallContext *)
ULong64_t PyLongOrInt_AsULong64(PyObject *pyobject)
Definition Utility.cxx:150
bool ReleasesGIL(CallContext *ctxt)
PyObject * BindCppObjectArray(Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, Py_ssize_t *dims)
intptr_t TCppMethod_t
Definition cpp_cppyy.h:22
void * TCppObject_t
Definition cpp_cppyy.h:21
TCppScope_t TCppType_t
Definition cpp_cppyy.h:19
RPY_EXPORTED TCppObject_t CallO(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args, TCppType_t result_type)
size_t TCppScope_t
Definition cpp_cppyy.h:18
RPY_EXPORTED std::string ResolveName(const std::string &cppitem_name)
RPY_EXPORTED TCppObject_t CallConstructor(TCppMethod_t method, TCppType_t type, size_t nargs, void *args)
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
RooArgList L(Args_t &&... args)
Definition RooArgList.h:156
Parameter * GetArgs(size_t sz)
Definition CallContext.h:81