Logo ROOT  
Reference Guide
DispatchPtr.h
Go to the documentation of this file.
1 #ifndef CPYCPPYY_DISPATCHPTR_H
2 #define CPYCPPYY_DISPATCHPTR_H
3 
4 //////////////////////////////////////////////////////////////////////////////
5 // //
6 // DispatchPtr //
7 // //
8 // Smart pointer for reference management and C++ instance tracking when //
9 // cross-inheriting. The carried pointer is always expected to be derived //
10 // from CPPInstance, and the DispatchPtr to be embedded in the C++ instance //
11 // derived dispatcher to which it points (ownership is two-way; life-times //
12 // are equal). The C++ dispatcher then uses the DispatchPtr to call Python //
13 // functions for virtual methods. //
14 // //
15 //////////////////////////////////////////////////////////////////////////////
16 
17 // Bindings
18 #include "CPyCppyy/CommonDefs.h"
19 
20 
21 namespace CPyCppyy {
22 
24 public:
25 // Default constructor: only ever created from C++, as by definition, creation
26 // from the Python side makes the relevant Python instance available. Calls to
27 // the default ctor happen eg. in STL containers. It is expected that the
28 // pointer to the Python object is filled in later, eg. through assign().
29  DispatchPtr() : fPyHardRef(nullptr), fPyWeakRef(nullptr) {}
30 
31 // Conversion constructor: called with C++ object construction when the PyObject
32 // is known (eg. when instantiating from Python), with pyobj the Python-side
33 // representation of the C++ object.
34  explicit DispatchPtr(PyObject* pyobj);
35 
36 // Copy constructor: only ever called from C++. The Python object needs to be
37 // copied, in case it has added state, and rebound to the new C++ instance.
38  DispatchPtr(const DispatchPtr& other, void* cppinst);
39 
40 // Assignment: only ever called from C++. Similarly to the copy constructor, the
41 // Pythonb object needs to be copied and rebound.
42  DispatchPtr& assign(const DispatchPtr& other, void* cppinst);
43 
44 // Do not otherwise allow straight copies/assignment.
45  DispatchPtr(DispatchPtr&) = delete;
46  DispatchPtr(DispatchPtr&&) = delete;
47  DispatchPtr& operator=(const DispatchPtr& other) = delete;
48 
49 // lifetime is directly bound to the lifetime of the dispatcher object
51  Py_XDECREF(fPyWeakRef);
52  Py_XDECREF(fPyHardRef);
53  }
54 
55 // either C++ owns the Python object through a reference count (on fPyHardRef) or
56 // Python owns the C++ object and we only have a weak reference (through fPyWeakRef)
57  void PythonOwns();
58  void CppOwns();
59 
60 // access to underlying object: cast and dereferencing
61  operator PyObject*() const {
62  return Get();
63  }
64 
65  PyObject* operator->() const {
66  return Get();
67  }
68 
69 private:
70  PyObject* Get() const;
71 
72 private:
75 };
76 
77 } // namespace CPyCppyy
78 
79 #endif // !CPYCPPYY_DISPATCHPTR_H
PyObject * fPyHardRef
Definition: DispatchPtr.h:73
#define CPYCPPYY_CLASS_EXTERN
Definition: CommonDefs.h:29
_object PyObject
Definition: PyMethodBase.h:41
PyObject * fPyWeakRef
Definition: DispatchPtr.h:74
Binding & operator=(OUT(*fun)(void))
PyObject * operator->() const
Definition: DispatchPtr.h:65