From 5e4e477b8bade7d215471326bd1137289ac52bb2 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sun, 28 Aug 2016 02:03:15 +0200 Subject: [PATCH] minor fixes to PR #368 --- docs/advanced.rst | 26 ++++++++++++-------------- include/pybind11/common.h | 8 ++------ 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/docs/advanced.rst b/docs/advanced.rst index ddb99c089..96b64eae9 100644 --- a/docs/advanced.rst +++ b/docs/advanced.rst @@ -947,32 +947,30 @@ within pybind11. 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 +If a class has a private or protected destructor (as might e.g. be the case in +a singleton pattern), a compile error will occur when creating bindings via +pybind11. The underlying issue is that the ``std::unique_ptr`` holder type that +is responsible for managing the lifetime of instances will reference the +destructor even if no deallocations ever take place. In order to expose classes +with private or protected destructors, it is possible to override the holder +type via the second argument to ``class_``. Pybind11 provides a helper class +``py::nodelete`` that disables any destructor invocations. In this case, it is +crucial that instances are deallocated on the C++ side to avoid memory leaks. .. code-block:: cpp /* ... definition ... */ class MyClass { - ~MyClass() {} + private: + ~MyClass() { } }; /* ... binding code ... */ - py::class_>(m, "MyClass") + py::class_>(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 diff --git a/include/pybind11/common.h b/include/pybind11/common.h index ae008ca7c..8b794f750 100644 --- a/include/pybind11/common.h +++ b/include/pybind11/common.h @@ -350,11 +350,7 @@ 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 -struct blank_deleter -{ - void operator()(T*) {} -}; +/// Dummy destructor wrapper that can be used to expose classes with a private destructor +struct nodelete { template void operator()(T*) { } }; NAMESPACE_END(pybind11)