• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 // Author: tibell@google.com (Johan Tibell)
9 
10 #ifndef GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__
11 #define GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__
12 
13 #define PY_SSIZE_T_CLEAN
14 #include <Python.h>
15 namespace google {
16 namespace protobuf {
17 namespace python {
18 
19 // Owns a python object and decrements the reference count on destruction.
20 // This class is not threadsafe.
21 template <typename PyObjectStruct>
22 class ScopedPythonPtr {
23  public:
24   // Takes the ownership of the specified object to ScopedPythonPtr.
25   // The reference count of the specified py_object is not incremented.
26   explicit ScopedPythonPtr(PyObjectStruct* py_object = nullptr)
ptr_(py_object)27       : ptr_(py_object) {}
28   ScopedPythonPtr(const ScopedPythonPtr&) = delete;
29   ScopedPythonPtr& operator=(const ScopedPythonPtr&) = delete;
30 
31   // If a PyObject is owned, decrement its reference count.
~ScopedPythonPtr()32   ~ScopedPythonPtr() { Py_XDECREF(ptr_); }
33 
34   // Deletes the current owned object, if any.
35   // Then takes ownership of a new object without incrementing the reference
36   // count.
37   // This function must be called with a reference that you own.
38   //   this->reset(this->get()) is wrong!
39   //   this->reset(this->release()) is OK.
40   PyObjectStruct* reset(PyObjectStruct* p = nullptr) {
41     Py_XDECREF(ptr_);
42     ptr_ = p;
43     return ptr_;
44   }
45 
46   // Releases ownership of the object without decrementing the reference count.
47   // The caller now owns the returned reference.
release()48   PyObjectStruct* release() {
49     PyObject* p = ptr_;
50     ptr_ = nullptr;
51     return p;
52   }
53 
get()54   PyObjectStruct* get() const { return ptr_; }
55 
as_pyobject()56   PyObject* as_pyobject() const { return reinterpret_cast<PyObject*>(ptr_); }
57 
58   // Increments the reference count of the current object.
59   // Should not be called when no object is held.
inc()60   void inc() const { Py_INCREF(ptr_); }
61 
62   // True when a ScopedPyObjectPtr and a raw pointer refer to the same object.
63   // Comparison operators are non reflexive.
64   bool operator==(const PyObjectStruct* p) const { return ptr_ == p; }
65   bool operator!=(const PyObjectStruct* p) const { return ptr_ != p; }
66 
67  private:
68   PyObjectStruct* ptr_;
69 };
70 
71 typedef ScopedPythonPtr<PyObject> ScopedPyObjectPtr;
72 
73 }  // namespace python
74 }  // namespace protobuf
75 }  // namespace google
76 #endif  // GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__
77