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// Standard
20#include <algorithm>
21#include <map>
22#include <set>
23#include <string>
24#include <sstream>
25#include <utility>
26#include <vector>
27
28
29//- from Python's dictobject.c -------------------------------------------------
30#if PY_VERSION_HEX >= 0x03030000
31 typedef struct PyDictKeyEntry {
32 /* Cached hash code of me_key. */
33 Py_hash_t me_hash;
34 PyObject *me_key;
35 PyObject *me_value; /* This field is only meaningful for combined tables */
36 } PyDictEntry;
37
38 typedef struct _dictkeysobject {
39 Py_ssize_t dk_refcnt;
40 Py_ssize_t dk_size;
41 dict_lookup_func dk_lookup;
42 Py_ssize_t dk_usable;
43#if PY_VERSION_HEX >= 0x03060000
44 Py_ssize_t dk_nentries;
45 union {
46 int8_t as_1[8];
47 int16_t as_2[4];
48 int32_t as_4[2];
49#if SIZEOF_VOID_P > 4
50 int64_t as_8[1];
51#endif
52 } dk_indices;
53#else
54 PyDictKeyEntry dk_entries[1];
55#endif
56 } PyDictKeysObject;
57
58#define CPYCPPYY_GET_DICT_LOOKUP(mp) \
59 ((dict_lookup_func&)mp->ma_keys->dk_lookup)
60
61#else
62
63#define CPYCPPYY_GET_DICT_LOOKUP(mp) \
64 ((dict_lookup_func&)mp->ma_lookup)
65
66#endif
67
68//- data -----------------------------------------------------------------------
70{
71 return CPyCppyy_PyText_FromString("nullptr");
72}
73
75{
76 Py_FatalError("deallocating nullptr");
77}
78
80{
81 return 0;
82}
83
84static PyNumberMethods nullptr_as_number = {
85 0, 0, 0,
86#if PY_VERSION_HEX < 0x03000000
87 0,
88#endif
89 0, 0, 0, 0, 0, 0,
90 (inquiry)nullptr_nonzero, // tp_nonzero (nb_bool in p3)
91 0, 0, 0, 0, 0, 0,
92#if PY_VERSION_HEX < 0x03000000
93 0, // nb_coerce
94#endif
95 0, 0, 0,
96#if PY_VERSION_HEX < 0x03000000
97 0, 0,
98#endif
99 0, 0, 0,
100#if PY_VERSION_HEX < 0x03000000
101 0, // nb_inplace_divide
102#endif
103 0, 0, 0, 0, 0, 0, 0
104#if PY_VERSION_HEX >= 0x02020000
105 , 0 // nb_floor_divide
106#if PY_VERSION_HEX < 0x03000000
107 , 0 // nb_true_divide
108#else
109 , 0 // nb_true_divide
110#endif
111 , 0, 0
112#endif
113#if PY_VERSION_HEX >= 0x02050000
114 , 0 // nb_index
115#endif
116#if PY_VERSION_HEX >= 0x03050000
117 , 0 // nb_matrix_multiply
118 , 0 // nb_inplace_matrix_multiply
119#endif
120};
121
122static PyTypeObject PyNullPtr_t_Type = {
123 PyVarObject_HEAD_INIT(&PyType_Type, 0)
124 "nullptr_t", // tp_name
125 sizeof(PyObject), // tp_basicsize
126 0, // tp_itemsize
127 nullptr_dealloc, // tp_dealloc (never called)
128 0, 0, 0, 0,
129 nullptr_repr, // tp_repr
130 &nullptr_as_number, // tp_as_number
131 0, 0,
132 (hashfunc)_Py_HashPointer, // tp_hash
133 0, 0, 0, 0, 0, Py_TPFLAGS_DEFAULT, 0, 0, 0, 0, 0, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
135#if PY_VERSION_HEX >= 0x02030000
136 , 0 // tp_del
137#endif
138#if PY_VERSION_HEX >= 0x02060000
139 , 0 // tp_version_tag
140#endif
141#if PY_VERSION_HEX >= 0x03040000
142 , 0 // tp_finalize
143#endif
144};
145
146namespace {
147
148PyObject _CPyCppyy_NullPtrStruct = {
149 _PyObject_EXTRA_INIT
151};
152
153// TOOD: refactor with Converters.cxx
154struct CPyCppyy_tagCDataObject { // non-public (but stable)
155 PyObject_HEAD
156 char* b_ptr;
157 int b_needsfree;
158};
159
160} // unnamed namespace
161
162namespace CPyCppyy {
163 PyObject* gThisModule = nullptr;
170 std::map<std::string, std::vector<PyObject*>> gPythonizations;
171 std::set<Cppyy::TCppType_t> gPinnedTypes;
172}
173
174
175//- private helpers ------------------------------------------------------------
176namespace {
177
178using namespace CPyCppyy;
179
180//----------------------------------------------------------------------------
181namespace {
182
183class GblGetter {
184public:
185 GblGetter() {
186 PyObject* cppyy = PyImport_AddModule((char*)"cppyy");
187 fGbl = PyObject_GetAttrString(cppyy, (char*)"gbl");
188 }
189 ~GblGetter() { Py_DECREF(fGbl); }
190
191 PyObject* operator*() { return fGbl; }
192
193private:
194 PyObject* fGbl;
195};
196
197} // unnamed namespace
198
199#if PY_VERSION_HEX >= 0x03060000
200inline Py_ssize_t OrgDictLookup(PyDictObject* mp, PyObject* key,
201 Py_hash_t hash, PyObject*** value_addr, Py_ssize_t* hashpos)
202{
203 return (*gDictLookupOrg)(mp, key, hash, value_addr, hashpos);
204}
205#define CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos) \
206 OrgDictLookup(mp, key, hash, value_addr, hashpos)
207
208Py_ssize_t CPyCppyyLookDictString(PyDictObject* mp, PyObject* key,
209 Py_hash_t hash, PyObject*** value_addr, Py_ssize_t* hashpos)
210
211#elif PY_VERSION_HEX >= 0x03030000
212inline PyDictKeyEntry* OrgDictLookup(
213 PyDictObject* mp, PyObject* key, Py_hash_t hash, PyObject*** value_addr)
214{
215 return (*gDictLookupOrg)(mp, key, hash, value_addr);
216}
217
218#define CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos) \
219 OrgDictLookup(mp, key, hash, value_addr)
220
221PyDictKeyEntry* CPyCppyyLookDictString(
222 PyDictObject* mp, PyObject* key, Py_hash_t hash, PyObject*** value_addr)
223
224#else /* < 3.3 */
225
226inline PyDictEntry* OrgDictLookup(PyDictObject* mp, PyObject* key, long hash)
227{
228 return (*gDictLookupOrg)(mp, key, hash);
229}
230
231#define CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos) \
232 OrgDictLookup(mp, key, hash)
233
234PyDictEntry* CPyCppyyLookDictString(PyDictObject* mp, PyObject* key, long hash)
235#endif
236{
237 static GblGetter gbl;
238#if PY_VERSION_HEX >= 0x03060000
239 Py_ssize_t ep;
240#else
241 PyDictEntry* ep;
242#endif
243
244// first search dictionary itself
245 ep = CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos);
247 return ep;
248
249#if PY_VERSION_HEX >= 0x03060000
250 if (ep >= 0)
251#else
252 if (!ep || (ep->me_key && ep->me_value))
253#endif
254 return ep;
255
256// filter for builtins
257 if (PyDict_GetItem(PyEval_GetBuiltins(), key) != 0)
258 return ep;
259
260// normal lookup failed, attempt to get C++ enum/global/class from top-level
261 gDictLookupActive = true;
262
263// attempt to get C++ enum/global/class from top-level
264 PyObject* val = PyObject_GetAttr(*gbl, key);
265
266 if (val) {
267 // success ...
268
269 if (CPPDataMember_CheckExact(val)) {
270 // don't want to add to dictionary (the proper place would be the
271 // dictionary of the (meta)class), but modifying ep will be noticed no
272 // matter what; just return the actual value and live with the copy in
273 // the dictionary (mostly, this is correct)
274 PyObject* actual_val = Py_TYPE(val)->tp_descr_get(val, nullptr, nullptr);
275 Py_DECREF(val);
276 val = actual_val;
277 }
278
279 // add reference to C++ entity in the given dictionary
280 CPYCPPYY_GET_DICT_LOOKUP(mp) = gDictLookupOrg; // prevent recursion
281 if (PyDict_SetItem((PyObject*)mp, key, val) == 0) {
282 ep = CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos);
283 } else {
284#if PY_VERSION_HEX >= 0x03060000
285 ep = -1;
286#else
287 ep->me_key = nullptr;
288 ep->me_value = nullptr;
289#endif
290 }
291 CPYCPPYY_GET_DICT_LOOKUP(mp) = CPyCppyyLookDictString; // restore
292
293 // done with val
294 Py_DECREF(val);
295 } else
296 PyErr_Clear();
297
298#if PY_VERSION_HEX >= 0x03030000
299 if (mp->ma_keys->dk_usable <= 0) {
300 // big risk that this lookup will result in a resize, so force it here
301 // to be able to reset the lookup function; of course, this is nowhere
302 // near fool-proof, but should cover interactive usage ...
304 const int maxinsert = 5;
305 PyObject* buf[maxinsert];
306 for (int varmax = 1; varmax <= maxinsert; ++varmax) {
307 for (int ivar = 0; ivar < varmax; ++ivar) {
308 buf[ivar] = CPyCppyy_PyText_FromFormat("__CPYCPPYY_FORCE_RESIZE_%d", ivar);
309 PyDict_SetItem((PyObject*)mp, buf[ivar], Py_None);
310 }
311 for (int ivar = 0; ivar < varmax; ++ivar) {
312 PyDict_DelItem((PyObject*)mp, buf[ivar]);
313 Py_DECREF(buf[ivar]);
314 }
315 if (0 < mp->ma_keys->dk_usable)
316 break;
317 }
318
319 // make sure the entry pointer is still valid by re-doing the lookup
320 ep = CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos);
321
322 // full reset of all lookup functions
324 CPYCPPYY_GET_DICT_LOOKUP(mp) = CPyCppyyLookDictString; // restore
325 }
326#endif
327
328// stopped calling into the reflection system
329 gDictLookupActive = false;
330 return ep;
331}
332
333//----------------------------------------------------------------------------
334static PyObject* SetCppLazyLookup(PyObject*, PyObject* args)
335{
336// Modify the given dictionary to install the lookup function that also
337// tries the global C++ namespace before failing. Called on a module's dictionary,
338// this allows for lazy lookups. This works fine for p3.2 and earlier, but should
339// not be used beyond interactive code for p3.3 and later b/c resizing causes the
340// lookup function to revert to the default (lookdict_unicode_nodummy).
341 PyDictObject* dict = nullptr;
342 if (!PyArg_ParseTuple(args, const_cast<char*>("O!"), &PyDict_Type, &dict))
343 return nullptr;
344
345 CPYCPPYY_GET_DICT_LOOKUP(dict) = CPyCppyyLookDictString;
346
348}
349
350//----------------------------------------------------------------------------
351static PyObject* MakeCppTemplateClass(PyObject*, PyObject* args)
352{
353// Create a binding for a templated class instantiation.
354
355// args is class name + template arguments; build full instantiation
356 Py_ssize_t nArgs = PyTuple_GET_SIZE(args);
357 if (nArgs < 2) {
358 PyErr_Format(PyExc_TypeError, "too few arguments for template instantiation");
359 return nullptr;
360 }
361
362// build "< type, type, ... >" part of class name (modifies pyname)
363 const std::string& tmpl_name =
364 Utility::ConstructTemplateArgs(PyTuple_GET_ITEM(args, 0), args, nullptr, Utility::kNone, 1);
365 if (!tmpl_name.size())
366 return nullptr;
367
368 return CreateScopeProxy(tmpl_name);
369}
370
371//----------------------------------------------------------------------------
372static char* GCIA_kwlist[] = {(char*)"instance", (char*)"field", (char*)"byref", NULL};
373static void* GetCPPInstanceAddress(const char* fname, PyObject* args, PyObject* kwds)
374{
375// Helper to get the address (address-of-address) of various object proxy types.
376 CPPInstance* pyobj = 0; PyObject* pyname = 0; int byref = 0;
377 if (PyArg_ParseTupleAndKeywords(args, kwds, const_cast<char*>("O|O!b"), GCIA_kwlist,
378 &pyobj, &CPyCppyy_PyText_Type, &pyname, &byref) && CPPInstance_Check(pyobj)) {
379
380 if (pyname != 0) {
381 // locate property proxy for offset info
382 CPPDataMember* pyprop = nullptr;
383
384 PyObject* pyclass = (PyObject*)Py_TYPE((PyObject*)pyobj);
385 PyObject* dict = PyObject_GetAttr(pyclass, PyStrings::gDict);
386 pyprop = (CPPDataMember*)PyObject_GetItem(dict, pyname);
387 Py_DECREF(dict);
388
389 if (CPPDataMember_Check(pyprop)) {
390 // this is an address of a value (i.e. &myobj->prop)
391 void* addr = (void*)pyprop->GetAddress(pyobj);
392 Py_DECREF(pyprop);
393 return addr;
394 }
395
396 Py_XDECREF(pyprop);
397
398 PyErr_Format(PyExc_TypeError,
399 "%s is not a valid data member", CPyCppyy_PyText_AsString(pyname));
400 return nullptr;
401 }
402
403 // this is an address of an address (i.e. &myobj, with myobj of type MyObj*)
404 // note that the return result may be null
405 if (!byref) return ((CPPInstance*)pyobj)->GetObject();
406 return &((CPPInstance*)pyobj)->GetObjectRaw();
407 }
408
409 if (!PyErr_Occurred())
410 PyErr_Format(PyExc_ValueError, "invalid argument for %s", fname);
411 return nullptr;
412}
413
414//----------------------------------------------------------------------------
415static PyObject* addressof(PyObject* /* dummy */, PyObject* args, PyObject* kwds)
416{
417// Return object proxy address as a value (cppyy-style), or the same for an array.
418 void* addr = GetCPPInstanceAddress("addressof", args, kwds);
419 if (addr)
420 return PyLong_FromLongLong((intptr_t)addr);
421 else if (!PyErr_Occurred()) {
422 return PyLong_FromLong(0);
423 } else if (PyTuple_CheckExact(args) && PyTuple_GET_SIZE(args) == 1) {
424 PyErr_Clear();
425 PyObject* arg0 = PyTuple_GET_ITEM(args, 0);
426 if (arg0 == gNullPtrObject || (PyInt_Check(arg0) && PyInt_AsLong(arg0) == 0))
427 return PyLong_FromLong(0);
428 Utility::GetBuffer(arg0, '*', 1, addr, false);
429 if (addr) return PyLong_FromLongLong((intptr_t)addr);
430 }
431
432// error message if not already set
433 if (!PyErr_Occurred()) {
434 if (PyTuple_CheckExact(args) && PyTuple_GET_SIZE(args)) {
435 PyObject* str = PyObject_Str(PyTuple_GET_ITEM(args, 0));
436 if (str && CPyCppyy_PyText_Check(str))
437 PyErr_Format(PyExc_TypeError, "unknown object %s", CPyCppyy_PyText_AsString(str));
438 else
439 PyErr_Format(PyExc_TypeError, "unknown object at %p", (void*)PyTuple_GET_ITEM(args, 0));
440 Py_XDECREF(str);
441 }
442 }
443 return nullptr;
444}
445
446//----------------------------------------------------------------------------
447static PyObject* AsCObject(PyObject* /* unused */, PyObject* args, PyObject* kwds)
448{
449// Return object proxy as an opaque CObject.
450 void* addr = GetCPPInstanceAddress("as_cobject", args, kwds);
451 if (addr)
452 return CPyCppyy_PyCapsule_New((void*)addr, nullptr, nullptr);
453 return nullptr;
454}
455
456//----------------------------------------------------------------------------
457static PyObject* AsCapsule(PyObject* /* dummy */, PyObject* args, PyObject* kwds)
458{
459// Return object proxy as an opaque PyCapsule.
460 void* addr = GetCPPInstanceAddress("as_capsule", args, kwds);
461 if (addr)
462#if PY_VERSION_HEX < 0x02060000
463 return PyCObject_FromVoidPtr(addr, nullptr);
464#else
465 return PyCapsule_New(addr, nullptr, nullptr);
466#endif
467 return nullptr;
468}
469
470//----------------------------------------------------------------------------
471static PyObject* AsCTypes(PyObject* /* dummy */, PyObject* args, PyObject* kwds)
472{
473// Return object proxy as a ctypes c_void_p
474 void* addr = GetCPPInstanceAddress("as_ctypes", args, kwds);
475 if (!addr)
476 return nullptr;
477
478// TODO: refactor code below with converters code
479 static PyTypeObject* ct_cvoidp = nullptr;
480 if (!ct_cvoidp) {
481 PyObject* ctmod = PyImport_ImportModule("ctypes"); // ref-count kept
482 if (!ctmod) return nullptr;
483
484 ct_cvoidp = (PyTypeObject*)PyObject_GetAttrString(ctmod, "c_void_p");
485 Py_DECREF(ctmod);
486 if (!ct_cvoidp) return nullptr;
487 Py_DECREF(ct_cvoidp); // module keeps a reference
488 }
489
490 PyObject* ref = ct_cvoidp->tp_new(ct_cvoidp, nullptr, nullptr);
491 *(void**)((CPyCppyy_tagCDataObject*)ref)->b_ptr = addr;
492 ((CPyCppyy_tagCDataObject*)ref)->b_needsfree = 0;
493 return ref;
494}
495
496//----------------------------------------------------------------------------
497static PyObject* BindObject(PyObject*, PyObject* args, PyObject* kwds)
498{
499// From a long representing an address or a PyCapsule/CObject, bind to a class.
500 Py_ssize_t argc = PyTuple_GET_SIZE(args);
501 if (argc != 2) {
502 PyErr_Format(PyExc_TypeError,
503 "BindObject takes exactly 2 argumenst (" PY_SSIZE_T_FORMAT " given)", argc);
504 return nullptr;
505 }
506
507// try to convert first argument: either PyCapsule/CObject or long integer
508 PyObject* pyaddr = PyTuple_GET_ITEM(args, 0);
509
510 void* addr = nullptr;
511 if (pyaddr != &_CPyCppyy_NullPtrStruct) {
512 addr = CPyCppyy_PyCapsule_GetPointer(pyaddr, nullptr);
513 if (PyErr_Occurred()) {
514 PyErr_Clear();
515
516 addr = PyLong_AsVoidPtr(pyaddr);
517 if (PyErr_Occurred()) {
518 PyErr_Clear();
519
520 // last chance, perhaps it's a buffer/array (return from void*)
521 Py_ssize_t buflen = Utility::GetBuffer(PyTuple_GetItem(args, 0), '*', 1, addr, false);
522 if (!addr || !buflen) {
523 PyErr_SetString(PyExc_TypeError,
524 "BindObject requires a CObject or long integer as first argument");
525 return nullptr;
526 }
527 }
528 }
529 }
530
531 Cppyy::TCppType_t klass = 0;
532 PyObject* pyname = PyTuple_GET_ITEM(args, 1);
533 if (!CPyCppyy_PyText_Check(pyname)) { // not string, then class
535 klass = ((CPPClass*)pyname)->fCppType;
536 else
537 pyname = PyObject_GetAttr(pyname, PyStrings::gName);
538 } else
539 Py_INCREF(pyname);
540
541 if (!klass && pyname) {
543 Py_DECREF(pyname);
544 }
545
546 if (!klass) {
547 PyErr_SetString(PyExc_TypeError,
548 "BindObject expects a valid class or class name as an argument");
549 return nullptr;
550 }
551
552 bool do_cast = false;
553 if (kwds) {
554 PyObject* cast = PyDict_GetItemString(kwds, "cast");
555 do_cast = cast && PyObject_IsTrue(cast);
556 }
557
558 if (do_cast)
559 return BindCppObject(addr, klass);
560
561 return BindCppObjectNoCast(addr, klass);
562}
563
564//----------------------------------------------------------------------------
565static PyObject* Move(PyObject*, PyObject* pyobject)
566{
567// Prepare the given C++ object for moving.
568 if (!CPPInstance_Check(pyobject)) {
569 PyErr_SetString(PyExc_TypeError, "C++ object expected");
570 return nullptr;
571 }
572
573 ((CPPInstance*)pyobject)->fFlags |= CPPInstance::kIsRValue;
574 Py_INCREF(pyobject);
575 return pyobject;
576}
577
578
579//----------------------------------------------------------------------------
580static PyObject* AddPythonization(PyObject*, PyObject* args)
581{
582// Remove a previously registered pythonizor from the given scope.
583 PyObject* pythonizor = nullptr; const char* scope;
584 if (!PyArg_ParseTuple(args, const_cast<char*>("Os"), &pythonizor, &scope))
585 return nullptr;
586
587 if (!PyCallable_Check(pythonizor)) {
588 PyObject* pystr = PyObject_Str(pythonizor);
589 PyErr_Format(PyExc_TypeError,
590 "given \'%s\' object is not callable", CPyCppyy_PyText_AsString(pystr));
591 Py_DECREF(pystr);
592 return nullptr;
593 }
594
595 Py_INCREF(pythonizor);
596 gPythonizations[scope].push_back(pythonizor);
597
599}
600
601
602//----------------------------------------------------------------------------
603static PyObject* RemovePythonization(PyObject*, PyObject* args)
604{
605// Remove a previously registered pythonizor from the given scope.
606 PyObject* pythonizor = nullptr; const char* scope;
607 if (!PyArg_ParseTuple(args, const_cast<char*>("Os"), &pythonizor, &scope))
608 return nullptr;
609
610 auto p1 = gPythonizations.find(scope);
611 if (p1 != gPythonizations.end()) {
612 auto p2 = std::find(p1->second.begin(), p1->second.end(), pythonizor);
613 if (p2 != p1->second.end()) {
614 p1->second.erase(p2);
616 }
617 }
618
620}
621
622//----------------------------------------------------------------------------
623static PyObject* SetMemoryPolicy(PyObject*, PyObject* args)
624{
625// Set the global memory policy, which affects object ownership when objects
626// are passed as function arguments.
627 PyObject* policy = nullptr;
628 if (!PyArg_ParseTuple(args, const_cast<char*>("O!"), &PyInt_Type, &policy))
629 return nullptr;
630
631 long l = PyInt_AS_LONG(policy);
634 }
635
636 PyErr_Format(PyExc_ValueError, "Unknown policy %ld", l);
637 return nullptr;
638}
639
640//----------------------------------------------------------------------------
641static PyObject* SetGlobalSignalPolicy(PyObject*, PyObject* args)
642{
643// Set the global signal policy, which determines whether a jmp address
644// should be saved to return to after a C++ segfault.
645 PyObject* setProtected = 0;
646 if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &setProtected))
647 return nullptr;
648
649 if (CallContext::SetGlobalSignalPolicy(PyObject_IsTrue(setProtected))) {
651 }
652
654}
655
656//----------------------------------------------------------------------------
657static PyObject* SetOwnership(PyObject*, PyObject* args)
658{
659// Set the ownership (True is python-owns) for the given object.
660 CPPInstance* pyobj = nullptr; PyObject* pykeep = nullptr;
661 if (!PyArg_ParseTuple(args, const_cast<char*>("O!O!"),
662 &CPPInstance_Type, (void*)&pyobj, &PyInt_Type, &pykeep))
663 return nullptr;
664
665 (bool)PyLong_AsLong(pykeep) ? pyobj->PythonOwns() : pyobj->CppOwns();
666
668}
669
670//----------------------------------------------------------------------------
672{
673// Add a smart pointer to the list of known smart pointer types.
674 const char* type_name;
675 if (!PyArg_ParseTuple(args, const_cast<char*>("s"), &type_name))
676 return nullptr;
677
678 Cppyy::AddSmartPtrType(type_name);
679
681}
682
683//----------------------------------------------------------------------------
684static PyObject* PinType(PyObject*, PyObject* pyclass)
685{
686// Add a pinning so that objects of type `derived' are interpreted as
687// objects of type `base'.
688 if (!CPPScope_Check(pyclass)) {
689 PyErr_SetString(PyExc_TypeError, "C++ class expected");
690 return nullptr;
691 }
692
693 gPinnedTypes.insert(((CPPClass*)pyclass)->fCppType);
694
696}
697
698//----------------------------------------------------------------------------
699static PyObject* Cast(PyObject*, PyObject* args)
700{
701// Cast `obj' to type `type'.
702 CPPInstance* obj = nullptr;
703 CPPClass* type = nullptr;
704 if (!PyArg_ParseTuple(args, const_cast<char*>("O!O!"),
705 &CPPInstance_Type, &obj,
707 return nullptr;
708// TODO: this misses an offset calculation, and reference type must not
709// be cast ...
710 return BindCppObjectNoCast(obj->GetObject(), type->fCppType,
712}
713
714} // unnamed namespace
715
716
717//- data -----------------------------------------------------------------------
718static PyMethodDef gCPyCppyyMethods[] = {
719 {(char*) "CreateScopeProxy", (PyCFunction)CPyCppyy::CreateScopeProxy,
720 METH_VARARGS, (char*)"cppyy internal function"},
721 {(char*) "MakeCppTemplateClass", (PyCFunction)MakeCppTemplateClass,
722 METH_VARARGS, (char*)"cppyy internal function"},
723 {(char*) "_set_cpp_lazy_lookup", (PyCFunction)SetCppLazyLookup,
724 METH_VARARGS, (char*)"cppyy internal function"},
725 {(char*) "_DestroyPyStrings", (PyCFunction)CPyCppyy::DestroyPyStrings,
726 METH_NOARGS, (char*)"cppyy internal function"},
727 {(char*) "addressof", (PyCFunction)addressof,
728 METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field as a value."},
729 {(char*) "as_cobject", (PyCFunction)AsCObject,
730 METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field in a CObject."},
731 {(char*) "as_capsule", (PyCFunction)AsCapsule,
732 METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field in a PyCapsule."},
733 {(char*) "as_ctypes", (PyCFunction)AsCTypes,
734 METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field in a ctypes c_void_p."},
735 {(char*)"bind_object", (PyCFunction)BindObject,
736 METH_VARARGS | METH_KEYWORDS, (char*) "Create an object of given type, from given address."},
737 {(char*) "move", (PyCFunction)Move,
738 METH_O, (char*)"Cast the C++ object to become movable."},
739 {(char*) "add_pythonization", (PyCFunction)AddPythonization,
740 METH_VARARGS, (char*)"Add a pythonizor."},
741 {(char*) "remove_pythonization", (PyCFunction)RemovePythonization,
742 METH_VARARGS, (char*)"Remove a pythonizor."},
743 {(char*) "SetMemoryPolicy", (PyCFunction)SetMemoryPolicy,
744 METH_VARARGS, (char*)"Determines object ownership model."},
745 {(char*) "SetGlobalSignalPolicy", (PyCFunction)SetGlobalSignalPolicy,
746 METH_VARARGS, (char*)"Trap signals in safe mode to prevent interpreter abort."},
747 {(char*) "SetOwnership", (PyCFunction)SetOwnership,
748 METH_VARARGS, (char*)"Modify held C++ object ownership."},
749 {(char*) "AddSmartPtrType", (PyCFunction)AddSmartPtrType,
750 METH_VARARGS, (char*) "Add a smart pointer to the list of known smart pointer types."},
751 {(char*) "_pin_type", (PyCFunction)PinType,
752 METH_O, (char*)"Install a type pinning."},
753 {(char*) "Cast", (PyCFunction)Cast,
754 METH_VARARGS, (char*)"Cast the given object to the given type"},
755 {nullptr, nullptr, 0, nullptr}
756};
757
758#define QuoteIdent(ident) #ident
759#define QuoteMacro(macro) QuoteIdent(macro)
760#define LIBCPPYY_NAME "libcppyy" QuoteMacro(PY_MAJOR_VERSION) "_" QuoteMacro(PY_MINOR_VERSION)
761
762#define CONCAT(a, b, c, d) a##b##c##d
763#define LIBCPPYY_INIT_FUNCTION(a, b, c, d) CONCAT(a, b, c, d)
764
765#if PY_VERSION_HEX >= 0x03000000
766struct module_state {
767 PyObject *error;
768};
769
770#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
771
772static int cpycppyymodule_traverse(PyObject* m, visitproc visit, void* arg)
773{
774 Py_VISIT(GETSTATE(m)->error);
775 return 0;
776}
777
778static int cpycppyymodule_clear(PyObject* m)
779{
780 Py_CLEAR(GETSTATE(m)->error);
781 return 0;
782}
783
784static struct PyModuleDef moduledef = {
785 PyModuleDef_HEAD_INIT,
787 nullptr,
788 sizeof(struct module_state),
790 nullptr,
791 cpycppyymodule_traverse,
792 cpycppyymodule_clear,
793 nullptr
794};
795
796
797//----------------------------------------------------------------------------
798#define CPYCPPYY_INIT_ERROR return nullptr
799LIBCPPYY_INIT_FUNCTION(extern "C" PyObject* PyInit_libcppyy, PY_MAJOR_VERSION, _, PY_MINOR_VERSION) ()
800#else
802LIBCPPYY_INIT_FUNCTION(extern "C" void initlibcppyy, PY_MAJOR_VERSION, _, PY_MINOR_VERSION) ()
803#endif
804{
805// Initialization of extension module libcppyy.
806
807// load commonly used python strings
810
811// setup interpreter
812#if PY_VERSION_HEX < 0x03090000
813 PyEval_InitThreads();
814#endif
815
816// prepare for lazyness (the insert is needed to capture the most generic lookup
817// function, just in case ...)
818 PyObject* dict = PyDict_New();
819 PyObject* notstring = PyInt_FromLong(5);
820 PyDict_SetItem(dict, notstring, notstring);
821 Py_DECREF(notstring);
822#if PY_VERSION_HEX >= 0x03030000
823 gDictLookupOrg = (dict_lookup_func)((PyDictObject*)dict)->ma_keys->dk_lookup;
824#else
825 gDictLookupOrg = (dict_lookup_func)((PyDictObject*)dict)->ma_lookup;
826#endif
827 Py_DECREF(dict);
828
829// setup this module
830#if PY_VERSION_HEX >= 0x03000000
831 gThisModule = PyModule_Create(&moduledef);
832#else
833 gThisModule = Py_InitModule(const_cast<char*>(LIBCPPYY_NAME), gCPyCppyyMethods);
834#endif
835 if (!gThisModule)
837
838// keep gThisModule, but do not increase its reference count even as it is borrowed,
839// or a self-referencing cycle would be created
840
841// external types
842 gPyTypeMap = PyDict_New();
843 PyModule_AddObject(gThisModule, "type_map", gPyTypeMap); // steals reference
844
845// Pythonizations ...
846 PyModule_AddObject(gThisModule, "UserExceptions", PyDict_New());
847
848// inject meta type
849 if (!Utility::InitProxy(gThisModule, &CPPScope_Type, "CPPScope"))
851
852// inject object proxy type
853 if (!Utility::InitProxy(gThisModule, &CPPInstance_Type, "CPPInstance"))
855
856// inject exception object proxy type
857 if (!Utility::InitProxy(gThisModule, &CPPExcInstance_Type, "CPPExcInstance"))
859
860// inject method proxy type
861 if (!Utility::InitProxy(gThisModule, &CPPOverload_Type, "CPPOverload"))
863
864// inject template proxy type
865 if (!Utility::InitProxy(gThisModule, &TemplateProxy_Type, "TemplateProxy"))
867
868// inject property proxy type
869 if (!Utility::InitProxy(gThisModule, &CPPDataMember_Type, "CPPDataMember"))
871
872// inject custom data types
875
878
881
882 if (!Utility::InitProxy(gThisModule, &TupleOfInstances_Type, "InstancesArray"))
884
885 if (!Utility::InitProxy(gThisModule, &InstanceArrayIter_Type, "instancearrayiter"))
887
890
891// initialize low level ptr type, but do not inject in gThisModule
892 if (PyType_Ready(&LowLevelView_Type) < 0)
894
895// custom iterators
896 if (PyType_Ready(&IndexIter_Type) < 0)
898
899 if (PyType_Ready(&VectorIter_Type) < 0)
901
902// inject identifiable nullptr
903 gNullPtrObject = (PyObject*)&_CPyCppyy_NullPtrStruct;
904 Py_INCREF(gNullPtrObject);
905 PyModule_AddObject(gThisModule, (char*)"nullptr", gNullPtrObject);
906
907// C++-specific exceptions
908 PyObject* cppfatal = PyErr_NewException((char*)"cppyy.ll.FatalError", nullptr, nullptr);
909 PyModule_AddObject(gThisModule, (char*)"FatalError", cppfatal);
910
911 gBusException = PyErr_NewException((char*)"cppyy.ll.BusError", cppfatal, nullptr);
912 PyModule_AddObject(gThisModule, (char*)"BusError", gBusException);
913 gSegvException = PyErr_NewException((char*)"cppyy.ll.SegmentationViolation", cppfatal, nullptr);
914 PyModule_AddObject(gThisModule, (char*)"SegmentationViolation", gSegvException);
915 gIllException = PyErr_NewException((char*)"cppyy.ll.IllegalInstruction", cppfatal, nullptr);
916 PyModule_AddObject(gThisModule, (char*)"IllegalInstruction", gIllException);
917 gAbrtException = PyErr_NewException((char*)"cppyy.ll.AbortSignal", cppfatal, nullptr);
918 PyModule_AddObject(gThisModule, (char*)"AbortSignal", gAbrtException);
919
920// policy labels
921 PyModule_AddObject(gThisModule, (char*)"kMemoryHeuristics",
923 PyModule_AddObject(gThisModule, (char*)"kMemoryStrict",
925
926// gbl namespace is injected in cppyy.py
927
928// create the memory regulator
929 static MemoryRegulator s_memory_regulator;
930
931#if PY_VERSION_HEX >= 0x03000000
932 Py_INCREF(gThisModule);
933 return gThisModule;
934#endif
935}
#define CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos)
static PyObject * nullptr_repr(PyObject *)
static PyNumberMethods nullptr_as_number
#define CPYCPPYY_INIT_ERROR
#define LIBCPPYY_INIT_FUNCTION(a, b, c, d)
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 LIBCPPYY_NAME
#define Py_TYPE(ob)
Definition CPyCppyy.h:217
PyDictEntry *(* dict_lookup_func)(PyDictObject *, PyObject *, long)
Definition CPyCppyy.h:69
#define Py_RETURN_TRUE
Definition CPyCppyy.h:293
#define Py_RETURN_FALSE
Definition CPyCppyy.h:297
#define PY_SSIZE_T_FORMAT
Definition CPyCppyy.h:239
static void * CPyCppyy_PyCapsule_GetPointer(PyObject *capsule, const char *)
Definition CPyCppyy.h:125
#define CPyCppyy_PyText_AsString
Definition CPyCppyy.h:97
static PyObject * CPyCppyy_PyCapsule_New(void *cobj, const char *, void(*destr)(void *))
Definition CPyCppyy.h:119
long Py_hash_t
Definition CPyCppyy.h:135
#define CPyCppyy_PyText_FromFormat
Definition CPyCppyy.h:101
#define Py_RETURN_NONE
Definition CPyCppyy.h:289
#define CPyCppyy_PyText_Type
Definition CPyCppyy.h:115
#define CPyCppyy_PyText_FromString
Definition CPyCppyy.h:102
#define CPyCppyy_PyText_Check
Definition CPyCppyy.h:95
#define PyVarObject_HEAD_INIT(type, size)
Definition CPyCppyy.h:215
PyInt_FromLong
_object PyObject
int type
Definition TGX11.cxx:121
#define pyname
TTime operator*(const TTime &t1, const TTime &t2)
Definition TTime.h:85
#define _(A, B)
Definition cfortran.h:108
void * GetAddress(CPPInstance *pyobj)
R__EXTERN PyObject * gName
Definition TPython.cxx:105
Py_ssize_t GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, bool check=true)
Definition Utility.cxx:614
std::string ConstructTemplateArgs(PyObject *pyname, PyObject *tpArgs, PyObject *args=nullptr, ArgPreference=kNone, int argoff=0, int *pcnt=nullptr)
Definition Utility.cxx:473
bool InitProxy(PyObject *module, PyTypeObject *pytype, const char *name)
Definition Utility.cxx:594
Set of helper functions that are invoked from the pythonizors, on the Python side.
PyTypeObject CPPInstance_Type
PyObject * gAbrtException
R__EXTERN bool gDictLookupActive
PyTypeObject VectorIter_Type
PyTypeObject CPPExcInstance_Type
dict_lookup_func gDictLookupOrg
Definition Utility.cxx:26
PyTypeObject CustomInstanceMethod_Type
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:76
bool CreatePyStrings()
Definition PyStrings.cxx:67
bool CPPInstance_Check(T *object)
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
PyTypeObject IndexIter_Type
PyObject * gNullPtrObject
PyTypeObject CPPOverload_Type
PyTypeObject TemplateProxy_Type
R__EXTERN PyObject * gThisModule
Definition TPython.cxx:100
PyTypeObject InstanceArrayIter_Type
bool CPPDataMember_Check(T *object)
PyObject * BindCppObject(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
PyTypeObject CPPScope_Type
Definition CPPScope.cxx:614
PyObject * gIllException
PyTypeObject LowLevelView_Type
PyObject * gPyTypeMap
PyTypeObject CPPDataMember_Type
PyObject * gBusException
PyTypeObject TupleOfInstances_Type
Representation of C-style array of instances.
PyTypeObject RefInt_Type
RPY_EXPORTED void AddSmartPtrType(const std::string &)
TCppScope_t TCppType_t
Definition cpp_cppyy.h:19
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
static bool SetGlobalSignalPolicy(bool setProtected)
static bool SetMemoryPolicy(ECallFlags e)
PyObject_HEAD char * b_ptr
auto * m
Definition textangle.C:8
auto * l
Definition textangle.C:4