首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Pybind11包装STL容器返回类型

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

Stack Overflow用户
提问于 2017-09-01 21:29:10
回答 1查看 3.9K关注 0票数 4

我正在绑定一个C++函数(使用Pybind11),该函数返回一个STL容器,该容器本身封装在一个智能指针中。下面是一个例子。函数是重载的,所以我必须指定签名。

代码语言:javascript
复制
#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:无法将函数返回值转换为Python!

我确信我只是为Pybind11设置了错误的东西。谢谢你的帮助!

编辑

问题肯定在于我试图绑定std::Array数据类型。最后,我修改了代码以使用std::Vector,然后Pybind11就没有问题了。关于如何绑定std::Array容器,请参见下面Mackey的回答。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-02 14:49:02

问题可能在于PYBIND11_MAKE_OPAQUE对ArrayComplex4数据结构的处理,我无法让它工作,不过我会在有时间的时候再看一看。

下面的代码,我已经开始工作了,是我到目前为止最接近您的设计。我使用了一个额外的用户定义的数据结构来包装std::元素:

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

我发现,为了使python铸造工作,需要额外的pybind #includes。

简单的python代码是:

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

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

代码语言:javascript
复制
[(1.2345+0j), 0j, 0j, 0j]
[(1.2345+0j), (6.789+0j), 0j, 0j]

我希望这给你一个工作的起点。我想知道你是否能找到更好的选择..。当作,作为

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

https://stackoverflow.com/questions/46008172

复制
相关文章

相似问题

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