《人生苦短,我用python·三》pybind11简单使用

简介: 《人生苦短,我用python·三》pybind11简单使用

Pybind11 是一个轻量级的 C++ 库,用于将你的 C++ 代码暴露给 Python 调用(反之也可,但主要还是前者)。Pybind11 借鉴了 Boost::Python 库的设计,但使用了更为简洁的实现方式,使用了大量 C++11 的新特性,更易于使用。

对于Pybind11和Ctype方式都可以使用Python访问C++代码,但区别在于使用 PyBind11,我们可以更轻松地共享许多数据类型,而使用 ctypes 是一种低级的 C 样式解决方案,共享许多数据类型需要相当多的低级解决方法。例如,虽然ctypes不支持复数等基本的东西,但PyBind11使Numpy与Eigen完全互操作,需要最少的代码。

使用pybind11需要注意的是开发者使用哪个版本编译的pybind11,调用者也必须使用这个版本的python才可以调用。

Pybind11使用:

1、先安装pybind11

pip install pybind11

2、克隆pybind11代码

git clone pybind11代码(https://github.com/pybind/pybind11

3、加入Python头文件

(1)VS2019创建动态库(我这里是写了一个C++动态库专门存放pybind11的接口),在附加包含目录加入pybind11和python头文件(注意:动态库的cpp文件不要删掉,不然编译无法生产lib文件)

(2)附加库目录:

(3)附加依赖项:

(4)属性-配置属性-高级-目标文件扩展名-改为.pyd

(5)加入如下代码(案例):

#include <pybind11/pybind11.h>
#include<Python.h>
namespace py = pybind11;
PYBIND11_MODULE(pybind, m){
  m.doc() = "pybind11的案例";
  m.def("func", [](){return "这是pybind11的一个方法";}); 
}

编译成功会生成.pyd和.lib文件,可以在python中调用pybind11的方法或者类。

注意:PYBIND11_MODULE后面的名字和文件名要相同

一些常见用法案例:

当前文件名为pybindTest.h

#pragma once
#include <pybind11/pybind11.h>
#include<Python.h>
namespace py = pybind11;
const char* add(int i, int j) 
{
  return "helloworld";
}
PYBIND11_MODULE(pybindTest, m){
  //可选,说明这个模块是做什么的
  m.doc() = "pybind11的案例";
  //7/def(“给python调用方法名”,&实际操作的函效, 函数功能说明” ).其中函数功能说明为可选
  m.def("add", &add, "A function which adds two numbers", py::arg("i") = 1, py::arg("j") = 2):
}

第二条也可以写成m.def(“add”, &add);

python调用:

>>> import sys

>>> sys.path.append(“D:/pybindTest/x64/Debug/”)

>>> import pybindtest

>>> print(pybindtest.add(1,2))

Helloworld

案例2:

py::class_是用来给C++ class 或者 struct-style 的数据结构创建binding的。

py:: init()用来给相应的初始化函数创建binding。

#pragma once
#include <iostream>
#include <vector>
#include <pybind11/pybind11. h>
#include <Python.h>
#include <pybind11/st1.h> /1 函数中用到了C++的STL库,所以要包含该头文件
namespace py = pybind11;
//向量求和,返回一个向量
std::vector<doub1e> sum(const std::vector<doub1e>& vec1, const std::vector<doub1e>& vec2){
  auto result = vec1;
  for(int i = 0:i < vec1.size(); i++){
    result[i] += vec2[i];
  }
  return result;
}
//定义一个向量类
c1ass Vector {
public:
  Vector() = default;
  ~Vector() = default;
  std::vector<double> sum(const std::vector<doub1e>& vecl, const std::vector<double>& vec2) {
    auto result = vec1;
    for(int i=0;i<vec1.size():i++){
      result[i] += vec2[i];
    }
    return result;
  }
}
PYBIND11_MODULE(pybindTest, m){
  //可选,说明这个模块是做什么的
  m.doc() = "pybind11的案例";
  //封装函数
  m.def(sum,&sum);
  //封装类
  pybindll::class_<Vector> (m "Vector")
    .def(pybind1::init())
    .def("sum", &Vector::sum);
}

pybind11封装QT动态库:

Intrument_Controll.h是QT动态库的一个头文件,想要调用这个头文件类中的方法那么需要创建QT动态库,C++动态库不可以调用QT动态库,用pybind11封装好后,在Python命令行下创建对象报错:

在目录下面明明有pybindtest2.pyd文件为啥调用不了?很可能是缺少某些DLL。现在在项目-属性-高级-目标文件扩展名把.pyd改回.dll,编译生成dll后用depend查看pybindtest2.dll缺少哪些dll,查看后得知缺少QT5CORED.DLL。

进入D:\QT\5.15.2\msvc2019_64\bin目录下把QT5CORED.DLL拷贝到pybindtest2目录下然后能正常调用。

注意:pybind11会自动析构间接的类指针

GetModuleByID(1)返回的是IMonocular指针多态调用Monocular子类方法,在GetCaptureDate之后在重复调用一次发现IMonocular指针已经被自动析构了,这种用指针间接调用方式想要不被自动析构有两个方法:

方法一:

写成直接方式:

ptr = intrument.GetModuleByID(1)

data = ptr.GetCaptureDate()

data = ptr.GetCaptureDate()

方式二:

在绑定的子类后面加std::unique_ptr<Monocular, py::nodelete>这样在间接调用类指针的时候不会被主动析构。

python类继承C++中的抽象类:

先在外层写一个中间类继承抽象类,中间类中成员方法的实现格式如下:

案例:MLCameraCallback是一个抽象类

然后在PYBIND11_MODULE(MLColorimeter_py, m)中如下实现:

在python中实现类继承C++抽象类MLCameraCallBack:

📢博客主页: 主页

📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

📢本文由 梦回阑珊 原创,首发于 CSDN,转载注明出处🙉

📢代码改变世界,你来改变代码!✨

相关文章
|
API Python Windows
python2.7 win32com 避坑指南
python2.7 win32com 避坑指南
806 0
|
6月前
|
自然语言处理 数据挖掘 Shell
8个很少用,但却很好用的 Python 库,一起来看看吧
8个很少用,但却很好用的 Python 库,一起来看看吧
|
11月前
|
网络架构 Python
官网说明:Python 2 or 3区别
官网说明:Python 2 or 3区别
38 0
|
编译器 C++ Python
《人生苦短,我用python·二》python在C++中的断点调试
《人生苦短,我用python·二》python在C++中的断点调试
114 0
|
机器学习/深度学习 数据采集 数据挖掘
人生苦短,我用Python:如何入门Python的世界
人生苦短,我用Python:如何入门Python的世界
|
数据采集 前端开发 搜索推荐
我用什么写Python?
对编程新手来说,开发环境的选择常常成为入门后的第一道坎。因为捣鼓了半天没能成功运行代码而被迫从入门到放弃的情景并不少见。初上手时选择的编辑器是否易用也会直接影响你的学习热情。
|
Python Windows
【Python入门】人生苦短,我用Python
【Python入门】人生苦短,我用Python
|
存储 IDE JavaScript
python教程基础篇(一看就懂)
Python由荷兰数学和计算机科学研究学会的吉多·范罗苏姆于1990年代初设计,作为一门叫做ABC语言的替代品。
python教程基础篇(一看就懂)
|
Python
Python3.6.3安装详细简单完整版
Python3.6.3安装详细简单完整版
680 0
Python3.6.3安装详细简单完整版
|
算法 JavaScript Unix
怎么样才算是精通 Python?
程序员写过简历的都知道,先说精通->后说熟悉->最后说了解,要把精通放在最前面。 But 很少人会说自己精通Python,这也是因为Python的应用领域是真的多,最好还是说自己精通的领域,而不是语言,除非你真的是大佬。
254 0
怎么样才算是精通 Python?