【问题标题】:Problem with passing STL containers using pybind11使用 pybind11 传递 STL 容器的问题
【发布时间】:2022-01-04 22:23:06
【问题描述】:

我的目标是能够将 std::map 从 Python 传递到 C++,用 C++ 填充它,然后在 Python 端查看结果。这是如何实现的?我什至无法让 std::vector 工作。

我在 C++ 中有这样的函数定义

void predict(std::vector<T>& seq, std::map<T, double>& probabilities)

main.cpp 看起来像这样

#include "node.h"
#include "probtree.h"
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>

PYBIND11_MAKE_OPAQUE(std::vector<double>);
PYBIND11_MAKE_OPAQUE(std::map<double, double>);

namespace py = pybind11;

using namespace std;

int main(int argc, char** argv){

}

PYBIND11_MODULE(sps_c, m){
    py::bind_vector<std::vector<double>>(m, "VectorD");
    py::bind_map<std::map<double, double>>(m, "MapDD");
    py::class_<ProbTree<double>>(m, "ProbTree")
        .def(py::init())
        .def("process", &ProbTree<double>::process)
        .def("predict", &ProbTree<double>::predict)
        ;
}

我期望的工作都没有:

>>> import sps_c
>>> pt = sps_c.ProbTree
>>> vd = sps_c.VectorD
>>> m = sps_c.MapDD
>>> pt.process(vd)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: process(): incompatible function arguments. The following argument types are supported:
    1. (self: sps_c.ProbTree, arg0: sps_c.VectorD) -> None

Invoked with: <class 'sps_c.VectorD'>

也许是一个列表?

>>> pt.process([1.0])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: process(): incompatible function arguments. The following argument types are supported:
    1. (self: sps_c.ProbTree, arg0: sps_c.VectorD) -> None

Invoked with: [1.0]

我该如何做?

还有一个问题是 STL 方法不可用:

vd.push_back(1.0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'sps_c.VectorD' has no attribute 'push_back'

我是否必须编写一堆样板才能让 STL 容器工作?

【问题讨论】:

    标签: python c++ pybind11


    【解决方案1】:

    您的第一个示例不起作用,因为您使用类而不是实例调用方法。我认为这应该可行:

    >>> pt = sps_c.ProbTree()
    >>> vd = sps_c.VectorD()
    >>> pt.process(vd)
    

    关于你的第二个例子:没有自动类型转换,所以你需要自己转换:

    >>> pt_instance.process(sps_c.VectorD(vd))
    

    关于第三个示例:push_back 和其他方法都可以在它们常用的 Python 名称下使用。这没有很好的记录,所以这里是它们的列表 (from here):

    bind_vector 公开了appendclearextendinsertpop 和一些迭代器方法。 bind_map 公开了keysvaluesitems 和一些迭代器方法。

    如果包含的类型不可复制,这些方法可能不可用。

    【讨论】:

    • 是的,愚蠢的错误忘记了括号。感谢您指出可用的方法。删除#include 、PYBIND11_MAKE_OPAQUE(std::vector); 和 PYBIND11_MAKE_OPAQUE(std::map); 后,我能够让它工作。这里缺少的:github.com/pybind/pybind11/blob/master/tests/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-19
    • 1970-01-01
    • 1970-01-01
    • 2020-02-29
    • 1970-01-01
    相关资源
    最近更新 更多