Logo ROOT  
Reference Guide
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 
84 static 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 
122 static 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 
146 namespace {
147 
148 PyObject _CPyCppyy_NullPtrStruct = {
149  _PyObject_EXTRA_INIT
150  1, &PyNullPtr_t_Type
151 };
152 
153 // TOOD: refactor with Converters.cxx
154 struct CPyCppyy_tagCDataObject { // non-public (but stable)
155  PyObject_HEAD
156  char* b_ptr;
157  int b_needsfree;
158 };
159 
160 } // unnamed namespace
161 
162 namespace CPyCppyy {
163  PyObject* gThisModule = nullptr;
164  PyObject* gPyTypeMap = nullptr;
170  std::map<std::string, std::vector<PyObject*>> gPythonizations;
171  std::set<Cppyy::TCppType_t> gPinnedTypes;
172 }
173 
174 
175 //- private helpers ------------------------------------------------------------
176 namespace {
177 
178 using namespace CPyCppyy;
179 
180 //----------------------------------------------------------------------------
181 namespace {
182 
183 class GblGetter {
184 public:
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 
193 private:
194  PyObject* fGbl;
195 };
196 
197 } // unnamed namespace
198 
199 #if PY_VERSION_HEX >= 0x03060000
200 inline 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 
208 Py_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
212 inline 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 
221 PyDictKeyEntry* CPyCppyyLookDictString(
222  PyDictObject* mp, PyObject* key, Py_hash_t hash, PyObject*** value_addr)
223 
224 #else /* < 3.3 */
225 
226 inline 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 
234 PyDictEntry* 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);
246  if (gDictLookupActive)
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 //----------------------------------------------------------------------------
334 static 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 //----------------------------------------------------------------------------
351 static 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 //----------------------------------------------------------------------------
372 static char* GCIA_kwlist[] = {(char*)"instance", (char*)"field", (char*)"byref", NULL};
373 static 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 //----------------------------------------------------------------------------
415 static 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 //----------------------------------------------------------------------------
448 static 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 //----------------------------------------------------------------------------
458 static 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 //----------------------------------------------------------------------------
472 static 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 //----------------------------------------------------------------------------
498 static 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
535  if (CPPScope_Check(pyname))
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 //----------------------------------------------------------------------------
566 static 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 //----------------------------------------------------------------------------
581 static 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 //----------------------------------------------------------------------------
604 static 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 //----------------------------------------------------------------------------
624 static 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 //----------------------------------------------------------------------------
642 static 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 //----------------------------------------------------------------------------
658 static 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 //----------------------------------------------------------------------------
672 static PyObject* AddSmartPtrType(PyObject*, PyObject* args)
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 //----------------------------------------------------------------------------
685 static 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 //----------------------------------------------------------------------------
700 static 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,
707  &CPPScope_Type, &type))
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 -----------------------------------------------------------------------
719 static 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
767 struct module_state {
768  PyObject *error;
769 };
770 
771 #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
772 
773 static int cpycppyymodule_traverse(PyObject* m, visitproc visit, void* arg)
774 {
775  Py_VISIT(GETSTATE(m)->error);
776  return 0;
777 }
778 
779 static int cpycppyymodule_clear(PyObject* m)
780 {
781  Py_CLEAR(GETSTATE(m)->error);
782  return 0;
783 }
784 
785 static 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
800 LIBCPPYY_INIT_FUNCTION(extern "C" PyObject* PyInit_libcppyy, PY_MAJOR_VERSION, _, PY_MINOR_VERSION) ()
801 #else
802 #define CPYCPPYY_INIT_ERROR return
803 LIBCPPYY_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  PyEval_InitThreads();
814 
815 // prepare for lazyness (the insert is needed to capture the most generic lookup
816 // function, just in case ...)
817  PyObject* dict = PyDict_New();
818  PyObject* notstring = PyInt_FromLong(5);
819  PyDict_SetItem(dict, notstring, notstring);
820  Py_DECREF(notstring);
821 #if PY_VERSION_HEX >= 0x03030000
822  gDictLookupOrg = (dict_lookup_func)((PyDictObject*)dict)->ma_keys->dk_lookup;
823 #else
824  gDictLookupOrg = (dict_lookup_func)((PyDictObject*)dict)->ma_lookup;
825 #endif
826  Py_DECREF(dict);
827 
828 // setup this module
829 #if PY_VERSION_HEX >= 0x03000000
830  gThisModule = PyModule_Create(&moduledef);
831 #else
832  gThisModule = Py_InitModule(const_cast<char*>(LIBCPPYY_NAME), gCPyCppyyMethods);
833 #endif
834  if (!gThisModule)
836 
837 // keep gThisModule, but do not increase its reference count even as it is borrowed,
838 // or a self-referencing cycle would be created
839 
840 // external types
841  gPyTypeMap = PyDict_New();
842  PyModule_AddObject(gThisModule, "type_map", gPyTypeMap); // steals reference
843 
844 // Pythonizations ...
845  PyModule_AddObject(gThisModule, "UserExceptions", PyDict_New());
846 
847 // inject meta type
848  if (!Utility::InitProxy(gThisModule, &CPPScope_Type, "CPPScope"))
850 
851 // inject object proxy type
852  if (!Utility::InitProxy(gThisModule, &CPPInstance_Type, "CPPInstance"))
854 
855 // inject exception object proxy type
856  if (!Utility::InitProxy(gThisModule, &CPPExcInstance_Type, "CPPExcInstance"))
858 
859 // inject method proxy type
860  if (!Utility::InitProxy(gThisModule, &CPPOverload_Type, "CPPOverload"))
862 
863 // inject template proxy type
864  if (!Utility::InitProxy(gThisModule, &TemplateProxy_Type, "TemplateProxy"))
866 
867 // inject property proxy type
868  if (!Utility::InitProxy(gThisModule, &CPPDataMember_Type, "CPPDataMember"))
870 
871 // inject custom data types
872  if (!Utility::InitProxy(gThisModule, &RefFloat_Type, "Double"))
874 
877 
878  if (!Utility::InitProxy(gThisModule, &CustomInstanceMethod_Type, "InstanceMethod"))
880 
881  if (!Utility::InitProxy(gThisModule, &TupleOfInstances_Type, "InstancesArray"))
883 
884  if (!Utility::InitProxy(gThisModule, &InstanceArrayIter_Type, "instancearrayiter"))
886 
887  if (!Utility::InitProxy(gThisModule, &PyNullPtr_t_Type, "nullptr_t"))
889 
890 // initialize low level ptr type, but do not inject in gThisModule
891  if (PyType_Ready(&LowLevelView_Type) < 0)
893 
894 // custom iterators
895  if (PyType_Ready(&IndexIter_Type) < 0)
897 
898  if (PyType_Ready(&VectorIter_Type) < 0)
900 
901 // inject identifiable nullptr
902  gNullPtrObject = (PyObject*)&_CPyCppyy_NullPtrStruct;
903  Py_INCREF(gNullPtrObject);
904  PyModule_AddObject(gThisModule, (char*)"nullptr", gNullPtrObject);
905 
906 // C++-specific exceptions
907  PyObject* cppfatal = PyErr_NewException((char*)"cppyy.ll.FatalError", nullptr, nullptr);
908  PyModule_AddObject(gThisModule, (char*)"FatalError", cppfatal);
909 
910  gBusException = PyErr_NewException((char*)"cppyy.ll.BusError", cppfatal, nullptr);
911  PyModule_AddObject(gThisModule, (char*)"BusError", gBusException);
912  gSegvException = PyErr_NewException((char*)"cppyy.ll.SegmentationViolation", cppfatal, nullptr);
913  PyModule_AddObject(gThisModule, (char*)"SegmentationViolation", gSegvException);
914  gIllException = PyErr_NewException((char*)"cppyy.ll.IllegalInstruction", cppfatal, nullptr);
915  PyModule_AddObject(gThisModule, (char*)"IllegalInstruction", gIllException);
916  gAbrtException = PyErr_NewException((char*)"cppyy.ll.AbortSignal", cppfatal, nullptr);
917  PyModule_AddObject(gThisModule, (char*)"AbortSignal", gAbrtException);
918 
919 // policy labels
920  PyModule_AddObject(gThisModule, (char*)"kMemoryHeuristics",
921  PyInt_FromLong((int)CallContext::kUseHeuristics));
922  PyModule_AddObject(gThisModule, (char*)"kMemoryStrict",
923  PyInt_FromLong((int)CallContext::kUseStrict));
924 
925 // gbl namespace is injected in cppyy.py
926 
927 // create the memory regulator
928  static MemoryRegulator s_memory_regulator;
929 
930 #if PY_VERSION_HEX >= 0x03000000
931  Py_INCREF(gThisModule);
932  return gThisModule;
933 #endif
934 }
PyTypeObject IndexIter_Type
PyTypeObject InstanceArrayIter_Type
#define CPYCPPYY_INIT_ERROR
PyTypeObject CPPScope_Type
Definition: CPPScope.cxx:613
TCppScope_t TCppType_t
Definition: cpp_cppyy.h:19
#define pyname
Definition: TMCParticle.cxx:19
#define LIBCPPYY_INIT_FUNCTION(a, b, c, d)
PyTypeObject CPPOverload_Type
static PyMethodDef gCPyCppyyMethods[]
#define LIBCPPYY_NAME
PyInt_FromLong
Definition: Converters.cxx:858
auto * m
Definition: textangle.C:8
bool CPPInstance_Check(T *object)
Definition: CPPInstance.h:118
bool gDictLookupActive
Definition: Utility.cxx:27
static PyObject * CPyCppyy_PyCapsule_New(void *cobj, const char *, void(*destr)(void *))
Definition: CPyCppyy.h:117
#define CPYCPPYY_GET_DICT_LOOKUP(mp)
PyTypeObject VectorIter_Type
bool InitProxy(PyObject *module, PyTypeObject *pytype, const char *name)
Definition: Utility.cxx:594
Py_ssize_t GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, bool check=true)
Definition: Utility.cxx:614
#define Py_RETURN_TRUE
Definition: CPyCppyy.h:285
std::string ConstructTemplateArgs(PyObject *pyname, PyObject *tpArgs, PyObject *args=nullptr, ArgPreference=kNone, int argoff=0, int *pcnt=nullptr)
Definition: Utility.cxx:473
#define Py_TYPE(ob)
Definition: CPyCppyy.h:209
#define PyVarObject_HEAD_INIT(type, size)
Definition: CPyCppyy.h:207
RPY_EXPORTED void AddSmartPtrType(const std::string &)
#define CPyCppyy_PyText_Type
Definition: CPyCppyy.h:115
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
PyObject * DestroyPyStrings()
Definition: PyStrings.cxx:128
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
PyObject * gPyTypeMap
PyObject * gThisModule
Definition: API.cxx:32
static bool SetGlobalSignalPolicy(bool setProtected)
Definition: CallContext.cxx:53
PyObject * gDict
Definition: PyStrings.cxx:14
static PyNumberMethods nullptr_as_number
PyObject * gSegvException
#define Py_RETURN_NONE
Definition: CPyCppyy.h:281
static PyTypeObject PyNullPtr_t_Type
PyTypeObject TemplateProxy_Type
dict_lookup_func gDictLookupOrg
Definition: Utility.cxx:26
PyTypeObject RefInt_Type
PyTypeObject CustomInstanceMethod_Type
bool CPPDataMember_CheckExact(T *object)
Definition: CPPDataMember.h:46
_object PyObject
Definition: PyMethodBase.h:41
TTime operator*(const TTime &t1, const TTime &t2)
Definition: TTime.h:85
#define _(A, B)
Definition: cfortran.h:108
long Py_hash_t
Definition: CPyCppyy.h:133
std::map< std::string, std::vector< PyObject * > > gPythonizations
PyObject * BindCppObject(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
PyTypeObject CPPDataMember_Type
#define CPYCPPYY_ORGDICT_LOOKUP(mp, key, hash, value_addr, hashpos)
PyTypeObject RefFloat_Type
Custom "builtins," detectable by type, for pass by ref and improved performance.
#define CPyCppyy_PyText_FromString
Definition: CPyCppyy.h:102
#define CPyCppyy_PyText_FromFormat
Definition: CPyCppyy.h:101
PyObject * gIllException
void * GetAddress(CPPInstance *pyobj)
bool CPPDataMember_Check(T *object)
Definition: CPPDataMember.h:40
int type
Definition: TGX11.cxx:120
PyObject * gBusException
std::set< Cppyy::TCppType_t > gPinnedTypes
bool CPPScope_Check(T *object)
Definition: CPPScope.h:76
#define PY_SSIZE_T_FORMAT
Definition: CPyCppyy.h:231
#define Py_RETURN_FALSE
Definition: CPyCppyy.h:289
static PyObject * nullptr_repr(PyObject *)
auto * l
Definition: textangle.C:4
PyDictEntry *(* dict_lookup_func)(PyDictObject *, PyObject *, long)
Definition: CPyCppyy.h:69
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
PyTypeObject CPPInstance_Type
PyTypeObject CPPExcInstance_Type
PyObject * gAbrtException
bool CreatePyStrings()
Definition: PyStrings.cxx:66
PyTypeObject TupleOfInstances_Type
Representation of C-style array of instances.
static int nullptr_nonzero(PyObject *)
static void * CPyCppyy_PyCapsule_GetPointer(PyObject *capsule, const char *)
Definition: CPyCppyy.h:123
PyTypeObject LowLevelView_Type
PyObject * gName
Definition: PyStrings.cxx:26
PyObject * gNullPtrObject
#define CPyCppyy_PyText_Check
Definition: CPyCppyy.h:95
static bool SetMemoryPolicy(ECallFlags e)
Definition: CallContext.cxx:41
static void nullptr_dealloc(PyObject *)
#define CPyCppyy_PyText_AsString
Definition: CPyCppyy.h:97