python - pybind 如何操作 py::list 对象

标签 python c++ pybind11

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

虽然我知道我可以使用 py::list 类,但我还没有弄清楚这个类的可用方法。我查看了文档引用,然后查看了代码(list.h、STL.h),但无法弄清楚哪些方法可用。

__getitem__ 的等价物是什么? py::list 是否有可用的所有 python 方法?

最佳答案

您要找的代码是here :

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());
    }
};

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

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

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)

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);
}

输出:

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)

如您所见,我还包括了您关于转换为 float 的具体问题。在这里,我使用了 cast py::handle的方法| ,这给出了一个很好的异常(exception)。您可以尝试“直接”转换对象(类似 float* f = (float*) &l; ),但这会给您垃圾,我想这不是您要找的。

再多说一句:pybind/stl.h启用 Python 的标准类型和 C++ 版本之间的转换。例如,list可以转换为 std::vector<int> ,包括类型检查。这样做的一个重要影响是数据作为拷贝而不是作为引用传递。

关于python - pybind 如何操作 py::list 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50883703/

相关文章:

c++ - "How to impress interviewers with my coding? What practices can I adopt in the code I' 已经为给面试官留下深刻印象的问题而写了吗?

c++ - Eigen 中填充稀疏矩阵的速度取决于节点数或边数?

python - 从 pybind11 包装特征返回数组列表或元组

python - 尝试读取在 Python 中创建的对象时访问冲突传递给 C++ 端的 std::vector 然后返回给 Python

c++ - 使用 python3-config 进行 Pybind11 编译不起作用

python - 为什么在处理函数和类中的未绑定(bind)局部变量时存在差异?

python - """TypeError: only length-1 arrays can be converted to Python scalars"""尝试在具有 7 段显示的 Pi3 上运行计数器时

python - 无法通过 Grafana API 导入 grafana 仪表板

python - 迭代 excel-sheets 名称从 "Line"开始

c# - InfoPath 2010 中的规则或代码关闭浏览器窗口