返回Pybind11包装特征的阵列列表或元组



i使用eigen具有C 函数,该功能是使用Pybind11包装的,以便我可以从Python称呼它。预期功能的简单版本返回Eigen::MatrixXd类型,PyBind成功将其转换为2D Numpy数组。

我希望此功能能够返回此类矩阵的列表或元组,或一个3D numpy Array。

我有点像C 的新手,而Pybind的文档(据我所知(没有提供任何方向。一个模拟示例如下:

test.cpp

#include <pybind11/pybind11.h>
#include <pybind11/eigen.h>
#include <Eigen/Dense>
Eigen::MatrixXd test(Eigen::Ref<const Eigen::MatrixXd> x, double a)
{
  Eigen::MatrixXd y;
  y = x * a;
  return y;
}
Eigen::MatrixXd *test2(Eigen::Ref<const Eigen::MatrixXd> x, Eigen::Ref<const Eigen::VectorXd> as)
{
  Eigen::MatrixXd *ys = new Eigen::MatrixXd[as.size()];
  for(unsigned int k = 0; k < as.size(); k++){
    Eigen::MatrixXd& y = ys[k];
    y = x * as[k];
  }
  return ys;
}
namespace py = pybind11;
PYBIND11_MODULE(test, m)
{
  m.doc() = "minimal working example";
  m.def("test", &test);
  m.def("test2", &test2);
}

我希望 test2返回列表或元组。

在Python中:

import test
import numpy as np
x = np.random.random((50, 50))
x = np.asfortranarray(x)
a = 0.1
a2 = np.array([1.0, 2.0, 3.0])
y = test.test(x, a)
ys = test.test2(x, a2)

数组y是预期的,但是ys仅包含与a2的第一个系数相对应的数组。

我应该如何修改test2正确返回多个数组?3D阵列也可以接受。

我以前曾经使用过特征,但我不是专家,因此其他人也许可以改善此解决方案。

#include <pybind11/pybind11.h>
#include <pybind11/eigen.h>
#include <pybind11/stl.h>
#include <Eigen/Dense>
std::vector<Eigen::MatrixXd> 
test2(Eigen::Ref<const Eigen::MatrixXd> x, Eigen::Ref<const Eigen::VectorXd> as){
    std::vector<Eigen::MatrixXd> matrices;
    for(unsigned int k = 0; k < as.size(); k++){
        Eigen::MatrixXd ys = x * as[k];
        matrices.push_back(ys);
    }
    return matrices;
}
namespace py = pybind11;
PYBIND11_MODULE(test, m){
    m.doc() = "minimal working example";
    m.def("test2", &test2);
}

pybind11将向量转换为numpy阵列的列表。结果:

In [1]: import numpy as np; x = np.ones((2,2)); a = np.array((2., 3.)); import test
In [2]: test.test2(x, a)
Out[2]: 
[array([[2., 2.],
        [2., 2.]]), array([[3., 3.],
        [3., 3.]])]

我建议返回 std::tuple,但通过移动本地对象:

std::tuple<Eigen::MatrixXd,int> function(){
    ...
    int m = 4;
    Eigen::MatrixXd M = ...;
    ...
    return make_tuple(std::move(M),m);
}

PYBIND11_MODULE中,我不确定哪个是正确的:

m.def("function", &function, py::return_value_policy::reference_internal);

m.def("function", &function);

我已经根据需要测试了这两项工作,即在返回过程中复制和分配更多内存。

最新更新