protected virtual destructor in pybind11 [duplicat

2019-08-20 16:23发布

问题:

This question already has an answer here:

  • protected destructor with unique_ptr 2 answers

I want to bind with the class from third party library. The class have some pure virtual functions but the destructor is protected and virtual.

In order to bind the class, I have to write a derived class that overrides the pure virtual functions (https://pybind11.readthedocs.io/en/stable/advanced/classes.html)

so the code is like this

class Parent {  
  public:  
    virtual void foo() = 0;
  protected:
    virtual ~ Parent() //Dtor
    {
    }
};

class PyParent : public Parent 
{
  public:
    void foo () override {
        PYBIND11_OVERLOAD_PURE(
            void,
            Parent,
            foo
        );
    }
};

void init(py::module & m) {
    py::class_<Parent, PyParent> p(m, "p");
}

However, since the destructor of the base class is declared as protected, the following errors are thrown

error: ‘virtual Parent::~Parent()’ is protected
         virtual ~ Parent() //Dtor

I can not modify the base class since it's a third party library.

Any idea to bind the class with pybind11?

回答1:

std::unique_ptr and std::shared_ptr are smart pointers supported by pybind out of box. Both of them require destructor to be public.

The simplest solution would be to write intermediate class with public destructor and expose it with pybind11.

...
class DeletableParent : public Parent{
public:
  ~DeletableParent() override = default;
};
...
py::class_<DeletableParent, PyParent> p(m, "p");

So all your Python classes will inherit from DeletableParent

If all you want to do is to make Parent-derived classes on Python side, this solution is fine.

If you want to expose a C++ Parent-derived-class which doesn't have DeletableParent as one of it's bases you will find difficulties in exposing such diverged inheritance relations.

Another option is to write your own smart pointer which does not call destructor of holded pointer. But it looks like straight road to memory leaks.

Update: I overlooked that this particular issue is already covered in pybind11 doc: https://pybind11.readthedocs.io/en/stable/advanced/classes.html#non-public-destructors



标签: c++ pybind11