栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Pybind11 tutorial

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Pybind11 tutorial

pybind core features

pybind11(available in https://github.com/pybind/pybind11) is a lightweight header-only library that exposes C++ types in Python and vice versa, mainly to create Python bindings of existing C++ code

similar project: Boost.python

advantages of pybind compared to Boost.python:
dramatically simpler binding code in many common situations

Include with PyPI
pip install pybind11

  • Functions accepting and returning custom data structures per value, reference, or pointer
// example.cpp
#include 

int add(int i, int j) {
    return i + j;
}

PYBIND11_MODULE(example, m) {
    m.doc() = "pybind11 example plugin"; // optional module docstring

    m.def("add", &add, "A function which adds two numbers");
}

# CMakeLists
find_package(pybind11)

pybind11_add_module(example
                    example.cpp              
)

m.doc()–>对于这一个module的说明

PYBIND11_MODULE(example, m)中example是module的名字,m defines a variable of type

py::module_ which can be used to initialize the module.

  • Object-oriented code
struct Pet {
    Pet(const std::string &name) : name(name) { }
    void setName(const std::string &name_) { name = name_; }
    const std::string &getName() const { return name; }

    std::string name;
};
#include 

namespace py = pybind11;

PYBIND11_MODULE(example, m) {
    py::class_(m, "Pet")
        .def(py::init())
        .def("setName", &Pet::setName)
        .def("getName", &Pet::getName);
}
% python
>>> import example
>>> p = example.Pet('Molly')
>>> print(p)

>>> p.getName()
u'Molly'
>>> p.setName('Charly')
>>> p.getName()
u'Charly'

注意到上面的print打印出的内容对于我们掌握pet的信息并没有什么帮助,所以我们可以重写,增加一句

 .def("__repr__",
        [](const Pet &a) {
            return "";
        }

此时

print(p)

还能在python端给类增加新的属性

py::class_(m, "Pet", py::dynamic_attr())
    .def(py::init<>())
    .def_readwrite("name", &Pet::name);
p = example.Pet()
>>> p.name = 'Charly'  # OK, overwrite value in C++
>>> p.age = 2  # OK, dynamically add a new attribute
>>> p.__dict__  # just like a native Python class
{'age': 2}

方法重载

py::class_(m, "Pet")
    .def("set", py::overload_cast(&Pet::set), "Set the pet's age")
    .def("set", py::overload_cast(&Pet::set), "Set the pet's name");
  • Functions

return value policies(具体说明在官方文档),默认的为automatic

a wrong example

Data *get_data() { return _data;  }
...


m.def("get_data", &get_data); // <-- KABOOM, will cause crash when called from Python

需要被更改为

m.def("get_data", &get_data, py::return_value_policy::reference);
  • Class

如果在类中定义了纯虚函数,那么在绑定的时候需要定义一个trampoline class来辅助绑定

范例:

class Animal {
public:
    virtual ~Animal() { }
    virtual std::string go(int n_times) = 0;
};

class Dog : public Animal {
public:
    std::string go(int n_times) override {
        std::string result;
        for (int i=0; i 

trampoline class:

class PyAnimal : public Animal {
public:
    
    using Animal::Animal;

    
    std::string go(int n_times) override {
        PYBIND11_OVERRIDE_PURE(
            std::string, 
            Animal,      
            go,          
            n_times      
        );
    }
};

绑定代码:

PYBIND11_MODULE(example, m) {
    py::class_(m, "Animal")
        .def(py::init<>())
        .def("go", &Animal::go);

    py::class_(m, "Dog")
        .def(py::init<>());

    m.def("call_go", &call_go);
}

py_heuristic_load_planner中

class ContainerTrampoline
    : public Container
  {
  public:
    using base_container_t = Container;
    using base_container_t::base_container_t;

    void load_all() override
    {
      PYBIND11_OVERRIDE(void, base_container_t, load_all,
      );
    }
    LoadStatus load_once() override
    {
      PYBIND11_OVERRIDE_PURE(LoadStatus, base_container_t, load_once,
      );
    }
  };

注意在PYBIND11_OVERRIDE中是只识别逗号的,所以当使用带有多个模板的模板类的时候需要先使用using关键字,再填写否则会报错

pybind11还能够绑定factory function和lamda function

pickling support:

Python’s pickle module provides a powerful facility to serialize and de-serialize a Python object graph into a binary data stream

class Pickleable {
public:
    Pickleable(const std::string &value) : m_value(value) { }
    const std::string &value() const { return m_value; }

    void setExtra(int extra) { m_extra = extra; }
    int extra() const { return m_extra; }
private:
    std::string m_value;
    int m_extra = 0;
};
py::class_(m, "Pickleable")
    .def(py::init())
    .def("value", &Pickleable::value)
    .def("extra", &Pickleable::extra)
    .def("setExtra", &Pickleable::setExtra)
    .def(py::pickle(
        [](const Pickleable &p) { // __getstate__
            
            return py::make_tuple(p.value(), p.extra());
        },
        [](py::tuple t) { // __setstate__
            if (t.size() != 2)
                throw std::runtime_error("Invalid state!");

            
            Pickleable p(t[0].cast());

            
            p.setExtra(t[1].cast());

            return p;
        }
    ));
  • Smart pointers

std::unique_ptr:

不用做额外处理

std::shared_ptr:

#include 
namespace py = pybind11;
class Child { };
class Parent {
public:
   Parent() : child(std::make_shared()) { }
private:
    std::shared_ptr child;
};
PYBIND11_MODULE(example, m) {
    py::class_>(m, "Child");

    py::class_>(m, "Parent")
       .def(py::init<>());
}

Reference: https://pybind11.readthedocs.io/en/latest/

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/275372.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号