pybind如何操作py :: list对象

Jua*_*oMF 3 c++ python pybind11

为了更好地理解如何使用pybind库将参数从Python传递到C++函数,我想构建一个小的虚拟/演示代码,我可以在C++端接收Python列表,将其转换为浮点指针对象,以及然后打印出来.

虽然我知道我可以使用这个py::list类,但我还没有想出这个类可用的方法.我查看了文档参考,然后在代码(list.h,stl.h)中查找并且无法确定哪些方法可用.

相当于__getitem__什么?我有可用的每个python方法py::list吗?

Eve*_*len 7

您正在寻找的代码在这里:

class list : public object {
public:
    PYBIND11_OBJECT_CVT(list, object, PyList_Check, PySequence_List)
    explicit list(size_t size = 0) : object(PyList_New((ssize_t) size), stolen_t{}) {
        if (!m_ptr) pybind11_fail("Could not allocate list object!");
    }
    size_t size() const { return (size_t) PyList_Size(m_ptr); }
    detail::list_accessor operator[](size_t index) const { return {*this, index}; }
    detail::list_iterator begin() const { return {*this, 0}; }
    detail::list_iterator end() const { return {*this, PyList_GET_SIZE(m_ptr)}; }
    template <typename T> void append(T &&val) const {
        PyList_Append(m_ptr, detail::object_or_cast(std::forward<T>(val)).ptr());
    }
};
Run Code Online (Sandbox Code Playgroud)

还要记住,py::list继承自py::object,继承自py::handle(这也意味着你通过引用传递).根据我的经验,这种用法的文档很少,阅读代码是最好的选择.

我们可以从类定义,我们可以使用成员函数看size,operator[],begin,end(C++迭代器!)和append(模板!).如果这还不够,您可以使用attr访问python属性(包括方法).这是一个例子:

Python代码(some_python.py):

import cppimport
cpp = cppimport.imp("some_cpp")

l = [1,2,3,4,5]
cpp.test(l)
print('after C++', l)

cpp.float_cast(l)
Run Code Online (Sandbox Code Playgroud)

C++代码(some_cpp.cpp):

/* <%
setup_pybind11(cfg)
%> */

#include <pybind11/pybind11.h>
#include <iostream>
#include <string>

namespace py = pybind11;

void test(py::list l) {
    l.attr("pop")();
    std::cout << "List has length " << l.size() << std::endl;
    for (py::handle obj : l) {  // iterators!
        std::cout << "  - " << obj.attr("__str__")().cast<std::string>() << std::endl;
    }
    l.append(10);  // automatic casting (through templating)!
}

void float_cast(py::list l) {
    float f = l.cast<float>();
}

PYBIND11_MODULE(some_cpp, m) {
    m.def("test", &test);
    m.def("float_cast", &float_cast);
}
Run Code Online (Sandbox Code Playgroud)

输出:

List has length 4
  - 1
  - 2
  - 3
  - 4
after C++ [1, 2, 3, 4, 10]
Traceback (most recent call last):
  File "some_python.py", line 9, in <module>
    cpp.float_cast(l)
RuntimeError: Unable to cast Python instance to C++ type (compile in debug mode for details)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我还将您的特定问题包括在浮动中.在这里我使用了cast方法py::handle,它提供了一个很好的例外.您可以尝试"直接"投射对象(类似的东西float* f = (float*) &l;),但这会给你垃圾,我想这不是你想要的.

还有一点:pybind/stl.h在Python的标准类型和C++版本之间进行转换.例如,a list可以转换为a std::vector<int>,包括typechecks.这样做的一个重要影响是数据作为副本而不是作为引用传递.