Pybind11: Not able to return a shared_ptr from a py::init definition.

Created on 21 May 2018  路  1Comment  路  Source: pybind/pybind11

I have a C++ library that has factory functions which return shared_pointers to my various classes. You can't get access to the raw constructors for a bunch of reasons. I'm trying to wrap this lib in python with pybind11 and use those factory functions in py::init definitions. However, this doesn't work and causes a static assert in pybind11. If the factory function returns a raw or unique pointer it works happily, but my lib can't work that way. Given that you have wrapped normal C++ functions that return a range of holders, I would have thought this would have worked. The following code snippet replicates the error. If you change it to return a raw pointer or a std::unique_ptr it works fine. Have I found a bug or is it meant to work this way? Any suggested work arounds/code changes?

This is on XCode 9.3.1/ clang 9.1.0

#include <pybind11/pybind11.h>

namespace py = pybind11;

struct Blah {};

PYBIND11_MODULE(example, m)
{
  py::class_<Blah>(m, "Blah")
    .def(py::init([](size_t n)
                  {
                    // No problems if this is a raw pointer or a std::unique_ptr.
                    return std::shared_ptr<Blah>(new Blah); 
                  }));
}

The error message from clang is...

In file included from Modules/Wire/src/filiWirePythonBindings.cpp:1:
In file included from Thirdparty/pybind11/bncheckout/pybind11/include/pybind11/pybind11.h:46:
Thirdparty/pybind11/bncheckout/pybind11/include/pybind11/detail/init.h:237:35: error: cannot pass object of non-trivial type 'std::__1::shared_ptr<Blah>' through variadic function; call will abort at runtime [-Wnon-pod-varargs]
            construct<Class>(v_h, func(std::forward<Args>(args)...),
                                  ^
Thirdparty/pybind11/bncheckout/pybind11/include/pybind11/pybind11.h:1127:25: note: in instantiation of function template specialization 'pybind11::detail::initimpl::factory<(lambda at Modules/Wire/src/filiWirePythonBindings.cpp:10:19), pybind11::detail::void_type (*)(), std::__1::shared_ptr<Blah> (unsigned long), pybind11::detail::void_type ()>::execute<pybind11::class_<Blah>>' requested here
        std::move(init).execute(*this, extra...);
                        ^
Modules/Wire/src/filiWirePythonBindings.cpp:10:6: note: in instantiation of function template specialization 'pybind11::class_<Blah>::def<(lambda at Modules/Wire/src/filiWirePythonBindings.cpp:10:19), pybind11::detail::void_type (*)(), std::__1::shared_ptr<Blah> (unsigned long), pybind11::detail::void_type ()>' requested here
    .def(py::init([](size_t n)
     ^
In file included from Modules/Wire/src/filiWirePythonBindings.cpp:1:
In file included from Thirdparty/pybind11/bncheckout/pybind11/include/pybind11/pybind11.h:46:
Thirdparty/pybind11/bncheckout/pybind11/include/pybind11/detail/init.h:86:5: error: static_assert failed "pybind11::init(): init function must return a compatible pointer, holder, or value"
    static_assert(!std::is_same<Class, Class>::value /* always false */,
    ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Thirdparty/pybind11/bncheckout/pybind11/include/pybind11/detail/init.h:237:13: note: in instantiation of function template specialization 'pybind11::detail::initimpl::construct<pybind11::class_<Blah> >' requested here
            construct<Class>(v_h, func(std::forward<Args>(args)...),
            ^
Thirdparty/pybind11/bncheckout/pybind11/include/pybind11/pybind11.h:1127:25: note: in instantiation of function template specialization 'pybind11::detail::initimpl::factory<(lambda at Modules/Wire/src/filiWirePythonBindings.cpp:10:19), pybind11::detail::void_type (*)(), std::__1::shared_ptr<Blah> (unsigned long), pybind11::detail::void_type ()>::execute<pybind11::class_<Blah>>' requested here
        std::move(init).execute(*this, extra...);
                        ^
Modules/Wire/src/filiWirePythonBindings.cpp:10:6: note: in instantiation of function template specialization 'pybind11::class_<Blah>::def<(lambda at Modules/Wire/src/filiWirePythonBindings.cpp:10:19), pybind11::detail::void_type (*)(), std::__1::shared_ptr<Blah> (unsigned long), pybind11::detail::void_type ()>' requested here
    .def(py::init([](size_t n)
     ^
2 errors generated.

Most helpful comment

Ignore this. Figured it out from looking through the test code.

One suggestion, could you have more comprehensive documentation of the API. The developers guide is fine for getting started but a programmer's reference to the API would be marvellous.

>All comments

Ignore this. Figured it out from looking through the test code.

One suggestion, could you have more comprehensive documentation of the API. The developers guide is fine for getting started but a programmer's reference to the API would be marvellous.

Was this page helpful?
0 / 5 - 0 ratings