python - 使用 Pybind11 包装 STL 容器返回类型

标签 python c++ pybind11

我打算包装一个 C++ 函数(使用 Pybind11),它返回一个本身包装在智能指针中的 STL 容器。一个例子如下所示。该函数已重载,因此我必须指定签名。

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

typedef std::array<std::complex<double>, 4> ArrayComplex4;
PYBIND11_MAKE_OPAQUE(ArrayComplex4);

namespace py = pybind11;
using namespace my_namespace;

PYBIND11_MODULE(my_module, m) {
    py::class_<MyClass>(m, "MyClass", py::dynamic_attr())
        .def("my_function", (std::unique_ptr<ArrayComplex4> (MyClass::*)(double)) &MyClass::my_function)
        .def("my_function", (std::unique_ptr<ArrayComplex4> (MyClass::*)(double, double)) &MyClass::my_function);
}

该模块将编译,但当我尝试在 Python 中使用该函数时会出现错误:

TypeError: Unable to convert function return value to a Python type!

我确定我只是为 Pybind11 设置了错误。感谢您的帮助!

编辑

问题肯定出在我尝试绑定(bind) std::Array 数据类型时。我最终修改了代码以使用 std::Vector 然后 Pybind11 没有问题。请参阅下面 AS Mackey 的回答,了解如何绑定(bind) std::Array 容器。

最佳答案

问题可能出在 ArrayComplex4 数据结构的 PYBIND11_MAKE_OPAQUE 处理上,我无法让它工作,尽管我有空时会再看一下。

下面的代码,我确实开始工作,是我迄今为止最接近你的设计的近似值。我使用了一个额外的用户定义的数据结构来包装 std::元素:

#include <pybind11/pybind11.h>
#include <pybind11/complex.h>
#include <pybind11/stl.h>
#include <memory>
#include <complex>
#include <array>
#include <cmath>

namespace py = pybind11;


typedef std::array<std::complex<double>, 4> ArrayComplex4;

struct ArrayComplex4Holder
{
    ArrayComplex4 data;
    ArrayComplex4 getData() { return data; }
};

class MyClass {
public:
    MyClass() { }
    std::unique_ptr<ArrayComplex4Holder> my_function(double x)
    {
        std::unique_ptr<ArrayComplex4Holder> ph( new ArrayComplex4Holder());
        ph->data[0] = std::complex<double>(x);
        return ph;
    }
    std::unique_ptr<ArrayComplex4Holder> my_function(double x, double y)
    {
        std::unique_ptr<ArrayComplex4Holder> ph( new ArrayComplex4Holder());
        ph->data[0] = std::complex<double>(x);
        ph->data[1] = std::complex<double>(y);
        return ph;
    }
};

PYBIND11_MODULE(example, m) {
    m.doc() = "pybind11 example"; // optional module docstring

    py::class_<ArrayComplex4Holder>(m, "ArrayComplex4Holder")
            .def(py::init<>())
            .def("getData", &ArrayComplex4Holder::getData);

    py::class_<MyClass>(m, "MyClass")
            .def(py::init<>())
            .def("my_function", (std::unique_ptr<ArrayComplex4Holder> (MyClass::*)(double))         &MyClass::my_function)
            .def("my_function", (std::unique_ptr<ArrayComplex4Holder> (MyClass::*)(double, double)) &MyClass::my_function);
}

注意我发现需要额外的 pybind #includes 才能使 python 转换工作。

简单的python代码是:

import sys
sys.path.append('/Volumes/RAID 1/Projects/workspace/Project CPP 1')
import example

p = example.MyClass()
print (p.my_function(1.2345).getData())
print (p.my_function(1.2345, 6.7890).getData())

这会产生以下输出,看起来是正确的:

[(1.2345+0j), 0j, 0j, 0j]
[(1.2345+0j), (6.789+0j), 0j, 0j]

我希望这能为您提供一个工作起点。我很想知道您是否找到了更好的选择...问候,AS

关于python - 使用 Pybind11 包装 STL 容器返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46008172/

相关文章:

python - 如何在 Python-OpenCV 中使用 `cv2.inRange` 检测两种不同的颜色?

python - 如何将 pandas 中的列索引转换为行索引?

c++ - 新图的深拷贝构造函数

python - 使用 Python、C++ 和 pybind11 返回和传递原始 POD 指针(数组)

python - uwsgi内部可调用文件模块导入错误

python - 使用 Pandas 数据框中的两列计算加权和

c++ - 有没有办法将 2 个变量放在一个变量中? (这有点难以解释)

c++ - 在 C++ 中将 unsigned int 转换为 int 时避免整数溢出的有效方法是什么?

python - 使用pybind11在C++中涉及多线程的问题

python - 我可以使用 pybind11 将 numpy 数组传递给接受 Eigen::Tensor 的函数吗?