使用pybind11绑定数组

问题描述 投票:0回答:1

我在c中具有如下结构

typedef struct _person{
         int id[10];
         int number[10];
}person;

如何使用pybind11绑定它?

pybind11
1个回答
0
投票

[当您希望数据可写时,似乎没有AFAICT的好方法(当数据为只读时,它的设计要少一些)。无论如何,假设您已经安装了numpy,以下操作可以解决问题:

#include <pybind11/pybind11.h>
#include <pybind11/pytypes.h>
#include <pybind11/numpy.h>


typedef struct _person{
    int id[10];
    int number[10];
} person;

PYBIND11_MODULE(person, m)
{   
    pybind11::class_<person>(m, "person", pybind11::buffer_protocol())
        .def(pybind11::init<>())
        .def_property("id", [](person &p) -> pybind11::array {
            auto dtype = pybind11::dtype(pybind11::format_descriptor<int>::format());
            auto base = pybind11::array(dtype, {10}, {sizeof(int)});
            return pybind11::array(
                dtype, {10}, {sizeof(int)}, p.id, base);
        }, [](person& p) {})
        .def_property("number", [](person &p) -> pybind11::array {
            auto dtype = pybind11::dtype(pybind11::format_descriptor<int>::format());
            auto base = pybind11::array(dtype, {10}, {sizeof(int)});
            return pybind11::array(dtype, {10}, {sizeof(int)}, p.number, base);
        }, [](person& p) {});
}

该票证将提供一个空的基础对象,该对象使数组表现为视图对象。没有基础,它将复制。您不需要属性设置器(如果实现,则可以设置数组,而不是数组项),并且可能会引发错误,而不是像我那样提供无操作。另外,如果确实有两个相同大小的数组,则可以使用辅助函数代替lambda。

绑定C内置数组的基本问题是python没有合适的数组类型(有一个基本的内存视图和模块数组,但是没有真正的数组类型),因此您需要从某个地方获取一个,并且pybind11更喜欢从numpy那里获得一款,因为它是镇上最好的游戏。

只是为了向您展示一个替代方法,在cppyy(http://cppyy.org)中,我采取了另一种方法:它具有低级数组视图,随后可以将其交给numpy进行查看或复制,因为它实现了全缓冲协议。这样做的好处是可以由python用户决定最终用途。缺点是,如果您仍然要使用numpy,那将是一个额外的步骤。但它也可以直接使用而无需安装numpy:

import cppyy

cppyy.cppdef("""
typedef struct _person{
    int id[10];
    int number[10];
} person;
""")

p = cppyy.gbl.person()
print(len(p.id), p.id)
print(list(p.id))

产生:

(10, <cppyy.LowLevelView object at 0x105ab33b0>)
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
© www.soinside.com 2019 - 2024. All rights reserved.