pybind / pybind/pybind11

[QUESTION] Protected / private desctructors of abstract base class

Open
#2,703 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
18k
Forks
2.3k
Avg merge
5d 17h
Merged PRs (30d)
10

Description

The following comes from a real c++ project I am trying to wrap using pybind11, on which I have no influence and where the path of raising issues is not clear.

So, for the sake of this example, please assume I cannot change any of the C++ classes I am trying to wrap.

The problem is, that I have an inheritance tree where two classes inherit from an abstract base class with a protected desctructor and I need to wrap a method that can return instances of either of these classes via a pointer to the abstract base with the protected destructor.

Example:


#include <pybind11/pybind11.h>

namespace py = pybind11;


class Base {
    protected:
        virtual ~Base() {};
};


class Derived1 : public Base {
    public:
        ~Derived1() {};
};

class Derived2 : public Base {
    public:
        ~Derived2() {};
};


std::unique_ptr<Base> func(bool one) {
    if (one) {
        return std::make_unique<Derived1>();
    } else {
        return std::make_unique<Derived2>();
    }
}



PYBIND11_MODULE(example, m) {
    py::class_<Base>(m, "Base");
    py::class_<Derived1, Base>(m, "Derived1")
        .def(py::init<>());
    py::class_<Derived2, Base>(m, "Derived2")
        .def(py::init<>());
        ;
    m.def("func", &func);
}

It all works fine if Base::~Base is public.

The docs say one can use py::nodelete here, but I don't want to do that due to the memory leakage that will follow from that.

This answer on stackoverflow proposes writing a class just making the destructor public: https://stackoverflow.com/questions/56240230/protected-virtual-destructor-in-pybind11

But I seem to be unable to inject it correctly into the class hierarchy to make it work (as mentioned in the answer)

Is there anyway to solve this case?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the minimal C++ example in the issue and review pybind11's documented py::nodelete behavior. Compare that approach with the linked Stack Overflow proposal for exposing the protected destructor; done would require a validated way to wrap the hierarchy without changing the original classes or leaking memory.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, python
Domain
tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.