175 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
		
		
			
		
	
	
			175 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
|  | Smart pointers
 | ||
|  | ##############
 | ||
|  | 
 | ||
|  | std::unique_ptr
 | ||
|  | ===============
 | ||
|  | 
 | ||
|  | Given a class ``Example`` with Python bindings, it's possible to return
 | ||
|  | instances wrapped in C++11 unique pointers, like so
 | ||
|  | 
 | ||
|  | .. code-block:: cpp
 | ||
|  | 
 | ||
|  |     std::unique_ptr<Example> create_example() { return std::unique_ptr<Example>(new Example()); }
 | ||
|  | 
 | ||
|  | .. code-block:: cpp
 | ||
|  | 
 | ||
|  |     m.def("create_example", &create_example);
 | ||
|  | 
 | ||
|  | In other words, there is nothing special that needs to be done. While returning
 | ||
|  | unique pointers in this way is allowed, it is *illegal* to use them as function
 | ||
|  | arguments. For instance, the following function signature cannot be processed
 | ||
|  | by pybind11.
 | ||
|  | 
 | ||
|  | .. code-block:: cpp
 | ||
|  | 
 | ||
|  |     void do_something_with_example(std::unique_ptr<Example> ex) { ... }
 | ||
|  | 
 | ||
|  | The above signature would imply that Python needs to give up ownership of an
 | ||
|  | object that is passed to this function, which is generally not possible (for
 | ||
|  | instance, the object might be referenced elsewhere).
 | ||
|  | 
 | ||
|  | std::shared_ptr
 | ||
|  | ===============
 | ||
|  | 
 | ||
|  | The binding generator for classes, :class:`class_`, can be passed a template
 | ||
|  | type that denotes a special *holder* type that is used to manage references to
 | ||
|  | the object.  If no such holder type template argument is given, the default for
 | ||
|  | a type named ``Type`` is ``std::unique_ptr<Type>``, which means that the object
 | ||
|  | is deallocated when Python's reference count goes to zero.
 | ||
|  | 
 | ||
|  | It is possible to switch to other types of reference counting wrappers or smart
 | ||
|  | pointers, which is useful in codebases that rely on them. For instance, the
 | ||
|  | following snippet causes ``std::shared_ptr`` to be used instead.
 | ||
|  | 
 | ||
|  | .. code-block:: cpp
 | ||
|  | 
 | ||
|  |     py::class_<Example, std::shared_ptr<Example> /* <- holder type */> obj(m, "Example");
 | ||
|  | 
 | ||
|  | Note that any particular class can only be associated with a single holder type.
 | ||
|  | 
 | ||
|  | One potential stumbling block when using holder types is that they need to be
 | ||
|  | applied consistently. Can you guess what's broken about the following binding
 | ||
|  | code?
 | ||
|  | 
 | ||
|  | .. code-block:: cpp
 | ||
|  | 
 | ||
|  |     class Child { };
 | ||
|  | 
 | ||
|  |     class Parent {
 | ||
|  |     public:
 | ||
|  |        Parent() : child(std::make_shared<Child>()) { }
 | ||
|  |        Child *get_child() { return child.get(); }  /* Hint: ** DON'T DO THIS ** */
 | ||
|  |     private:
 | ||
|  |         std::shared_ptr<Child> child;
 | ||
|  |     };
 | ||
|  | 
 | ||
|  |     PYBIND11_MODULE(example, m) {
 | ||
|  |         py::class_<Child, std::shared_ptr<Child>>(m, "Child");
 | ||
|  | 
 | ||
|  |         py::class_<Parent, std::shared_ptr<Parent>>(m, "Parent")
 | ||
|  |            .def(py::init<>())
 | ||
|  |            .def("get_child", &Parent::get_child);
 | ||
|  |     }
 | ||
|  | 
 | ||
|  | The following Python code will cause undefined behavior (and likely a
 | ||
|  | segmentation fault).
 | ||
|  | 
 | ||
|  | .. code-block:: python
 | ||
|  | 
 | ||
|  |    from example import Parent
 | ||
|  | 
 | ||
|  |    print(Parent().get_child())
 | ||
|  | 
 | ||
|  | The problem is that ``Parent::get_child()`` returns a pointer to an instance of
 | ||
|  | ``Child``, but the fact that this instance is already managed by
 | ||
|  | ``std::shared_ptr<...>`` is lost when passing raw pointers. In this case,
 | ||
|  | pybind11 will create a second independent ``std::shared_ptr<...>`` that also
 | ||
|  | claims ownership of the pointer. In the end, the object will be freed **twice**
 | ||
|  | since these shared pointers have no way of knowing about each other.
 | ||
|  | 
 | ||
|  | There are two ways to resolve this issue:
 | ||
|  | 
 | ||
|  | 1. For types that are managed by a smart pointer class, never use raw pointers
 | ||
|  |    in function arguments or return values. In other words: always consistently
 | ||
|  |    wrap pointers into their designated holder types (such as
 | ||
|  |    ``std::shared_ptr<...>``). In this case, the signature of ``get_child()``
 | ||
|  |    should be modified as follows:
 | ||
|  | 
 | ||
|  | .. code-block:: cpp
 | ||
|  | 
 | ||
|  |     std::shared_ptr<Child> get_child() { return child; }
 | ||
|  | 
 | ||
|  | 2. Adjust the definition of ``Child`` by specifying
 | ||
|  |    ``std::enable_shared_from_this<T>`` (see cppreference_ for details) as a
 | ||
|  |    base class. This adds a small bit of information to ``Child`` that allows
 | ||
|  |    pybind11 to realize that there is already an existing
 | ||
|  |    ``std::shared_ptr<...>`` and communicate with it. In this case, the
 | ||
|  |    declaration of ``Child`` should look as follows:
 | ||
|  | 
 | ||
|  | .. _cppreference: http://en.cppreference.com/w/cpp/memory/enable_shared_from_this
 | ||
|  | 
 | ||
|  | .. code-block:: cpp
 | ||
|  | 
 | ||
|  |     class Child : public std::enable_shared_from_this<Child> { };
 | ||
|  | 
 | ||
|  | .. _smart_pointers:
 | ||
|  | 
 | ||
|  | Custom smart pointers
 | ||
|  | =====================
 | ||
|  | 
 | ||
|  | pybind11 supports ``std::unique_ptr`` and ``std::shared_ptr`` right out of the
 | ||
|  | box. For any other custom smart pointer, transparent conversions can be enabled
 | ||
|  | using a macro invocation similar to the following. It must be declared at the
 | ||
|  | top namespace level before any binding code:
 | ||
|  | 
 | ||
|  | .. code-block:: cpp
 | ||
|  | 
 | ||
|  |     PYBIND11_DECLARE_HOLDER_TYPE(T, SmartPtr<T>);
 | ||
|  | 
 | ||
|  | The first argument of :func:`PYBIND11_DECLARE_HOLDER_TYPE` should be a
 | ||
|  | placeholder name that is used as a template parameter of the second argument.
 | ||
|  | Thus, feel free to use any identifier, but use it consistently on both sides;
 | ||
|  | also, don't use the name of a type that already exists in your codebase.
 | ||
|  | 
 | ||
|  | The macro also accepts a third optional boolean parameter that is set to false
 | ||
|  | by default. Specify
 | ||
|  | 
 | ||
|  | .. code-block:: cpp
 | ||
|  | 
 | ||
|  |     PYBIND11_DECLARE_HOLDER_TYPE(T, SmartPtr<T>, true);
 | ||
|  | 
 | ||
|  | if ``SmartPtr<T>`` can always be initialized from a ``T*`` pointer without the
 | ||
|  | risk of inconsistencies (such as multiple independent ``SmartPtr`` instances
 | ||
|  | believing that they are the sole owner of the ``T*`` pointer). A common
 | ||
|  | situation where ``true`` should be passed is when the ``T`` instances use
 | ||
|  | *intrusive* reference counting.
 | ||
|  | 
 | ||
|  | Please take a look at the :ref:`macro_notes` before using this feature.
 | ||
|  | 
 | ||
|  | By default, pybind11 assumes that your custom smart pointer has a standard
 | ||
|  | interface, i.e. provides a ``.get()`` member function to access the underlying
 | ||
|  | raw pointer. If this is not the case, pybind11's ``holder_helper`` must be
 | ||
|  | specialized:
 | ||
|  | 
 | ||
|  | .. code-block:: cpp
 | ||
|  | 
 | ||
|  |     // Always needed for custom holder types
 | ||
|  |     PYBIND11_DECLARE_HOLDER_TYPE(T, SmartPtr<T>);
 | ||
|  | 
 | ||
|  |     // Only needed if the type's `.get()` goes by another name
 | ||
|  |     namespace pybind11 { namespace detail {
 | ||
|  |         template <typename T>
 | ||
|  |         struct holder_helper<SmartPtr<T>> { // <-- specialization
 | ||
|  |             static const T *get(const SmartPtr<T> &p) { return p.getPointer(); }
 | ||
|  |         };
 | ||
|  |     }}
 | ||
|  | 
 | ||
|  | The above specialization informs pybind11 that the custom ``SmartPtr`` class
 | ||
|  | provides ``.get()`` functionality via ``.getPointer()``.
 | ||
|  | 
 | ||
|  | .. seealso::
 | ||
|  | 
 | ||
|  |     The file :file:`tests/test_smart_ptr.cpp` contains a complete example
 | ||
|  |     that demonstrates how to work with custom reference-counting holder types
 | ||
|  |     in more detail.
 |