pybind11使用教程笔记__4.3_binding STL containers -- opaque types

Making opaque types

为了处理这种情况,pybind11 提供了PYBIND11_MAKE_OPAQUE(T)的宏,这个宏使得类型转换不依赖于template-based conversion machinery of types。
这样一来是他们不透明。 opaque types 对象are never inspected or extracted, 因而可以通过引用进行传递。如将std::vector<int>转为opaque类型, 在编写binding code前,先添加如下声明:
PYBIND11_MAKE_OPAQUE(std::vector<int>)

这个宏必须在程序顶部进行声明,并且不能在namespcae当中,因为这句宏会对模板的初始化进行重载,如果有多个编译单元,那么需要在每个源文件中使用std::vector<int>前都要有这句宏,通常是共用一个头文件。
通常还会有一个class 来bind相关的operation,以便python能否调用相关操作。

py::class_<std::vector<int>>(m, "IntVector")
    .def(py::init<>())
    .def("clear", &std::vector<int>::clear)
    .def("pop_back", &std::vector<int>::pop_back)
    .def("__len__", [](const std::vector<int> &v) { return v.size(); })
    .def("__iter__", [](std::vector<int> &v) {
       return py::make_iterator(v.begin(), v.end());
    }, py::keep_alive<0, 1>()) /* Keep vector alive while iterator is used */
    // ....

pybind11 源码中 tests/test_opaque_types.cpp 有使用opaque完整的例子,且细节比较丰富。

代码

  • cpp代码

/*
    tests/test_opaque_types.cpp -- opaque types, passing void pointers

    Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>

    All rights reserved. Use of this source code is governed by a
    BSD-style license that can be found in the LICENSE file.
*/

// #include "pybind11_tests.h"
#include <pybind11/stl.h>
#include <vector>
#include <pybind11/pybind11.h>

namespace py = pybind11;
// IMPORTANT: Disable internal pybind11 translation mechanisms for STL data structures
//
// This also deliberately doesn't use the below StringList type alias to test
// that MAKE_OPAQUE can handle a type containing a `,`.  (The `std::allocator`
// bit is just the default `std::vector` allocator).
PYBIND11_MAKE_OPAQUE(std::vector<std::string, std::allocator<std::string>>);

using StringList = std::vector<std::string, std::allocator<std::string>>;

PYBIND11_MODULE(opaque_types, m) {
    // test_string_list
    py::class_<StringList>(m, "StringList")
        .def(py::init<>())
        .def("pop_back", &StringList::pop_back)
        /* There are multiple versions of push_back(), etc. Select the right ones. */
        .def("push_back", (void (StringList::*)(const std::string &)) &StringList::push_back)
        .def("back", (std::string &(StringList::*)()) &StringList::back)
        .def("__len__", [](const StringList &v) { return v.size(); })
        .def("__iter__", [](StringList &v) {
               return py::make_iterator(v.begin(), v.end());
            }, py::keep_alive<0, 1>());

    class ClassWithSTLVecProperty {
        public:
            StringList stringList;
    };
    py::class_<ClassWithSTLVecProperty>(m, "ClassWithSTLVecProperty")
        .def(py::init<>())
        .def_readwrite("stringList", &ClassWithSTLVecProperty::stringList);

    m.def("print_opaque_list", [](const StringList &l) {
        std::string ret = "Opaque list: [";
        bool first = true;
        for (auto entry : l) {
            if (!first)
                ret += ", ";
            ret += entry;
            first = false;
        }
        return ret + "]";
    });

    // test_pointers

}
  • py test code
from opaque_types import StringList, print_opaque_list

sl = StringList()
print_opaque_list(sl)
#%%

sl_2 = StringList()
sl_2
sl_2.push_back("1")
sl_2.push_back("hello")
sl_2.push_back("today")
sl_2.push_back("now")

print_opaque_list(sl_2)
print(sl_2.__iter__() )

for item in sl_2:
    print(item)

result:

print_opaque_list(sl)
Out[27]: 'Opaque list: []'

print_opaque_list(sl_2)
Out[28]: 'Opaque list: [1, hello, today, now]'

for item in sl_2:
    print(item)
1
hello
today
now
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值