Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
DispatchPtr.h
Go to the documentation of this file.
1#ifndef CPYRT_DISPATCHPTR_H
2#define CPYRT_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 <Python.h>
19#include "cpyrt/CommonDefs.h"
20
21namespace cppjit::cpyrt {
23 PyGILState_STATE state;
24
25public:
26 PythonGILRAII() : state(PyGILState_Ensure()) {}
27 ~PythonGILRAII() { PyGILState_Release(state); }
28};
29
31public:
32 // Default constructor: only ever created from C++, as by definition, creation
33 // from the Python side makes the relevant Python instance available. Calls to
34 // the default ctor happen eg. in STL containers. It is expected that the
35 // pointer to the Python object is filled in later, eg. through assign().
36 DispatchPtr() : fPyHardRef(nullptr), fPyWeakRef(nullptr) {}
37
38 // Conversion constructor: called with C++ object construction when the
39 // PyObject is known (eg. when instantiating from Python), with pyobj the
40 // Python-side representation of the C++ object.
41 explicit DispatchPtr(PyObject* pyobj, bool strong = false);
42
43 // Copy constructor: only ever called from C++. The Python object needs to be
44 // copied, in case it has added state, and rebound to the new C++ instance.
45 DispatchPtr(const DispatchPtr& other, void* cppinst);
46
47 // Assignment: only ever called from C++. Similarly to the copy constructor,
48 // the Pythonb object needs to be copied and rebound.
49 DispatchPtr& assign(const DispatchPtr& other, void* cppinst);
50
51 // Do not otherwise allow straight copies/assignment.
54 DispatchPtr& operator=(const DispatchPtr& other) = delete;
55
56 // lifetime is directly bound to the lifetime of the dispatcher object
58
59 // either C++ owns the Python object through a reference count (on fPyHardRef)
60 // or Python owns the C++ object and we only have a weak reference (through
61 // fPyWeakRef)
62 void PythonOwns();
63 void CppOwns();
64
65 // access to underlying object: cast and dereferencing
66 operator PyObject*() const { return Get(); }
67
68 PyObject* operator->() const { return Get(); }
69
70private:
71 PyObject* Get(bool borrowed = true) const;
72
73private:
76};
77
78} // namespace cppjit::cpyrt
79
80#endif // !CPYRT_DISPATCHPTR_H
_object PyObject
#define CPYRT_CLASS_EXTERN
Definition CommonDefs.h:29
DispatchPtr & operator=(const DispatchPtr &other)=delete
PyObject * operator->() const
Definition DispatchPtr.h:68
DispatchPtr(DispatchPtr &&)=delete
DispatchPtr(DispatchPtr &)=delete