首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从pybind11包装特征中返回数组的列表或元组

从pybind11包装特征中返回数组的列表或元组
EN

Stack Overflow用户
提问于 2019-05-25 02:14:30
回答 2查看 4.2K关注 0票数 4

我有一个使用eigen的c++函数,它是用pybind11包装的,这样我就可以从python中调用它。目标函数的一个简单版本返回一个Eigen::MatrixXd类型,pybind成功地将其转换为2Dnumpy数组。

我希望这个函数能够返回这样的矩阵的列表或元组,或者3D numpy数组。

我在某种程度上是c++的新手,pybind的文档(据我所知)没有提供任何指导。下面是一个模拟示例:

test.cpp

代码语言:javascript
复制
#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中:

代码语言:javascript
复制
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数组也是可以接受的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-25 22:24:06

我以前使用过Eigen,但我不是专家,所以其他人可能能够改进这个解决方案。

代码语言:javascript
复制
#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数组列表。结果:

代码语言:javascript
复制
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.]])]
票数 3
EN

Stack Overflow用户

发布于 2020-09-09 08:08:37

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

代码语言:javascript
复制
std::tuple<Eigen::MatrixXd,int> function(){
    ...
    int m = 4;
    Eigen::MatrixXd M = ...;
    ...

    return make_tuple(std::move(M),m);
}

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

代码语言:javascript
复制
m.def("function", &function, py::return_value_policy::reference_internal);

代码语言:javascript
复制
m.def("function", &function);

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56297728

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档