pybind11 - Return shared_ptr 个 std::vector

pybind11 - Return a shared_ptr of std::vector

我有一个存储 std::shared_ptr of std::vector<uint32_t> 的成员变量。我想为 test_func2() 创建一个 Python 绑定,这样我就可以访问该向量而无需任何额外的副本。这是一个骨架代码。

#include <vector>
#include <memory>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>

namespace py = pybind11;



class TestLoader
{
private:
    std::shared_ptr<std::vector<uint32_t>>  tileData;

public:
    TestLoader();
    ~TestLoader();
    void test_func1();
    std::shared_ptr<std::vector<uint32_t>> test_func2()  const;
};

void  TestLoader::test_func1() {
    tileData = std::make_shared<std::vector<uint32_t>>(100000000);
    for(auto &x: *tileData){ x = 1;}
}
std::shared_ptr<std::vector<uint32_t>>  TestLoader::test_func2() const{

    return tileData;
}

接口代码如下:

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

namespace py = pybind11;
PYBIND11_MODULE(fltest_lib, m) {
    py::class_<TestLoader,  std::shared_ptr<TestLoader>>(m, "TestLoader")
    .def(py::init<const std::string &>())
    .def("test_func1", &TestLoader::test_func1)
    .def("test_func2", &TestLoader::test_func2, py::return_value_policy::reference_internal);
}

但是,这无法编译,我收到一条很长的错误消息。其中一行如下:

/home/samee/fl_test/lib/pybind11/include/pybind11/cast.h:653:61: error: static assertion failed: Holder classes are only supported for custom types
  653 |     static_assert(std::is_base_of<base, type_caster<type>>::value,
      |                                                             ^~~~~

任何避免这种情况的帮助都会非常有帮助。

根据this issue, it doesn't work because std::vector<uint32_t> is not converted to a python type. So, you will have to return the dereferenced vector. To avoid copies, you can use PYBIND11_MAKE_OPAQUE

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>

#include "test_loader.h"

namespace py = pybind11;

PYBIND11_MAKE_OPAQUE(std::vector<uint32_t>);

PYBIND11_MODULE(fltest_lib, m) {
  py::bind_vector<std::vector<uint32_t>>(m, "VectorUInt32");
  py::class_<TestLoader, std::shared_ptr<TestLoader>>(m, "TestLoader")
      .def(py::init())
      .def("test_func1", &TestLoader::test_func1)
      .def("test_func2",
           [](const TestLoader& tl) -> const std::vector<uint32_t>& {
             return *tl.test_func2();
           }, py::return_value_policy::reference_internal);
}