Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
CPyCppyyModule.cxx
Go to the documentation of this file.
1// Bindings
2#include "CPyCppyy.h"
3#include "CallContext.h"
4#include "Converters.h"
5#include "CPPDataMember.h"
6#include "CPPExcInstance.h"
7#include "CPPInstance.h"
8#include "CPPOverload.h"
9#include "CPPScope.h"
10#include "CustomPyTypes.h"
11#include "LowLevelViews.h"
12#include "MemoryRegulator.h"
13#include "ProxyWrappers.h"
14#include "PyStrings.h"
15#include "TemplateProxy.h"
16#include "TupleOfInstances.h"
17#include "Utility.h"
18
19#define CPYCPPYY_INTERNAL 1
21namespace CPyCppyy {
22void* Instance_AsVoidPtr(PyObject* pyobject);
24 void* addr, const std::string& classname, bool python_owns = false);
25} // namespace CPyCppyy
26#undef CPYCPPYY_INTERNAL
27
28// Standard
29#include <algorithm>
30#include <map>
31#include <set>
32#include <string>
33#include <iostream>
34#include <sstream>
35#include <utility>
36#include <vector>
37
38
39// Note: as of py3.11, dictionary objects no longer carry a function pointer for
40// the lookup, so it can no longer be shimmed and "from cppyy.interactive import *"
41// thus no longer works.
42#if PY_VERSION_HEX < 0x030b0000
43
44//- from Python's dictobject.c -------------------------------------------------
45#if PY_VERSION_HEX >= 0x03030000
46 typedef struct PyDictKeyEntry {
47 /* Cached hash code of me_key. */
48 Py_hash_t me_hash;
49 PyObject *me_key;
50 PyObject *me_value; /* This field is only meaningful for combined tables */
51 } PyDictEntry;
52
53 typedef struct _dictkeysobject {
54 Py_ssize_t dk_refcnt;
55 Py_ssize_t dk_size;
56 dict_lookup_func dk_lookup;
57 Py_ssize_t dk_usable;
58#if PY_VERSION_HEX >= 0x03060000
59 Py_ssize_t dk_nentries;
60 union {
61 int8_t as_1[8];
62 int16_t as_2[4];
63 int32_t as_4[2];
64#if SIZEOF_VOID_P > 4
65 int64_t as_8[1];
66#endif
67 } dk_indices;
68#else
69 PyDictKeyEntry dk_entries[1];
70#endif
71 } PyDictKeysObject;
72
73#define CPYCPPYY_GET_DICT_LOOKUP(mp) \
74 ((dict_lookup_func&)mp->ma_keys->dk_lookup)
75
76#else
77
78#define CPYCPPYY_GET_DICT_LOOKUP(mp) \
79 ((dict_lookup_func&)mp->ma_lookup)
80
81#endif
82
83#endif // PY_VERSION_HEX < 0x030b0000
84
85//- data -----------------------------------------------------------------------
87{
88 return CPyCppyy_PyText_FromString("nullptr");
89}
90
92{
93 Py_FatalError("deallocating nullptr");
94}
95
97{
98 return 0;
99}
100
101static PyNumberMethods nullptr_as_number = {
102 0, 0, 0,
103#if PY_VERSION_HEX < 0x03000000
104 0,
105#endif
106 0, 0, 0, 0, 0, 0,
107 (inquiry)nullptr_nonzero, // tp_nonzero (nb_bool in p3)
108 0, 0, 0, 0, 0, 0,
109#if PY_VERSION_HEX < 0x03000000
110 0, // nb_coerce
111#endif
112 0, 0, 0,
113#if PY_VERSION_HEX < 0x03000000
114 0, 0,
115#endif
116 0, 0, 0,
117#if PY_VERSION_HEX < 0x03000000
118 0, // nb_inplace_divide
119#endif
120 0, 0, 0, 0, 0, 0, 0
121#if PY_VERSION_HEX >= 0x02020000
122 , 0 // nb_floor_divide
123#if PY_VERSION_HEX < 0x03000000
124 , 0 // nb_true_divide
125#else
126 , 0 // nb_true_divide
127#endif
128 , 0, 0
129#endif
130#if PY_VERSION_HEX >= 0x02050000
131 , 0 // nb_index
132#endif
133#if PY_VERSION_HEX >= 0x03050000
134 , 0 // nb_matrix_multiply
135 , 0 // nb_inplace_matrix_multiply
136#endif
137};
138
139static PyTypeObject PyNullPtr_t_Type = {
140 PyVarObject_HEAD_INIT(&PyType_Type, 0)
141 "nullptr_t", // tp_name
142 sizeof(PyObject), // tp_basicsize
143 0, // tp_itemsize
144 nullptr_dealloc, // tp_dealloc (never called)
145 0, 0, 0, 0,
146 nullptr_repr, // tp_repr
147 &nullptr_as_number, // tp_as_number
148 0, 0,
149 (hashfunc)_Py_HashPointer, // tp_hash
150 0, 0, 0, 0, 0, Py_TPFLAGS_DEFAULT, 0, 0, 0, 0, 0, 0, 0,
151 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
152#if PY_VERSION_HEX >= 0x02030000
153 , 0 // tp_del
154#endif
155#if PY_VERSION_HEX >= 0x02060000
156 , 0 // tp_version_tag
157#endif
158#if PY_VERSION_HEX >= 0x03040000
159 , 0 // tp_finalize
160#endif
161#if PY_VERSION_HEX >= 0x03080000
162 , 0 // tp_vectorcall
163#endif
164};
165
166
168{
169 return CPyCppyy_PyText_FromString("type default");
170}
171
173{
174 Py_FatalError("deallocating default");
175}
176
177static PyTypeObject PyDefault_t_Type = {
178 PyVarObject_HEAD_INIT(&PyType_Type, 0)
179 "default_t", // tp_name
180 sizeof(PyObject), // tp_basicsize
181 0, // tp_itemsize
182 default_dealloc, // tp_dealloc (never called)
183 0, 0, 0, 0,
184 default_repr, // tp_repr
185 0, 0, 0,
186 (hashfunc)_Py_HashPointer, // tp_hash
187 0, 0, 0, 0, 0, Py_TPFLAGS_DEFAULT, 0, 0, 0, 0, 0, 0, 0,
188 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
189#if PY_VERSION_HEX >= 0x02030000
190 , 0 // tp_del
191#endif
192#if PY_VERSION_HEX >= 0x02060000
193 , 0 // tp_version_tag
194#endif
195#if PY_VERSION_HEX >= 0x03040000
196 , 0 // tp_finalize
197#endif
198#if PY_VERSION_HEX >= 0x03080000
199 , 0 // tp_vectorcall
200#endif
201};
202
203namespace {
204
205PyObject _CPyCppyy_NullPtrStruct = {
206 _PyObject_EXTRA_INIT
208};
209
210PyObject _CPyCppyy_DefaultStruct = {
211 _PyObject_EXTRA_INIT
213};
214
215// TODO: refactor with Converters.cxx
216struct CPyCppyy_tagCDataObject { // non-public (but stable)
217 PyObject_HEAD
218 char* b_ptr;
219 int b_needsfree;
220};
221
222} // unnamed namespace
223
224namespace CPyCppyy {
225 PyObject* gThisModule = nullptr;
227 PyObject* gNullPtrObject = nullptr;
233 std::map<std::string, std::vector<PyObject*>> gPythonizations;
234 std::set<Cppyy::TCppType_t> gPinnedTypes;
235 std::ostringstream gCapturedError;
236 std::streambuf* gOldErrorBuffer = nullptr;
237}
238
239
240//- private helpers ------------------------------------------------------------
241namespace {
242
243using namespace CPyCppyy;
244
245
246//----------------------------------------------------------------------------
247#if PY_VERSION_HEX < 0x030b0000
248namespace {
249
250class GblGetter {
251public:
252 GblGetter() {
253 PyObject* cppyy = PyImport_AddModule((char*)"cppyy");
254 fGbl = PyObject_GetAttrString(cppyy, (char*)"gbl");
255 }
256 ~GblGetter() { Py_DECREF(fGbl); }
257
258 PyObject* operator*() { return fGbl; }
259
260private:
261 PyObject* fGbl;
262};
263
264} // unnamed namespace
265
266#if PY_VERSION_HEX >= 0x03060000
267inline Py_ssize_t OrgDictLookup(PyDictObject* mp, PyObject* key,
268 Py_hash_t hash, PyObject*** value_addr, Py_ssize_t* hashpos)
269{
270 return (*gDictLookupOrg)(mp, key, hash, value_addr, hashpos);
271}
272#define CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos) \
273 OrgDictLookup(mp, key, hash, value_addr, hashpos)
274
275Py_ssize_t CPyCppyyLookDictString(PyDictObject* mp, PyObject* key,
276 Py_hash_t hash, PyObject*** value_addr, Py_ssize_t* hashpos)
277
278#elif PY_VERSION_HEX >= 0x03030000
279inline PyDictKeyEntry* OrgDictLookup(
280 PyDictObject* mp, PyObject* key, Py_hash_t hash, PyObject*** value_addr)
281{
282 return (*gDictLookupOrg)(mp, key, hash, value_addr);
283}
284
285#define CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos) \
286 OrgDictLookup(mp, key, hash, value_addr)
287
288PyDictKeyEntry* CPyCppyyLookDictString(
289 PyDictObject* mp, PyObject* key, Py_hash_t hash, PyObject*** value_addr)
290
291#else /* < 3.3 */
292
293inline PyDictEntry* OrgDictLookup(PyDictObject* mp, PyObject* key, long hash)
294{
295 return (*gDictLookupOrg)(mp, key, hash);
296}
297
298#define CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos) \
299 OrgDictLookup(mp, key, hash)
300
301PyDictEntry* CPyCppyyLookDictString(PyDictObject* mp, PyObject* key, long hash)
302#endif
303{
304 static GblGetter gbl;
305#if PY_VERSION_HEX >= 0x03060000
306 Py_ssize_t ep;
307#else
308 PyDictEntry* ep;
309#endif
310
311// first search dictionary itself
312 ep = CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos);
314 return ep;
315
316#if PY_VERSION_HEX >= 0x03060000
317 if (ep >= 0)
318#else
319 if (!ep || (ep->me_key && ep->me_value))
320#endif
321 return ep;
322
323// filter for builtins
324 if (PyDict_GetItem(PyEval_GetBuiltins(), key) != 0)
325 return ep;
326
327// normal lookup failed, attempt to get C++ enum/global/class from top-level
328 gDictLookupActive = true;
329
330// attempt to get C++ enum/global/class from top-level
331 PyObject* val = PyObject_GetAttr(*gbl, key);
332
333 if (val) {
334 // success ...
335
336 if (CPPDataMember_CheckExact(val)) {
337 // don't want to add to dictionary (the proper place would be the
338 // dictionary of the (meta)class), but modifying ep will be noticed no
339 // matter what; just return the actual value and live with the copy in
340 // the dictionary (mostly, this is correct)
341 PyObject* actual_val = Py_TYPE(val)->tp_descr_get(val, nullptr, nullptr);
342 Py_DECREF(val);
343 val = actual_val;
344 }
345
346 // add reference to C++ entity in the given dictionary
347 CPYCPPYY_GET_DICT_LOOKUP(mp) = gDictLookupOrg; // prevent recursion
348 if (PyDict_SetItem((PyObject*)mp, key, val) == 0) {
349 ep = CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos);
350 } else {
351#if PY_VERSION_HEX >= 0x03060000
352 ep = -1;
353#else
354 ep->me_key = nullptr;
355 ep->me_value = nullptr;
356#endif
357 }
358 CPYCPPYY_GET_DICT_LOOKUP(mp) = CPyCppyyLookDictString; // restore
359
360 // done with val
361 Py_DECREF(val);
362 } else
363 PyErr_Clear();
364
365#if PY_VERSION_HEX >= 0x03030000
366 if (mp->ma_keys->dk_usable <= 0) {
367 // big risk that this lookup will result in a resize, so force it here
368 // to be able to reset the lookup function; of course, this is nowhere
369 // near fool-proof, but should cover interactive usage ...
371 const int maxinsert = 5;
372 PyObject* buf[maxinsert];
373 for (int varmax = 1; varmax <= maxinsert; ++varmax) {
374 for (int ivar = 0; ivar < varmax; ++ivar) {
375 buf[ivar] = CPyCppyy_PyText_FromFormat("__CPYCPPYY_FORCE_RESIZE_%d", ivar);
376 PyDict_SetItem((PyObject*)mp, buf[ivar], Py_None);
377 }
378 for (int ivar = 0; ivar < varmax; ++ivar) {
379 PyDict_DelItem((PyObject*)mp, buf[ivar]);
380 Py_DECREF(buf[ivar]);
381 }
382 if (0 < mp->ma_keys->dk_usable)
383 break;
384 }
385
386 // make sure the entry pointer is still valid by re-doing the lookup
387 ep = CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos);
388
389 // full reset of all lookup functions
391 CPYCPPYY_GET_DICT_LOOKUP(mp) = CPyCppyyLookDictString; // restore
392 }
393#endif
394
395// stopped calling into the reflection system
396 gDictLookupActive = false;
397 return ep;
398}
399
400#endif // PY_VERSION_HEX < 0x030b0000
401
402//----------------------------------------------------------------------------
403static PyObject* SetCppLazyLookup(PyObject*, PyObject* args)
404{
405#if PY_VERSION_HEX < 0x030b0000
406// Modify the given dictionary to install the lookup function that also
407// tries the global C++ namespace before failing. Called on a module's dictionary,
408// this allows for lazy lookups. This works fine for p3.2 and earlier, but should
409// not be used beyond interactive code for p3.3 and later b/c resizing causes the
410// lookup function to revert to the default (lookdict_unicode_nodummy).
411 PyDictObject* dict = nullptr;
412 if (!PyArg_ParseTuple(args, const_cast<char*>("O!"), &PyDict_Type, &dict))
413 return nullptr;
414
415 CPYCPPYY_GET_DICT_LOOKUP(dict) = CPyCppyyLookDictString;
416#else
417// As of py3.11, there is no longer a lookup function pointer in the dict object
418// to replace. Since this feature is not widely advertised, it's simply dropped
419 PyErr_Warn(PyExc_RuntimeWarning, (char*)"lazy lookup is no longer supported");
420 (void)args; // avoid warning about unused parameter
421#endif
422
424}
425
426//----------------------------------------------------------------------------
427static PyObject* MakeCppTemplateClass(PyObject*, PyObject* args)
428{
429// Create a binding for a templated class instantiation.
430
431// args is class name + template arguments; build full instantiation
432 Py_ssize_t nArgs = PyTuple_GET_SIZE(args);
433 if (nArgs < 2) {
434 PyErr_Format(PyExc_TypeError, "too few arguments for template instantiation");
435 return nullptr;
436 }
437
438// build "< type, type, ... >" part of class name (modifies pyname)
439 const std::string& tmpl_name =
440 Utility::ConstructTemplateArgs(PyTuple_GET_ITEM(args, 0), args, nullptr, Utility::kNone, 1);
441 if (!tmpl_name.size())
442 return nullptr;
443
444 return CreateScopeProxy(tmpl_name);
445}
446
447//----------------------------------------------------------------------------
448static char* GCIA_kwlist[] = {(char*)"instance", (char*)"field", (char*)"byref", NULL};
449static void* GetCPPInstanceAddress(const char* fname, PyObject* args, PyObject* kwds)
450{
451// Helper to get the address (address-of-address) of various object proxy types.
452 CPPInstance* pyobj = 0; PyObject* pyname = 0; int byref = 0;
453 if (PyArg_ParseTupleAndKeywords(args, kwds, const_cast<char*>("O|O!b"), GCIA_kwlist,
454 &pyobj, &CPyCppyy_PyText_Type, &pyname, &byref)) {
455
456 if (CPPInstance_Check(pyobj)) {
457 if (pyname != 0) {
458 // locate property proxy for offset info
459 CPPDataMember* pyprop = nullptr;
460
461 PyObject* pyclass = (PyObject*)Py_TYPE((PyObject*)pyobj);
462 PyObject* dict = PyObject_GetAttr(pyclass, PyStrings::gDict);
463 pyprop = (CPPDataMember*)PyObject_GetItem(dict, pyname);
464 Py_DECREF(dict);
465
466 if (CPPDataMember_Check(pyprop)) {
467 // this is an address of a value (i.e. &myobj->prop)
468 void* addr = (void*)pyprop->GetAddress(pyobj);
469 Py_DECREF(pyprop);
470 return addr;
471 }
472
473 Py_XDECREF(pyprop);
474
475 PyErr_Format(PyExc_TypeError,
476 "%s is not a valid data member", CPyCppyy_PyText_AsString(pyname));
477 return nullptr;
478 }
479
480 // this is an address of an address (i.e. &myobj, with myobj of type MyObj*)
481 // note that the return result may be null
482 if (!byref) return ((CPPInstance*)pyobj)->GetObject();
483 return &((CPPInstance*)pyobj)->GetObjectRaw();
484
485 } else if (CPyCppyy_PyText_Check(pyobj)) {
486 // special cases for access to the CPyCppyy API
487 std::string req = CPyCppyy_PyText_AsString((PyObject*)pyobj);
488 if (req == "Instance_AsVoidPtr")
489 return (void*)&Instance_AsVoidPtr;
490 else if (req == "Instance_FromVoidPtr")
491 return (void*)&Instance_FromVoidPtr;
492 }
493 }
494
495 if (!PyErr_Occurred())
496 PyErr_Format(PyExc_ValueError, "invalid argument for %s", fname);
497 return nullptr;
498}
499
500//----------------------------------------------------------------------------
501static PyObject* addressof(PyObject* /* dummy */, PyObject* args, PyObject* kwds)
502{
503// Return object proxy address as a value (cppyy-style), or the same for an array.
504 void* addr = GetCPPInstanceAddress("addressof", args, kwds);
505 if (addr)
506 return PyLong_FromLongLong((intptr_t)addr);
507 else if (!PyErr_Occurred()) {
508 return PyLong_FromLong(0);
509 } else if (PyTuple_CheckExact(args) && PyTuple_GET_SIZE(args) == 1) {
510 PyErr_Clear();
511 PyObject* arg0 = PyTuple_GET_ITEM(args, 0);
512
513 // nullptr special case
514 if (arg0 == gNullPtrObject || (PyInt_Check(arg0) && PyInt_AsLong(arg0) == 0))
515 return PyLong_FromLong(0);
516
517 // overload if unambiguous
518 if (CPPOverload_CheckExact(arg0)) {
519 const auto& methods = ((CPPOverload*)arg0)->fMethodInfo->fMethods;
520 if (methods.size() != 1) {
521 PyErr_SetString(PyExc_TypeError, "overload is not unambiguous");
522 return nullptr;
523 }
524
525 Cppyy::TCppFuncAddr_t caddr = methods[0]->GetFunctionAddress();
526 return PyLong_FromLongLong((intptr_t)caddr);
527 }
528
529 // C functions (incl. ourselves)
530 if (PyCFunction_Check(arg0)) {
531 void* caddr = (void*)PyCFunction_GetFunction(arg0);
532 return PyLong_FromLongLong((intptr_t)caddr);
533 }
534
535 // final attempt: any type of buffer
536 Utility::GetBuffer(arg0, '*', 1, addr, false);
537 if (addr) return PyLong_FromLongLong((intptr_t)addr);
538 }
539
540// error message if not already set
541 if (!PyErr_Occurred()) {
542 if (PyTuple_CheckExact(args) && PyTuple_GET_SIZE(args)) {
543 PyObject* str = PyObject_Str(PyTuple_GET_ITEM(args, 0));
544 if (str && CPyCppyy_PyText_Check(str))
545 PyErr_Format(PyExc_TypeError, "unknown object %s", CPyCppyy_PyText_AsString(str));
546 else
547 PyErr_Format(PyExc_TypeError, "unknown object at %p", (void*)PyTuple_GET_ITEM(args, 0));
548 Py_XDECREF(str);
549 }
550 }
551 return nullptr;
552}
553
554//----------------------------------------------------------------------------
555static PyObject* AsCObject(PyObject* /* unused */, PyObject* args, PyObject* kwds)
556{
557// Return object proxy as an opaque CObject.
558 void* addr = GetCPPInstanceAddress("as_cobject", args, kwds);
559 if (addr)
560 return CPyCppyy_PyCapsule_New((void*)addr, nullptr, nullptr);
561 return nullptr;
562}
563
564//----------------------------------------------------------------------------
565static PyObject* AsCapsule(PyObject* /* unused */, PyObject* args, PyObject* kwds)
566{
567// Return object proxy as an opaque PyCapsule.
568 void* addr = GetCPPInstanceAddress("as_capsule", args, kwds);
569 if (addr)
570#if PY_VERSION_HEX < 0x02060000
571 return PyCObject_FromVoidPtr(addr, nullptr);
572#else
573 return PyCapsule_New(addr, nullptr, nullptr);
574#endif
575 return nullptr;
576}
577
578//----------------------------------------------------------------------------
579static PyObject* AsCTypes(PyObject* /* unused */, PyObject* args, PyObject* kwds)
580{
581// Return object proxy as a ctypes c_void_p
582 void* addr = GetCPPInstanceAddress("as_ctypes", args, kwds);
583 if (!addr)
584 return nullptr;
585
586// TODO: refactor code below with converters code
587 static PyTypeObject* ct_cvoidp = nullptr;
588 if (!ct_cvoidp) {
589 PyObject* ctmod = PyImport_ImportModule("ctypes"); // ref-count kept
590 if (!ctmod) return nullptr;
591
592 ct_cvoidp = (PyTypeObject*)PyObject_GetAttrString(ctmod, "c_void_p");
593 Py_DECREF(ctmod);
594 if (!ct_cvoidp) return nullptr;
595 Py_DECREF(ct_cvoidp); // module keeps a reference
596 }
597
598 PyObject* ref = ct_cvoidp->tp_new(ct_cvoidp, nullptr, nullptr);
599 *(void**)((CPyCppyy_tagCDataObject*)ref)->b_ptr = addr;
600 ((CPyCppyy_tagCDataObject*)ref)->b_needsfree = 0;
601 return ref;
602}
603
604//----------------------------------------------------------------------------
605static PyObject* AsMemoryView(PyObject* /* unused */, PyObject* pyobject)
606{
607// Return a raw memory view on arrays of PODs.
608 if (!CPPInstance_Check(pyobject)) {
609 PyErr_SetString(PyExc_TypeError, "C++ object proxy expected");
610 return nullptr;
611 }
612
613 CPPInstance* pyobj = (CPPInstance*)pyobject;
614 Cppyy::TCppType_t klass = ((CPPClass*)Py_TYPE(pyobject))->fCppType;
615
616 Py_ssize_t array_len = pyobj->ArrayLength();
617
618 if (array_len < 0 || !Cppyy::IsAggregate(klass)) {
619 PyErr_SetString(
620 PyExc_TypeError, "object is not a proxy to an array of PODs of known size");
621 return nullptr;
622 }
623
624 Py_buffer view;
625
626 view.obj = pyobject;
627 view.buf = pyobj->GetObject();
628 view.itemsize = Cppyy::SizeOf(klass);
629 view.len = view.itemsize * array_len;
630 view.readonly = 0;
631 view.format = NULL; // i.e. "B" assumed
632 view.ndim = 1;
633 view.shape = NULL;
634 view.strides = NULL;
635 view.suboffsets = NULL;
636 view.internal = NULL;
637
638 return PyMemoryView_FromBuffer(&view);
639}
640
641//----------------------------------------------------------------------------
642static PyObject* BindObject(PyObject*, PyObject* args, PyObject* kwds)
643{
644// From a long representing an address or a PyCapsule/CObject, bind to a class.
645 Py_ssize_t argc = PyTuple_GET_SIZE(args);
646 if (argc != 2) {
647 PyErr_Format(PyExc_TypeError,
648 "bind_object takes 2 positional arguments but (" PY_SSIZE_T_FORMAT " were given)", argc);
649 return nullptr;
650 }
651
652// convert 2nd argument first (used for both pointer value and instance cases)
653 Cppyy::TCppType_t cast_type = 0;
654 PyObject* arg1 = PyTuple_GET_ITEM(args, 1);
655 if (!CPyCppyy_PyText_Check(arg1)) { // not string, then class
656 if (CPPScope_Check(arg1))
657 cast_type = ((CPPClass*)arg1)->fCppType;
658 else
659 arg1 = PyObject_GetAttr(arg1, PyStrings::gName);
660 } else
661 Py_INCREF(arg1);
662
663 if (!cast_type && arg1) {
665 Py_DECREF(arg1);
666 }
667
668 if (!cast_type) {
669 PyErr_SetString(PyExc_TypeError,
670 "bind_object expects a valid class or class name as an argument");
671 return nullptr;
672 }
673
674// next, convert the first argument, some pointer value or a pre-existing instance
675 PyObject* arg0 = PyTuple_GET_ITEM(args, 0);
676
677 if (CPPInstance_Check(arg0)) {
678 // if this instance's class has a relation to the requested one, calculate the
679 // offset, erase if from any caches, and update the pointer and type
680 CPPInstance* arg0_pyobj = (CPPInstance*)arg0;
681 Cppyy::TCppType_t cur_type = arg0_pyobj->ObjectIsA(false /* check_smart */);
682
683 bool isPython = CPPScope_Check(arg1) && \
684 (((CPPClass*)arg1)->fFlags & CPPScope::kIsPython);
685
686 if (cur_type == cast_type && !isPython) {
687 Py_INCREF(arg0); // nothing to do
688 return arg0;
689 }
690
691 int direction = 0;
692 Cppyy::TCppType_t base = 0, derived = 0;
693 if (Cppyy::IsSubtype(cast_type, cur_type)) {
694 derived = cast_type;
695 base = cur_type;
696 direction = -1; // down-cast
697 } else if (Cppyy::IsSubtype(cur_type, cast_type)) {
698 base = cast_type;
699 derived = cur_type;
700 direction = 1; // up-cast
701 } else {
702 PyErr_SetString(PyExc_TypeError,
703 "provided instance and provided target type are unrelated");
704 return nullptr;
705 }
706
707 Cppyy::TCppObject_t address = (Cppyy::TCppObject_t)arg0_pyobj->GetObject();
708 ptrdiff_t offset = Cppyy::GetBaseOffset(derived, base, address, direction);
709
710 // it's debatable whether a new proxy should be created rather than updating
711 // the old, but changing the old object would be changing the behavior of all
712 // code that has a reference to it, which may not be the intention if the cast
713 // is on a C++ data member; this probably is the "least surprise" option
714
715 // ownership is taken over as needed, again following the principle of "least
716 // surprise" as most likely only the cast object will be retained
717 bool owns = arg0_pyobj->fFlags & CPPInstance::kIsOwner;
718
719 if (!isPython) {
720 // ordinary C++ class
722 (void*)((intptr_t)address + offset), cast_type, owns ? CPPInstance::kIsOwner : 0);
723 if (owns && pyobj) arg0_pyobj->CppOwns();
724 return pyobj;
725
726 } else {
727 // rebinding to a Python-side class, create a fresh instance first to be able to
728 // perform a lookup of the original dispatch object and if found, return original
729 void* cast_address = (void*)((intptr_t)address + offset);
730 PyObject* pyobj = ((PyTypeObject*)arg1)->tp_new((PyTypeObject*)arg1, nullptr, nullptr);
731 ((CPPInstance*)pyobj)->GetObjectRaw() = cast_address;
732
733 PyObject* dispproxy = CPyCppyy::GetScopeProxy(cast_type);
734 PyObject* res = PyObject_CallMethodOneArg(dispproxy, PyStrings::gDispGet, pyobj);
735 /* Note: the resultant object is borrowed */
736 if (CPPInstance_Check(res) && ((CPPInstance*)res)->GetObject() == cast_address) {
737 ((CPPInstance*)pyobj)->CppOwns(); // make sure C++ object isn't deleted
738 Py_DECREF(pyobj); // on DECREF (is default, but still)
739 pyobj = res;
740 } else {
741 if (res) Py_DECREF(res); // most likely Py_None
742 else PyErr_Clear(); // should not happen
743 }
744 Py_DECREF(dispproxy);
745
746 if (pyobj && owns) {
747 arg0_pyobj->CppOwns();
748 ((CPPInstance*)pyobj)->PythonOwns();
749 }
750
751 return pyobj;
752 }
753 }
754
755// not a pre-existing object; get the address and bind
756 void* addr = nullptr;
757 if (arg0 != &_CPyCppyy_NullPtrStruct) {
758 addr = CPyCppyy_PyCapsule_GetPointer(arg0, nullptr);
759 if (PyErr_Occurred()) {
760 PyErr_Clear();
761
762 addr = PyLong_AsVoidPtr(arg0);
763 if (PyErr_Occurred()) {
764 PyErr_Clear();
765
766 // last chance, perhaps it's a buffer/array (return from void*)
767 Py_ssize_t buflen = Utility::GetBuffer(PyTuple_GetItem(args, 0), '*', 1, addr, false);
768 if (!addr || !buflen) {
769 PyErr_SetString(PyExc_TypeError,
770 "bind_object requires a CObject/Capsule, long integer, buffer, or instance as first argument");
771 return nullptr;
772 }
773 }
774 }
775 }
776
777 bool do_cast = false;
778 if (kwds) {
779 PyObject* cast = PyDict_GetItemString(kwds, "cast");
780 do_cast = cast && PyObject_IsTrue(cast);
781 }
782
783 if (do_cast)
784 return BindCppObject(addr, cast_type);
785
786 return BindCppObjectNoCast(addr, cast_type);
787}
788
789//----------------------------------------------------------------------------
790static PyObject* Move(PyObject*, PyObject* pyobject)
791{
792// Prepare the given C++ object for moving.
793 if (!CPPInstance_Check(pyobject)) {
794 PyErr_SetString(PyExc_TypeError, "C++ object expected");
795 return nullptr;
796 }
797
798 ((CPPInstance*)pyobject)->fFlags |= CPPInstance::kIsRValue;
799 Py_INCREF(pyobject);
800 return pyobject;
801}
802
803
804//----------------------------------------------------------------------------
805static PyObject* AddPythonization(PyObject*, PyObject* args)
806{
807// Remove a previously registered pythonizor from the given scope.
808 PyObject* pythonizor = nullptr; const char* scope;
809 if (!PyArg_ParseTuple(args, const_cast<char*>("Os"), &pythonizor, &scope))
810 return nullptr;
811
812 if (!PyCallable_Check(pythonizor)) {
813 PyObject* pystr = PyObject_Str(pythonizor);
814 PyErr_Format(PyExc_TypeError,
815 "given \'%s\' object is not callable", CPyCppyy_PyText_AsString(pystr));
816 Py_DECREF(pystr);
817 return nullptr;
818 }
819
820 Py_INCREF(pythonizor);
821 gPythonizations[scope].push_back(pythonizor);
822
824}
825
826
827//----------------------------------------------------------------------------
828static PyObject* RemovePythonization(PyObject*, PyObject* args)
829{
830// Remove a previously registered pythonizor from the given scope.
831 PyObject* pythonizor = nullptr; const char* scope;
832 if (!PyArg_ParseTuple(args, const_cast<char*>("Os"), &pythonizor, &scope))
833 return nullptr;
834
835 auto p1 = gPythonizations.find(scope);
836 if (p1 != gPythonizations.end()) {
837 auto p2 = std::find(p1->second.begin(), p1->second.end(), pythonizor);
838 if (p2 != p1->second.end()) {
839 p1->second.erase(p2);
841 }
842 }
843
845}
846
847//----------------------------------------------------------------------------
848static PyObject* PinType(PyObject*, PyObject* pyclass)
849{
850// Add a pinning so that objects of type `derived' are interpreted as
851// objects of type `base'.
852 if (!CPPScope_Check(pyclass)) {
853 PyErr_SetString(PyExc_TypeError, "C++ class expected");
854 return nullptr;
855 }
856
857 gPinnedTypes.insert(((CPPClass*)pyclass)->fCppType);
858
860}
861
862//----------------------------------------------------------------------------
864{
865// Add a type reducer to map type2 to type2 on function returns.
866 const char *reducable, *reduced;
867 if (!PyArg_ParseTuple(args, const_cast<char*>("ss"), &reducable, &reduced))
868 return nullptr;
869
870 Cppyy::AddTypeReducer(reducable, reduced);
871
873}
874
875//----------------------------------------------------------------------------
876static PyObject* SetMemoryPolicy(PyObject*, PyObject* args)
877{
878// Set the global memory policy, which affects object ownership when objects
879// are passed as function arguments.
880 PyObject* policy = nullptr;
881 if (!PyArg_ParseTuple(args, const_cast<char*>("O!"), &PyInt_Type, &policy))
882 return nullptr;
883
884 long l = PyInt_AS_LONG(policy);
887 }
888
889 PyErr_Format(PyExc_ValueError, "Unknown policy %ld", l);
890 return nullptr;
891}
892
893//----------------------------------------------------------------------------
894static PyObject* SetGlobalSignalPolicy(PyObject*, PyObject* args)
895{
896// Set the global signal policy, which determines whether a jmp address
897// should be saved to return to after a C++ segfault.
898 PyObject* setProtected = 0;
899 if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &setProtected))
900 return nullptr;
901
902 if (CallContext::SetGlobalSignalPolicy(PyObject_IsTrue(setProtected))) {
904 }
905
907}
908
909//----------------------------------------------------------------------------
910static PyObject* SetOwnership(PyObject*, PyObject* args)
911{
912// Set the ownership (True is python-owns) for the given object.
913 CPPInstance* pyobj = nullptr; PyObject* pykeep = nullptr;
914 if (!PyArg_ParseTuple(args, const_cast<char*>("O!O!"),
915 &CPPInstance_Type, (void*)&pyobj, &PyInt_Type, &pykeep))
916 return nullptr;
917
918 (bool)PyLong_AsLong(pykeep) ? pyobj->PythonOwns() : pyobj->CppOwns();
919
921}
922
923//----------------------------------------------------------------------------
925{
926// Add a smart pointer to the list of known smart pointer types.
927 const char* type_name;
928 if (!PyArg_ParseTuple(args, const_cast<char*>("s"), &type_name))
929 return nullptr;
930
931 Cppyy::AddSmartPtrType(type_name);
932
934}
935
936//----------------------------------------------------------------------------
937static PyObject* BeginCaptureStderr(PyObject*, PyObject*)
938{
939 gOldErrorBuffer = std::cerr.rdbuf();
940 std::cerr.rdbuf(gCapturedError.rdbuf());
941
943}
944
945//----------------------------------------------------------------------------
946static PyObject* EndCaptureStderr(PyObject*, PyObject*)
947{
948// restore old rdbuf and return captured result
949 std::cerr.rdbuf(gOldErrorBuffer);
950 gOldErrorBuffer = nullptr;
951
952 std::string capturedError = std::move(gCapturedError).str();
953
954 gCapturedError.str("");
955 gCapturedError.clear();
956
957 return Py_BuildValue("s", capturedError.c_str());
958}
959} // unnamed namespace
960
961
962//- data -----------------------------------------------------------------------
963static PyMethodDef gCPyCppyyMethods[] = {
964 {(char*) "CreateScopeProxy", (PyCFunction)CPyCppyy::CreateScopeProxy,
965 METH_VARARGS, (char*)"cppyy internal function"},
966 {(char*) "MakeCppTemplateClass", (PyCFunction)MakeCppTemplateClass,
967 METH_VARARGS, (char*)"cppyy internal function"},
968 {(char*) "_set_cpp_lazy_lookup", (PyCFunction)SetCppLazyLookup,
969 METH_VARARGS, (char*)"cppyy internal function"},
970 {(char*) "_DestroyPyStrings", (PyCFunction)CPyCppyy::DestroyPyStrings,
971 METH_NOARGS, (char*)"cppyy internal function"},
972 {(char*) "addressof", (PyCFunction)addressof,
973 METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field as a value."},
974 {(char*) "as_cobject", (PyCFunction)AsCObject,
975 METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field in a CObject."},
976 {(char*) "as_capsule", (PyCFunction)AsCapsule,
977 METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field in a PyCapsule."},
978 {(char*) "as_ctypes", (PyCFunction)AsCTypes,
979 METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field in a ctypes c_void_p."},
980 {(char*) "as_memoryview", (PyCFunction)AsMemoryView,
981 METH_O, (char*)"Represent an array of objects as raw memory."},
982 {(char*)"bind_object", (PyCFunction)BindObject,
983 METH_VARARGS | METH_KEYWORDS, (char*) "Create an object of given type, from given address."},
984 {(char*) "move", (PyCFunction)Move,
985 METH_O, (char*)"Cast the C++ object to become movable."},
986 {(char*) "add_pythonization", (PyCFunction)AddPythonization,
987 METH_VARARGS, (char*)"Add a pythonizor."},
988 {(char*) "remove_pythonization", (PyCFunction)RemovePythonization,
989 METH_VARARGS, (char*)"Remove a pythonizor."},
990 {(char*) "_pin_type", (PyCFunction)PinType,
991 METH_O, (char*)"Install a type pinning."},
992 {(char*) "_add_type_reducer", (PyCFunction)AddTypeReducer,
993 METH_VARARGS, (char*)"Add a type reducer."},
994 {(char*) "SetMemoryPolicy", (PyCFunction)SetMemoryPolicy,
995 METH_VARARGS, (char*)"Determines object ownership model."},
996 {(char*) "SetGlobalSignalPolicy", (PyCFunction)SetGlobalSignalPolicy,
997 METH_VARARGS, (char*)"Trap signals in safe mode to prevent interpreter abort."},
998 {(char*) "SetOwnership", (PyCFunction)SetOwnership,
999 METH_VARARGS, (char*)"Modify held C++ object ownership."},
1000 {(char*) "AddSmartPtrType", (PyCFunction)AddSmartPtrType,
1001 METH_VARARGS, (char*) "Add a smart pointer to the list of known smart pointer types."},
1002 {(char*) "_begin_capture_stderr", (PyCFunction)BeginCaptureStderr,
1003 METH_NOARGS, (char*) "Begin capturing stderr to a in memory buffer."},
1004 {(char*) "_end_capture_stderr", (PyCFunction)EndCaptureStderr,
1005 METH_NOARGS, (char*) "End capturing stderr and returns the captured buffer."},
1006 {nullptr, nullptr, 0, nullptr}
1007};
1008
1009
1010#if PY_VERSION_HEX >= 0x03000000
1011struct module_state {
1012 PyObject *error;
1013};
1014
1015#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
1016
1017static int cpycppyymodule_traverse(PyObject* m, visitproc visit, void* arg)
1018{
1019 Py_VISIT(GETSTATE(m)->error);
1020 return 0;
1021}
1022
1023static int cpycppyymodule_clear(PyObject* m)
1024{
1025 Py_CLEAR(GETSTATE(m)->error);
1026 return 0;
1027}
1028
1029
1030static struct PyModuleDef moduledef = {
1031 PyModuleDef_HEAD_INIT,
1032 "libcppyy",
1033 nullptr,
1034 sizeof(struct module_state),
1036 nullptr,
1037 cpycppyymodule_traverse,
1038 cpycppyymodule_clear,
1039 nullptr
1040};
1041
1042
1043//----------------------------------------------------------------------------
1044#define CPYCPPYY_INIT_ERROR return nullptr
1045extern "C" PyObject* PyInit_libcppyy()
1046#else
1047#define CPYCPPYY_INIT_ERROR return
1048extern "C" void initlibcppyy()
1049#endif
1050{
1051// Initialization of extension module libcppyy.
1052
1053// load commonly used python strings
1056
1057// setup interpreter
1058#if PY_VERSION_HEX < 0x03090000
1059 PyEval_InitThreads();
1060#endif
1061
1062#if PY_VERSION_HEX < 0x030b0000
1063// prepare for laziness (the insert is needed to capture the most generic lookup
1064// function, just in case ...)
1065 PyObject* dict = PyDict_New();
1066 PyObject* notstring = PyInt_FromLong(5);
1067 PyDict_SetItem(dict, notstring, notstring);
1068 Py_DECREF(notstring);
1069#if PY_VERSION_HEX >= 0x03030000
1070 gDictLookupOrg = (dict_lookup_func)((PyDictObject*)dict)->ma_keys->dk_lookup;
1071#else
1072 gDictLookupOrg = (dict_lookup_func)((PyDictObject*)dict)->ma_lookup;
1073#endif
1074 Py_DECREF(dict);
1075#endif // PY_VERSION_HEX < 0x030b0000
1076
1077// setup this module
1078#if PY_VERSION_HEX >= 0x03000000
1079 gThisModule = PyModule_Create(&moduledef);
1080#else
1081 gThisModule = Py_InitModule(const_cast<char*>("libcppyy"), gCPyCppyyMethods);
1082#endif
1083 if (!gThisModule)
1085
1086// keep gThisModule, but do not increase its reference count even as it is borrowed,
1087// or a self-referencing cycle would be created
1088
1089// external types
1090 gPyTypeMap = PyDict_New();
1091 PyModule_AddObject(gThisModule, "type_map", gPyTypeMap); // steals reference
1092
1093// Pythonizations ...
1094 PyModule_AddObject(gThisModule, "UserExceptions", PyDict_New());
1095
1096// inject meta type
1097 if (!Utility::InitProxy(gThisModule, &CPPScope_Type, "CPPScope"))
1099
1100// inject object proxy type
1101 if (!Utility::InitProxy(gThisModule, &CPPInstance_Type, "CPPInstance"))
1103
1104// inject exception object proxy type
1105 if (!Utility::InitProxy(gThisModule, &CPPExcInstance_Type, "CPPExcInstance"))
1107
1108// inject method proxy type
1109 if (!Utility::InitProxy(gThisModule, &CPPOverload_Type, "CPPOverload"))
1111
1112// inject template proxy type
1113 if (!Utility::InitProxy(gThisModule, &TemplateProxy_Type, "TemplateProxy"))
1115
1116// inject property proxy type
1117 if (!Utility::InitProxy(gThisModule, &CPPDataMember_Type, "CPPDataMember"))
1119
1120// inject custom data types
1121#if PY_VERSION_HEX < 0x03000000
1124
1127#endif
1128
1131
1132 if (!Utility::InitProxy(gThisModule, &TupleOfInstances_Type, "InstanceArray"))
1134
1135 if (!Utility::InitProxy(gThisModule, &LowLevelView_Type, "LowLevelView"))
1137
1138 if (!Utility::InitProxy(gThisModule, &PyNullPtr_t_Type, "nullptr_t"))
1140
1141// custom iterators
1142 if (PyType_Ready(&InstanceArrayIter_Type) < 0)
1144
1145 if (PyType_Ready(&IndexIter_Type) < 0)
1147
1148 if (PyType_Ready(&VectorIter_Type) < 0)
1150
1151// inject identifiable nullptr and default
1152 gNullPtrObject = (PyObject*)&_CPyCppyy_NullPtrStruct;
1153 Py_INCREF(gNullPtrObject);
1154 PyModule_AddObject(gThisModule, (char*)"nullptr", gNullPtrObject);
1155
1156 gDefaultObject = (PyObject*)&_CPyCppyy_DefaultStruct;
1157 Py_INCREF(gDefaultObject);
1158 PyModule_AddObject(gThisModule, (char*)"default", gDefaultObject);
1159
1160// C++-specific exceptions
1161 PyObject* cppfatal = PyErr_NewException((char*)"cppyy.ll.FatalError", nullptr, nullptr);
1162 PyModule_AddObject(gThisModule, (char*)"FatalError", cppfatal);
1163
1164 gBusException = PyErr_NewException((char*)"cppyy.ll.BusError", cppfatal, nullptr);
1165 PyModule_AddObject(gThisModule, (char*)"BusError", gBusException);
1166 gSegvException = PyErr_NewException((char*)"cppyy.ll.SegmentationViolation", cppfatal, nullptr);
1167 PyModule_AddObject(gThisModule, (char*)"SegmentationViolation", gSegvException);
1168 gIllException = PyErr_NewException((char*)"cppyy.ll.IllegalInstruction", cppfatal, nullptr);
1169 PyModule_AddObject(gThisModule, (char*)"IllegalInstruction", gIllException);
1170 gAbrtException = PyErr_NewException((char*)"cppyy.ll.AbortSignal", cppfatal, nullptr);
1171 PyModule_AddObject(gThisModule, (char*)"AbortSignal", gAbrtException);
1172
1173// policy labels
1174 PyModule_AddObject(gThisModule, (char*)"kMemoryHeuristics",
1175 PyInt_FromLong((int)CallContext::kUseHeuristics));
1176 PyModule_AddObject(gThisModule, (char*)"kMemoryStrict",
1177 PyInt_FromLong((int)CallContext::kUseStrict));
1178
1179// gbl namespace is injected in cppyy.py
1180
1181// create the memory regulator
1182 static MemoryRegulator s_memory_regulator;
1183
1184#if PY_VERSION_HEX >= 0x03000000
1185 Py_INCREF(gThisModule);
1186 return gThisModule;
1187#endif
1188}
static PyObject * default_repr(PyObject *)
#define CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos)
static PyObject * nullptr_repr(PyObject *)
static PyNumberMethods nullptr_as_number
#define CPYCPPYY_INIT_ERROR
static void default_dealloc(PyObject *)
void initlibcppyy()
static PyTypeObject PyDefault_t_Type
static void nullptr_dealloc(PyObject *)
static int nullptr_nonzero(PyObject *)
static PyMethodDef gCPyCppyyMethods[]
static PyTypeObject PyNullPtr_t_Type
#define CPYCPPYY_GET_DICT_LOOKUP(mp)
#define Py_TYPE(ob)
Definition CPyCppyy.h:196
PyDictEntry *(* dict_lookup_func)(PyDictObject *, PyObject *, long)
Definition CPyCppyy.h:44
#define Py_RETURN_TRUE
Definition CPyCppyy.h:272
#define Py_RETURN_FALSE
Definition CPyCppyy.h:276
#define PY_SSIZE_T_FORMAT
Definition CPyCppyy.h:218
static void * CPyCppyy_PyCapsule_GetPointer(PyObject *capsule, const char *)
Definition CPyCppyy.h:104
#define CPyCppyy_PyText_AsString
Definition CPyCppyy.h:76
static PyObject * CPyCppyy_PyCapsule_New(void *cobj, const char *, void(*destr)(void *))
Definition CPyCppyy.h:98
long Py_hash_t
Definition CPyCppyy.h:114
static PyObject * PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg)
Definition CPyCppyy.h:367
#define CPyCppyy_PyText_FromFormat
Definition CPyCppyy.h:80
#define Py_RETURN_NONE
Definition CPyCppyy.h:268
#define CPyCppyy_PyText_Type
Definition CPyCppyy.h:94
#define CPyCppyy_PyText_FromString
Definition CPyCppyy.h:81
#define CPyCppyy_PyText_Check
Definition CPyCppyy.h:74
#define PyVarObject_HEAD_INIT(type, size)
Definition CPyCppyy.h:194
_object PyObject
static struct PyModuleDef moduledef
#define GETSTATE(m)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
#define pyname
TTime operator*(const TTime &t1, const TTime &t2)
Definition TTime.h:85
void * GetAddress(CPPInstance *pyobj)
Cppyy::TCppType_t ObjectIsA(bool check_smart=true) const
Py_ssize_t GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, bool check=true)
Definition Utility.cxx:808
std::string ConstructTemplateArgs(PyObject *pyname, PyObject *tpArgs, PyObject *args=nullptr, ArgPreference=kNone, int argoff=0, int *pcnt=nullptr)
Definition Utility.cxx:580
bool InitProxy(PyObject *module, PyTypeObject *pytype, const char *name)
Definition Utility.cxx:788
PyTypeObject CPPInstance_Type
PyObject * gAbrtException
PyObject * gDefaultObject
bool gDictLookupActive
Definition Utility.cxx:28
PyTypeObject VectorIter_Type
PyTypeObject CPPExcInstance_Type
PyObject * GetScopeProxy(Cppyy::TCppScope_t)
std::ostringstream gCapturedError
dict_lookup_func gDictLookupOrg
Definition Utility.cxx:27
PyTypeObject CustomInstanceMethod_Type
PyObject * CreateScopeProxy(Cppyy::TCppScope_t, const unsigned flags=0)
bool CPPDataMember_CheckExact(T *object)
PyTypeObject RefFloat_Type
Custom "builtins," detectable by type, for pass by ref and improved performance.
PyObject * gSegvException
std::set< Cppyy::TCppType_t > gPinnedTypes
PyObject * DestroyPyStrings()
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
std::map< std::string, std::vector< PyObject * > > gPythonizations
bool CPPScope_Check(T *object)
Definition CPPScope.h:81
bool CreatePyStrings()
Definition PyStrings.cxx:84
CPYCPPYY_EXTERN PyObject * Instance_FromVoidPtr(void *addr, const std::string &classname, bool python_owns=false)
Definition API.cxx:118
bool CPPInstance_Check(T *object)
PyTypeObject IndexIter_Type
PyObject * gNullPtrObject
PyTypeObject CPPOverload_Type
PyTypeObject TemplateProxy_Type
PyObject * gThisModule
Definition CPPMethod.cxx:30
PyTypeObject InstanceArrayIter_Type
bool CPPDataMember_Check(T *object)
PyObject * BindCppObject(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
CPYCPPYY_EXTERN void * Instance_AsVoidPtr(PyObject *pyobject)
Definition API.cxx:103
PyTypeObject CPPScope_Type
Definition CPPScope.cxx:645
PyObject * gIllException
PyTypeObject LowLevelView_Type
PyObject * gPyTypeMap
bool CPPOverload_CheckExact(T *object)
Definition CPPOverload.h:96
PyTypeObject CPPDataMember_Type
PyObject * gBusException
std::streambuf * gOldErrorBuffer
PyTypeObject TupleOfInstances_Type
Representation of C-style array of instances.
PyTypeObject RefInt_Type
RPY_EXPORTED ptrdiff_t GetBaseOffset(TCppType_t derived, TCppType_t base, TCppObject_t address, int direction, bool rerror=false)
RPY_EXPORTED size_t SizeOf(TCppType_t klass)
RPY_EXPORTED void AddSmartPtrType(const std::string &)
RPY_EXPORTED bool IsSubtype(TCppType_t derived, TCppType_t base)
void * TCppObject_t
Definition cpp_cppyy.h:21
TCppScope_t TCppType_t
Definition cpp_cppyy.h:19
RPY_EXPORTED void AddTypeReducer(const std::string &reducable, const std::string &reduced)
RPY_EXPORTED bool IsAggregate(TCppType_t type)
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
void * TCppFuncAddr_t
Definition cpp_cppyy.h:25
void(off) SmallVectorTemplateBase< T
static bool SetGlobalSignalPolicy(bool setProtected)
static bool SetMemoryPolicy(ECallFlags e)
PyObject_HEAD char * b_ptr
PyObject * error
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4