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 PyErr_SetString(PyExc_TypeError, "aap");
435 /*if (PyTuple_CheckExact(args) && PyTuple_GET_SIZE(args)) {
436 PyObject* str = PyObject_Str(PyTuple_GET_ITEM(args, 0));
437 if (str && CPyCppyy_PyText_Check(str))
438 PyErr_Format(PyExc_TypeError, "unknown object %s", CPyCppyy_PyText_AsString(str));
439 else
440 PyErr_Format(PyExc_TypeError, "unknown object at %p", (void*)PyTuple_GET_ITEM(args, 0));
441 Py_XDECREF(str);
442 } */
443 }
444 return nullptr;
445}
446
447//----------------------------------------------------------------------------
448static PyObject* AsCObject(PyObject* /* unused */, PyObject* args, PyObject* kwds)
449{
450// Return object proxy as an opaque CObject.
451 void* addr = GetCPPInstanceAddress("as_cobject", args, kwds);
452 if (addr)
453 return CPyCppyy_PyCapsule_New((void*)addr, nullptr, nullptr);
454 return nullptr;
455}
456
457//----------------------------------------------------------------------------
458static PyObject* AsCapsule(PyObject* /* dummy */, PyObject* args, PyObject* kwds)
459{
460// Return object proxy as an opaque PyCapsule.
461 void* addr = GetCPPInstanceAddress("as_capsule", args, kwds);
462 if (addr)
463#if PY_VERSION_HEX < 0x02060000
464 return PyCObject_FromVoidPtr(addr, nullptr);
465#else
466 return PyCapsule_New(addr, nullptr, nullptr);
467#endif
468 return nullptr;
469}
470
471//----------------------------------------------------------------------------
472static PyObject* AsCTypes(PyObject* /* dummy */, PyObject* args, PyObject* kwds)
473{
474// Return object proxy as a ctypes c_void_p
475 void* addr = GetCPPInstanceAddress("as_ctypes", args, kwds);
476 if (!addr)
477 return nullptr;
478
479// TODO: refactor code below with converters code
480 static PyTypeObject* ct_cvoidp = nullptr;
481 if (!ct_cvoidp) {
482 PyObject* ctmod = PyImport_ImportModule("ctypes"); // ref-count kept
483 if (!ctmod) return nullptr;
484
485 ct_cvoidp = (PyTypeObject*)PyObject_GetAttrString(ctmod, "c_void_p");
486 Py_DECREF(ctmod);
487 if (!ct_cvoidp) return nullptr;
488 Py_DECREF(ct_cvoidp); // module keeps a reference
489 }
490
491 PyObject* ref = ct_cvoidp->tp_new(ct_cvoidp, nullptr, nullptr);
492 *(void**)((CPyCppyy_tagCDataObject*)ref)->b_ptr = addr;
493 ((CPyCppyy_tagCDataObject*)ref)->b_needsfree = 0;
494 return ref;
495}
496
497//----------------------------------------------------------------------------
498static PyObject* BindObject(PyObject*, PyObject* args, PyObject* kwds)
499{
500// From a long representing an address or a PyCapsule/CObject, bind to a class.
501 Py_ssize_t argc = PyTuple_GET_SIZE(args);
502 if (argc != 2) {
503 PyErr_Format(PyExc_TypeError,
504 "BindObject takes exactly 2 argumenst (" PY_SSIZE_T_FORMAT " given)", argc);
505 return nullptr;
506 }
507
508// try to convert first argument: either PyCapsule/CObject or long integer
509 PyObject* pyaddr = PyTuple_GET_ITEM(args, 0);
510
511 void* addr = nullptr;
512 if (pyaddr != &_CPyCppyy_NullPtrStruct) {
513 addr = CPyCppyy_PyCapsule_GetPointer(pyaddr, nullptr);
514 if (PyErr_Occurred()) {
515 PyErr_Clear();
516
517 addr = PyLong_AsVoidPtr(pyaddr);
518 if (PyErr_Occurred()) {
519 PyErr_Clear();
520
521 // last chance, perhaps it's a buffer/array (return from void*)
522 Py_ssize_t buflen = Utility::GetBuffer(PyTuple_GetItem(args, 0), '*', 1, addr, false);
523 if (!addr || !buflen) {
524 PyErr_SetString(PyExc_TypeError,
525 "BindObject requires a CObject or long integer as first argument");
526 return nullptr;
527 }
528 }
529 }
530 }
531
532 Cppyy::TCppType_t klass = 0;
533 PyObject* pyname = PyTuple_GET_ITEM(args, 1);
534 if (!CPyCppyy_PyText_Check(pyname)) { // not string, then class
536 klass = ((CPPClass*)pyname)->fCppType;
537 else
538 pyname = PyObject_GetAttr(pyname, PyStrings::gName);
539 } else
540 Py_INCREF(pyname);
541
542 if (!klass && pyname) {
544 Py_DECREF(pyname);
545 }
546
547 if (!klass) {
548 PyErr_SetString(PyExc_TypeError,
549 "BindObject expects a valid class or class name as an argument");
550 return nullptr;
551 }
552
553 bool do_cast = false;
554 if (kwds) {
555 PyObject* cast = PyDict_GetItemString(kwds, "cast");
556 do_cast = cast && PyObject_IsTrue(cast);
557 }
558
559 if (do_cast)
560 return BindCppObject(addr, klass);
561
562 return BindCppObjectNoCast(addr, klass);
563}
564
565//----------------------------------------------------------------------------
566static PyObject* Move(PyObject*, PyObject* pyobject)
567{
568// Prepare the given C++ object for moving.
569 if (!CPPInstance_Check(pyobject)) {
570 PyErr_SetString(PyExc_TypeError, "C++ object expected");
571 return nullptr;
572 }
573
574 ((CPPInstance*)pyobject)->fFlags |= CPPInstance::kIsRValue;
575 Py_INCREF(pyobject);
576 return pyobject;
577}
578
579
580//----------------------------------------------------------------------------
581static PyObject* AddPythonization(PyObject*, PyObject* args)
582{
583// Remove a previously registered pythonizor from the given scope.
584 PyObject* pythonizor = nullptr; const char* scope;
585 if (!PyArg_ParseTuple(args, const_cast<char*>("Os"), &pythonizor, &scope))
586 return nullptr;
587
588 if (!PyCallable_Check(pythonizor)) {
589 PyObject* pystr = PyObject_Str(pythonizor);
590 PyErr_Format(PyExc_TypeError,
591 "given \'%s\' object is not callable", CPyCppyy_PyText_AsString(pystr));
592 Py_DECREF(pystr);
593 return nullptr;
594 }
595
596 Py_INCREF(pythonizor);
597 gPythonizations[scope].push_back(pythonizor);
598
600}
601
602
603//----------------------------------------------------------------------------
604static PyObject* RemovePythonization(PyObject*, PyObject* args)
605{
606// Remove a previously registered pythonizor from the given scope.
607 PyObject* pythonizor = nullptr; const char* scope;
608 if (!PyArg_ParseTuple(args, const_cast<char*>("Os"), &pythonizor, &scope))
609 return nullptr;
610
611 auto p1 = gPythonizations.find(scope);
612 if (p1 != gPythonizations.end()) {
613 auto p2 = std::find(p1->second.begin(), p1->second.end(), pythonizor);
614 if (p2 != p1->second.end()) {
615 p1->second.erase(p2);
617 }
618 }
619
621}
622
623//----------------------------------------------------------------------------
624static PyObject* SetMemoryPolicy(PyObject*, PyObject* args)
625{
626// Set the global memory policy, which affects object ownership when objects
627// are passed as function arguments.
628 PyObject* policy = nullptr;
629 if (!PyArg_ParseTuple(args, const_cast<char*>("O!"), &PyInt_Type, &policy))
630 return nullptr;
631
632 long l = PyInt_AS_LONG(policy);
635 }
636
637 PyErr_Format(PyExc_ValueError, "Unknown policy %ld", l);
638 return nullptr;
639}
640
641//----------------------------------------------------------------------------
642static PyObject* SetGlobalSignalPolicy(PyObject*, PyObject* args)
643{
644// Set the global signal policy, which determines whether a jmp address
645// should be saved to return to after a C++ segfault.
646 PyObject* setProtected = 0;
647 if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &setProtected))
648 return nullptr;
649
650 if (CallContext::SetGlobalSignalPolicy(PyObject_IsTrue(setProtected))) {
652 }
653
655}
656
657//----------------------------------------------------------------------------
658static PyObject* SetOwnership(PyObject*, PyObject* args)
659{
660// Set the ownership (True is python-owns) for the given object.
661 CPPInstance* pyobj = nullptr; PyObject* pykeep = nullptr;
662 if (!PyArg_ParseTuple(args, const_cast<char*>("O!O!"),
663 &CPPInstance_Type, (void*)&pyobj, &PyInt_Type, &pykeep))
664 return nullptr;
665
666 (bool)PyLong_AsLong(pykeep) ? pyobj->PythonOwns() : pyobj->CppOwns();
667
669}
670
671//----------------------------------------------------------------------------
673{
674// Add a smart pointer to the list of known smart pointer types.
675 const char* type_name;
676 if (!PyArg_ParseTuple(args, const_cast<char*>("s"), &type_name))
677 return nullptr;
678
679 Cppyy::AddSmartPtrType(type_name);
680
682}
683
684//----------------------------------------------------------------------------
685static PyObject* PinType(PyObject*, PyObject* pyclass)
686{
687// Add a pinning so that objects of type `derived' are interpreted as
688// objects of type `base'.
689 if (!CPPScope_Check(pyclass)) {
690 PyErr_SetString(PyExc_TypeError, "C++ class expected");
691 return nullptr;
692 }
693
694 gPinnedTypes.insert(((CPPClass*)pyclass)->fCppType);
695
697}
698
699//----------------------------------------------------------------------------
700static PyObject* Cast(PyObject*, PyObject* args)
701{
702// Cast `obj' to type `type'.
703 CPPInstance* obj = nullptr;
704 CPPClass* type = nullptr;
705 if (!PyArg_ParseTuple(args, const_cast<char*>("O!O!"),
706 &CPPInstance_Type, &obj,
708 return nullptr;
709// TODO: this misses an offset calculation, and reference type must not
710// be cast ...
711 return BindCppObjectNoCast(obj->GetObject(), type->fCppType,
713}
714
715} // unnamed namespace
716
717
718//- data -----------------------------------------------------------------------
719static PyMethodDef gCPyCppyyMethods[] = {
720 {(char*) "CreateScopeProxy", (PyCFunction)CPyCppyy::CreateScopeProxy,
721 METH_VARARGS, (char*)"cppyy internal function"},
722 {(char*) "MakeCppTemplateClass", (PyCFunction)MakeCppTemplateClass,
723 METH_VARARGS, (char*)"cppyy internal function"},
724 {(char*) "_set_cpp_lazy_lookup", (PyCFunction)SetCppLazyLookup,
725 METH_VARARGS, (char*)"cppyy internal function"},
726 {(char*) "_DestroyPyStrings", (PyCFunction)CPyCppyy::DestroyPyStrings,
727 METH_NOARGS, (char*)"cppyy internal function"},
728 {(char*) "addressof", (PyCFunction)addressof,
729 METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field as a value."},
730 {(char*) "as_cobject", (PyCFunction)AsCObject,
731 METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field in a CObject."},
732 {(char*) "as_capsule", (PyCFunction)AsCapsule,
733 METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field in a PyCapsule."},
734 {(char*) "as_ctypes", (PyCFunction)AsCTypes,
735 METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field in a ctypes c_void_p."},
736 {(char*)"bind_object", (PyCFunction)BindObject,
737 METH_VARARGS | METH_KEYWORDS, (char*) "Create an object of given type, from given address."},
738 {(char*) "move", (PyCFunction)Move,
739 METH_O, (char*)"Cast the C++ object to become movable."},
740 {(char*) "add_pythonization", (PyCFunction)AddPythonization,
741 METH_VARARGS, (char*)"Add a pythonizor."},
742 {(char*) "remove_pythonization", (PyCFunction)RemovePythonization,
743 METH_VARARGS, (char*)"Remove a pythonizor."},
744 {(char*) "SetMemoryPolicy", (PyCFunction)SetMemoryPolicy,
745 METH_VARARGS, (char*)"Determines object ownership model."},
746 {(char*) "SetGlobalSignalPolicy", (PyCFunction)SetGlobalSignalPolicy,
747 METH_VARARGS, (char*)"Trap signals in safe mode to prevent interpreter abort."},
748 {(char*) "SetOwnership", (PyCFunction)SetOwnership,
749 METH_VARARGS, (char*)"Modify held C++ object ownership."},
750 {(char*) "AddSmartPtrType", (PyCFunction)AddSmartPtrType,
751 METH_VARARGS, (char*) "Add a smart pointer to the list of known smart pointer types."},
752 {(char*) "_pin_type", (PyCFunction)PinType,
753 METH_O, (char*)"Install a type pinning."},
754 {(char*) "Cast", (PyCFunction)Cast,
755 METH_VARARGS, (char*)"Cast the given object to the given type"},
756 {nullptr, nullptr, 0, nullptr}
757};
758
759#define QuoteIdent(ident) #ident
760#define QuoteMacro(macro) QuoteIdent(macro)
761#define LIBCPPYY_NAME "libcppyy" QuoteMacro(PY_MAJOR_VERSION) "_" QuoteMacro(PY_MINOR_VERSION)
762
763#define CONCAT(a, b, c, d) a##b##c##d
764#define LIBCPPYY_INIT_FUNCTION(a, b, c, d) CONCAT(a, b, c, d)
765
766#if PY_VERSION_HEX >= 0x03000000
767struct module_state {
768 PyObject *error;
769};
770
771#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
772
773static int cpycppyymodule_traverse(PyObject* m, visitproc visit, void* arg)
774{
775 Py_VISIT(GETSTATE(m)->error);
776 return 0;
777}
778
779static int cpycppyymodule_clear(PyObject* m)
780{
781 Py_CLEAR(GETSTATE(m)->error);
782 return 0;
783}
784
785static struct PyModuleDef moduledef = {
786 PyModuleDef_HEAD_INIT,
788 nullptr,
789 sizeof(struct module_state),
791 nullptr,
792 cpycppyymodule_traverse,
793 cpycppyymodule_clear,
794 nullptr
795};
796
797
798//----------------------------------------------------------------------------
799#define CPYCPPYY_INIT_ERROR return nullptr
800LIBCPPYY_INIT_FUNCTION(extern "C" PyObject* PyInit_libcppyy, PY_MAJOR_VERSION, _, PY_MINOR_VERSION) ()
801#else
803LIBCPPYY_INIT_FUNCTION(extern "C" void initlibcppyy, PY_MAJOR_VERSION, _, PY_MINOR_VERSION) ()
804#endif
805{
806// Initialization of extension module libcppyy.
807
808// load commonly used python strings
811
812// setup interpreter
813#if PY_VERSION_HEX < 0x03090000
814 PyEval_InitThreads();
815#endif
816
817// prepare for lazyness (the insert is needed to capture the most generic lookup
818// function, just in case ...)
819 PyObject* dict = PyDict_New();
820 PyObject* notstring = PyInt_FromLong(5);
821 PyDict_SetItem(dict, notstring, notstring);
822 Py_DECREF(notstring);
823#if PY_VERSION_HEX >= 0x03030000
824 gDictLookupOrg = (dict_lookup_func)((PyDictObject*)dict)->ma_keys->dk_lookup;
825#else
826 gDictLookupOrg = (dict_lookup_func)((PyDictObject*)dict)->ma_lookup;
827#endif
828 Py_DECREF(dict);
829
830// setup this module
831#if PY_VERSION_HEX >= 0x03000000
832 gThisModule = PyModule_Create(&moduledef);
833#else
834 gThisModule = Py_InitModule(const_cast<char*>(LIBCPPYY_NAME), gCPyCppyyMethods);
835#endif
836 if (!gThisModule)
838
839// keep gThisModule, but do not increase its reference count even as it is borrowed,
840// or a self-referencing cycle would be created
841
842// external types
843 gPyTypeMap = PyDict_New();
844 PyModule_AddObject(gThisModule, "type_map", gPyTypeMap); // steals reference
845
846// Pythonizations ...
847 PyModule_AddObject(gThisModule, "UserExceptions", PyDict_New());
848
849// inject meta type
850 if (!Utility::InitProxy(gThisModule, &CPPScope_Type, "CPPScope"))
852
853// inject object proxy type
854 if (!Utility::InitProxy(gThisModule, &CPPInstance_Type, "CPPInstance"))
856
857// inject exception object proxy type
858 if (!Utility::InitProxy(gThisModule, &CPPExcInstance_Type, "CPPExcInstance"))
860
861// inject method proxy type
862 if (!Utility::InitProxy(gThisModule, &CPPOverload_Type, "CPPOverload"))
864
865// inject template proxy type
866 if (!Utility::InitProxy(gThisModule, &TemplateProxy_Type, "TemplateProxy"))
868
869// inject property proxy type
870 if (!Utility::InitProxy(gThisModule, &CPPDataMember_Type, "CPPDataMember"))
872
873// inject custom data types
876
879
882
883 if (!Utility::InitProxy(gThisModule, &TupleOfInstances_Type, "InstancesArray"))
885
886 if (!Utility::InitProxy(gThisModule, &InstanceArrayIter_Type, "instancearrayiter"))
888
891
892// initialize low level ptr type, but do not inject in gThisModule
893 if (PyType_Ready(&LowLevelView_Type) < 0)
895
896// custom iterators
897 if (PyType_Ready(&IndexIter_Type) < 0)
899
900 if (PyType_Ready(&VectorIter_Type) < 0)
902
903// inject identifiable nullptr
904 gNullPtrObject = (PyObject*)&_CPyCppyy_NullPtrStruct;
905 Py_INCREF(gNullPtrObject);
906 PyModule_AddObject(gThisModule, (char*)"nullptr", gNullPtrObject);
907
908// C++-specific exceptions
909 PyObject* cppfatal = PyErr_NewException((char*)"cppyy.ll.FatalError", nullptr, nullptr);
910 PyModule_AddObject(gThisModule, (char*)"FatalError", cppfatal);
911
912 gBusException = PyErr_NewException((char*)"cppyy.ll.BusError", cppfatal, nullptr);
913 PyModule_AddObject(gThisModule, (char*)"BusError", gBusException);
914 gSegvException = PyErr_NewException((char*)"cppyy.ll.SegmentationViolation", cppfatal, nullptr);
915 PyModule_AddObject(gThisModule, (char*)"SegmentationViolation", gSegvException);
916 gIllException = PyErr_NewException((char*)"cppyy.ll.IllegalInstruction", cppfatal, nullptr);
917 PyModule_AddObject(gThisModule, (char*)"IllegalInstruction", gIllException);
918 gAbrtException = PyErr_NewException((char*)"cppyy.ll.AbortSignal", cppfatal, nullptr);
919 PyModule_AddObject(gThisModule, (char*)"AbortSignal", gAbrtException);
920
921// policy labels
922 PyModule_AddObject(gThisModule, (char*)"kMemoryHeuristics",
924 PyModule_AddObject(gThisModule, (char*)"kMemoryStrict",
926
927// gbl namespace is injected in cppyy.py
928
929// create the memory regulator
930 static MemoryRegulator s_memory_regulator;
931
932#if PY_VERSION_HEX >= 0x03000000
933 Py_INCREF(gThisModule);
934 return gThisModule;
935#endif
936}
#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)
auto * m
Definition textangle.C:8
auto * l
Definition textangle.C:4