C++ 二维向量到二维 pybind11 数组

C++ 2D vector to 2D pybind11 array

我是 C++ 的新手,在使用 pybind 时遇到了困难。我根本不知道如何说服 pybind 将二维向量从 C++ 转换为 python 可读格式。

这就是我想到的代码:

py::array_t<float> to_matrix(std::vector<std::vector<float>> &vals)
{
    int N = vals.size();
    int M = 6;
    py::array_t<float>({N, M}) arr;
    for (int i = 0; (i < N); i++)
    {
        for (int j = 0; (j < M); j++)
        {
            arr[i][j] = vals[i][j];
        };
    };
    return arr;
};

C++ 的输入是一个包含 N 行和 6 列的向量的向量,只是一个非常长的数据点列表。理想情况下,我希望将输出作为 numpy 数组,但任何 python 数据结构都可以(例如,列表列表)。

文档听起来很简单,但我想不通。我做错了什么?

提前感谢您的帮助。

这里发生了一些事情,但让我们先从一个最小的示例开始。以下函数将从 hard-coded std::vector<std::vector<float>>

创建一个二维数组
py::array_t<float> to_matrix()
{
    std::vector<std::vector<float>> vals = {
        {1, 2, 3, 4, 5},
        {6, 7, 8, 9, 10},
        {11, 12, 13, 14, 15}
    };

    size_t N = vals.size();
    size_t M = vals[0].size();

    py::array_t<float, py::array::c_style> arr({N, M});

    auto ra = arr.mutable_unchecked();

    for (size_t i = 0; i < N; i++)
    {
        for (size_t j = 0; j < M; j++)
        {
            ra(i, j) = vals[i][j];
        };
    };

    return arr;
};

PYBIND11_MODULE(foo, m)
{
    m.def("to_matrix", &to_matrix);
}

有两点需要注意,首先数组形状是数组的构造函数参数。其次是使用 mutable_unchecked 获得可用于进行分配的代理 object。

在您的情况下,向量的向量将来自您的 C++ 代码中的其他地方。

但请注意,pybind11 还提供了用于包装容器的样板,例如 std::vector。这些在 header pybind11/stl_bind.h 中可用,并允许您执行此操作

std::vector<std::vector<float>> make_vector()
{
    std::vector<std::vector<float>> vals = {
        {1, 2, 3, 4, 5},
        {6, 7, 8, 9, 10},
        {11, 12, 13, 14, 15}
    };

    return vals;

}

PYBIND11_MODULE(foo, m)
{
    py::bind_vector<std::vector<std::vector<float>>>(m, "FloatVector2D");
    m.def("make_vector", &make_vector);
}

这样的 object 不会完全等同于 numpy 数组(没有 shape 属性等)