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