Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:07

0001 #ifndef CPYCPPYY_DISPATCHPTR_H
0002 #define CPYCPPYY_DISPATCHPTR_H
0003 
0004 //////////////////////////////////////////////////////////////////////////////
0005 //                                                                          //
0006 // DispatchPtr                                                              //
0007 //                                                                          //
0008 // Smart pointer for reference management and C++ instance tracking when    //
0009 // cross-inheriting. The carried pointer is always expected to be derived   //
0010 // from CPPInstance, and the DispatchPtr to be embedded in the C++ instance //
0011 // derived dispatcher to which it points (ownership is two-way; life-times  //
0012 // are equal). The C++ dispatcher then uses the DispatchPtr to call Python  //
0013 // functions for virtual methods.                                           //
0014 //                                                                          //
0015 //////////////////////////////////////////////////////////////////////////////
0016 
0017 // Bindings
0018 #include "CPyCppyy/CommonDefs.h"
0019 
0020 
0021 namespace CPyCppyy {
0022 
0023 class CPYCPPYY_CLASS_EXTERN DispatchPtr {
0024 public:
0025 // Default constructor: only ever created from C++, as by definition, creation
0026 // from the Python side makes the relevant Python instance available. Calls to
0027 // the default ctor happen eg. in STL containers. It is expected that the
0028 // pointer to the Python object is filled in later, eg. through assign().
0029     DispatchPtr() : fPyHardRef(nullptr), fPyWeakRef(nullptr) {}
0030 
0031 // Conversion constructor: called with C++ object construction when the PyObject
0032 // is known (eg. when instantiating from Python), with pyobj the Python-side
0033 // representation of the C++ object.
0034     explicit DispatchPtr(PyObject* pyobj, bool strong = false);
0035 
0036 // Copy constructor: only ever called from C++. The Python object needs to be
0037 // copied, in case it has added state, and rebound to the new C++ instance.
0038     DispatchPtr(const DispatchPtr& other, void* cppinst);
0039 
0040 // Assignment: only ever called from C++. Similarly to the copy constructor, the
0041 // Pythonb object needs to be copied and rebound.
0042     DispatchPtr& assign(const DispatchPtr& other, void* cppinst);
0043 
0044 // Do not otherwise allow straight copies/assignment.
0045     DispatchPtr(DispatchPtr&)  = delete;
0046     DispatchPtr(DispatchPtr&&) = delete;
0047     DispatchPtr& operator=(const DispatchPtr& other) = delete;
0048 
0049 // lifetime is directly bound to the lifetime of the dispatcher object
0050     ~DispatchPtr();
0051 
0052 // either C++ owns the Python object through a reference count (on fPyHardRef) or
0053 // Python owns the C++ object and we only have a weak reference (through fPyWeakRef)
0054     void PythonOwns();
0055     void CppOwns();
0056 
0057 // access to underlying object: cast and dereferencing
0058     operator PyObject*() const {
0059         return Get();
0060     }
0061 
0062     PyObject* operator->() const {
0063         return Get();
0064     }
0065 
0066 private:
0067     PyObject* Get() const;
0068 
0069 private:
0070     PyObject* fPyHardRef;
0071     PyObject* fPyWeakRef;
0072 };
0073 
0074 } // namespace CPyCppyy
0075 
0076 #endif // !CPYCPPYY_DISPATCHPTR_H