《人生苦短,我用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,转载注明出处🙉

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

相关文章
|
人工智能 机器人 C++
【C++/Python】Windows用Swig实现C++调用Python(史上最简单详细,80岁看了都会操作)
【C++/Python】Windows用Swig实现C++调用Python(史上最简单详细,80岁看了都会操作)
|
搜索推荐 数据挖掘 PyTorch
Py之albumentations:albumentations库函数的简介、安装、使用方法之详细攻略续篇
Py之albumentations:albumentations库函数的简介、安装、使用方法之详细攻略续篇
Py之albumentations:albumentations库函数的简介、安装、使用方法之详细攻略续篇
|
C++ Python
【Pybind11】pybind11在visual studio中的配置
【Pybind11】pybind11在visual studio中的配置
|
Python
Python实用记录(十六):PyQt/PySide6联动VSCode便捷操作指南
本文提供了一份详细的PySide6与VSCode联动的操作指南,包括安装配置VSCode、安装必要的扩展、配置扩展以及编辑和运行PySide6项目。文中还提到了相关工具如uic.exe、rcc.exe和designer.exe的用途,并提供了进一步学习的资源。
2762 1
Python实用记录(十六):PyQt/PySide6联动VSCode便捷操作指南
|
Ubuntu Linux Shell
C++ 之 perf+火焰图分析与调试
【11月更文挑战第6天】在遇到一些内存异常的时候,经常这部分的代码是很难去进行分析的,最近了解到Perf这个神器,这里也展开介绍一下如何使用Perf以及如何去画火焰图。
714 5
|
C++ Python
【C++/Python】C++调用python文件
【C++/Python】C++调用python文件
|
C++ Python
探索Python与C/C++混合编程的艺术
探索Python与C/C++混合编程的艺术
585 1
|
Unix C语言 C++
Python调用C/C++
Python调用C/C++
1051 2
|
测试技术 开发工具 git
面向 C++ 的现代 CMake 教程(三)(3)
面向 C++ 的现代 CMake 教程(三)
914 0
|
网络协议 Linux 编译器
【原创】EtherCAT主站IgH解析(二)-- 如何将Igh移植到Linux/Windows/RTOS等多操作系统移植指南
EtherCAT主站方案对比:商业的如Acontis、TwinCAT3和开源的igh、SOEM。SOEM易移植但功能和实时性不足,适合简单应用;igh功能强大,实时性能优秀,基于内核态,适合复杂场景。igh能移植到其他RTOS,但需克服多任务无调度的挑战。依赖操作系统服务如定时器、内存分配,适合Linux内核,但移植到裸机复杂。
1724 0