pybind11,使用 std::enable_shared_from_this 绑定 Trampolines 和多重继承时编译失败

pybind11, compile fails on binding Trampolines and multiple inheritance with std::enable_shared_from_this

我遇到了多重继承结合蹦床的编译问题。下一段代码说明了问题:

#include <pybind11/pybind11.h>
#include <memory>

namespace py = pybind11;

// classes
class A {
public:
    virtual int fA() const = 0;
};

class B : public A, public std::enable_shared_from_this< B > {
public:
    int fA() const override {return 1;}
    virtual int fB() const {return 2;}
};

// trampolines
class PyA : public A {
public:
    using A::A;

    int fA() const override {
        PYBIND11_OVERLOAD_PURE(int, A, fA);
    }
};

class PyB : public B {
public:
    using B::B;

    int fA() const override {
        PYBIND11_OVERLOAD(int, B, fA);
    }
    int fB() const override {
        PYBIND11_OVERLOAD(int, B, fB);
    }
};

// bindings
void Bind(py::module_& m)
{
    py::class_<A, PyA>(m, "A" )
        .def( py::init<>() )
        .def( "fA", &A::fA );

//  py::class_<B, PyB, std::enable_shared_from_this< B > >(m, "B")
//  py::class_<B, PyB, A, std::enable_shared_from_this< B > >(m, "B", py::multiple_inheritance())
//  py::class_<B, PyB>(m, "B", py::multiple_inheritance())
    py::class_<B, PyB>(m, "B")
        .def( py::init<>() )
        .def( "fA", &B::fA )
        .def( "fB", &B::fB );
}

很快,

下一个是c++17的输出:

1>------ Build started: Project: AWB, Configuration: Debug x64 ------
1>Microsoft (R) C/C++ Optimizing Compiler Version 19.16.27045 for x64
1>Copyright (C) Microsoft Corporation.  All rights reserved.
1>
1>cl /c /IE:\Projects\AWB\pybind11\include /ID:\Python38\include /Zi /W1 /WX- /diagnostics:classic /Od /Ob0 /D _WINDLL /D _UNICODE /D UNICODE /D WIN32 /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /std:c++17 /Fo"AWB.dir\Debug\" /Fd"AWB.dir\Debug\vc141.pdb" /Gd /TP /errorReport:prompt  /bigobj Source.cpp
1>
1>Source.cpp
1>E:\Projects\AWB\pybind11\include\pybind11/pybind11.h(1512): error C2664: 'std::unique_ptr<B,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': cannot convert argument 1 from 'std::shared_ptr<_Ty>' to 'std::nullptr_t'
1>        with
1>        [
1>            _Ty=B
1>        ]
1>E:\Projects\AWB\pybind11\include\pybind11/pybind11.h(1507): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>E:\Projects\AWB\pybind11\include\pybind11/pybind11.h(1549): note: see reference to function template instantiation 'void pybind11::class_<B,PyB>::init_holder<B>(pybind11::detail::instance *,pybind11::detail::value_and_holder &,const std::unique_ptr<B,std::default_delete<_Ty>> *,const std::enable_shared_from_this<_Ty> *)' being compiled
1>        with
1>        [
1>            _Ty=B
1>        ]
1>E:\Projects\AWB\pybind11\include\pybind11/pybind11.h(1555): note: see reference to function template instantiation 'void pybind11::class_<B,PyB>::init_holder<B>(pybind11::detail::instance *,pybind11::detail::value_and_holder &,const std::unique_ptr<B,std::default_delete<_Ty>> *,const std::enable_shared_from_this<_Ty> *)' being compiled
1>        with
1>        [
1>            _Ty=B
1>        ]
1>E:\Projects\AWB\pybind11\include\pybind11/pybind11.h(1549): note: while compiling class template member function 'void pybind11::class_<B,PyB>::init_instance(pybind11::detail::instance *,const void *)'
1>E:\Projects\AWB\pybind11\include\pybind11/pybind11.h(1284): note: see reference to function template instantiation 'void pybind11::class_<B,PyB>::init_instance(pybind11::detail::instance *,const void *)' being compiled
1>Source.cpp(50): note: see reference to class template instantiation 'pybind11::class_<B,PyB>' being compiled
1>e:\projects\awb\pybind11\include\pybind11\cast.h(1638): note: see reference to class template instantiation 'pybind11::detail::descr<8>' being compiled
1>e:\projects\awb\pybind11\include\pybind11\cast.h(1637): note: see reference to class template instantiation 'pybind11::detail::descr<3>' being compiled
1>e:\projects\awb\pybind11\include\pybind11\cast.h(1636): note: see reference to class template instantiation 'pybind11::detail::descr<5>' being compiled
1>e:\projects\awb\pybind11\include\pybind11\cast.h(1177): note: see reference to class template instantiation 'pybind11::detail::descr<7>' being compiled
1>Done building project "AWB.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

如果我尝试使用另一个简单的 class (C) 而不是 std::enable_shared_from_this 一切正常。所以问题可能出在 py:class_<B, PyB, ? >... 行或其他地方的适当公式中......

我做错了什么?

谢谢

你解决了这个问题。根据 pybind's documentation,如果您没有为 class 指定任何持有人,则默认为 std::unique_ptr,据我所知,它与 std::enable_shared_from_this 不兼容。

因此,使用 py:class_<B, PyB, std::shared_ptr<B>> 应该可以解决您的编译问题。我试过这个解决方案,它适用于我的盒子。