Merge pull request #368 from nbelakovski/master

Added support for exposing classes with private destructors and corresponding documentation
This commit is contained in:
Wenzel Jakob 2016-08-28 01:54:38 +02:00 committed by GitHub
commit 35540ea35d
2 changed files with 38 additions and 0 deletions

View File

@ -942,6 +942,37 @@ In other words, :func:`init` creates an anonymous function that invokes an
in-place constructor. Memory allocation etc. is already take care of beforehand
within pybind11.
.. _classes_with_non_public_destructors:
Classes with non-public destructors
===================================
If a class has a private or protected destructor, as might be the case in a singleton
pattern for example, a compile error will occur when trying to expose the class because
the std::unique_ptr holding the instance of the class will attempt to call its destructor
when de-allocating the instance. In order to expose classes with private or protected
destructors you can override the ``holder_type`` and provide a custom destructor. Pybind11
provides a blank destructor for you to use as follows
.. code-block:: cpp
/* ... definition ... */
class MyClass {
~MyClass() {}
};
/* ... binding code ... */
py::class_<MyClass, std::unique_ptr<MyClass, py::blank_deleter<MyClass>>(m, "MyClass")
.def(py::init<>)
The blank destructor provided by Pybind11 is a no-op, so you will still need to make sure
you are cleaning up the memory in C++. Additionally, the blank destructor, or any custom
destructor you provide to the unique_ptr will only be called if the object is initialized
within Python. If the object is initialized in C++ via a getter function, the deleter will
not be called at all.
.. _catching_and_throwing_exceptions:
Catching and throwing exceptions

View File

@ -350,4 +350,11 @@ PYBIND11_DECL_FMT(float, "f");
PYBIND11_DECL_FMT(double, "d");
PYBIND11_DECL_FMT(bool, "?");
// Helper class for exposing classes with a private destructor by overriding the deleter object of std::unique_ptr
template <typename T>
struct blank_deleter
{
void operator()(T*) {}
};
NAMESPACE_END(pybind11)