Python 和 C++ 混合编程:pybind11 使用

这篇具有很好参考价值的文章主要介绍了Python 和 C++ 混合编程:pybind11 使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 目的需求

我们通常在 Python 上进行算法开发,因为 Python 编程方便,易于快速验证算法。而在验证算法正确后,如果对运行效率有更高要求的话,则会将计算密集的模块使用 C/C++ 重新实现,来达到代码运行效率加速的效果。所以,这就涉及到了 Python 和 C++ 混合编程,而在这方面 pybind11 是一个很流行的库,可以很好的开展 Python 和 C++ 混合编程,并通过 Python 的 import 调用动态链接库(.so/.pyd等)达到本地代码加速。

2. pybind 11 简介

  • 代码链接:https://github.com/pybind/pybind11

  • 文档链接:https://pybind11.readthedocs.io/en/stable/index.html

pybind11 是一个轻量级的只包含头文件的库,它在Python中公开C++类型,反之亦然,主要用于创建现有C++代码的Python绑定。它的目标和语法类似于David Abrahams的优秀Boost.Python库:通过使用编译时内省推断类型信息,最大限度地减少传统扩展模块中的样板代码。

3. 使用实践:一个简单的实例

3.1 开发环境

  • ubuntu 20.04

  • cmake

  • python 3.9:此处实践中,使用 conda 管理 python 虚拟环境,此处新建 env_test 环境,可参考 Anaconda 的使用;对于非虚拟环境,方法大同小异;

3.2 准备工作

  • 安装相关库
conda install pybind11
conda install pytest
  • 查看库列表
(env_test) hjw@hjw-pc:~/test$ conda list
# packages in environment at /home/hjw/anaconda3/envs/env_test:
#
# Name                    Version                   Build  Channel
_libgcc_mutex             0.1                        main    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
_openmp_mutex             5.1                       1_gnu    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
attrs                     22.1.0           py39h06a4308_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
ca-certificates           2023.01.10           h06a4308_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
exceptiongroup            1.0.4            py39h06a4308_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
iniconfig                 1.1.1              pyhd3eb1b0_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
ld_impl_linux-64          2.38                 h1181459_1    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
libffi                    3.3                  he6710b0_2    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
libgcc-ng                 11.2.0               h1234567_1    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
libgomp                   11.2.0               h1234567_1    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
libstdcxx-ng              11.2.0               h1234567_1    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
ncurses                   6.4                  h6a678d5_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
openssl                   1.1.1t               h7f8727e_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
packaging                 23.0             py39h06a4308_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
pip                       23.0.1           py39h06a4308_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
pluggy                    1.0.0            py39h06a4308_1    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
pybind11                  2.10.4           py39hdb19cb5_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
pybind11-global           2.10.4           py39hdb19cb5_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
pytest                    7.3.1            py39h06a4308_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
python                    3.9.0                hdb3f193_2    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
readline                  8.2                  h5eee18b_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
setuptools                67.8.0           py39h06a4308_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
sqlite                    3.41.2               h5eee18b_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
tk                        8.6.12               h1ccaba5_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
tomli                     2.0.1            py39h06a4308_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
tzdata                    2023c                h04d1e81_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
wheel                     0.38.4           py39h06a4308_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
xz                        5.4.2                h5eee18b_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
zlib                      1.2.13               h5eee18b_0    https://mirrors.ustc.edu.cn/anaconda/pkgs/main
(env_test) hjw@hjw-pc:~/test$ 

3.3 建立工程 test

  • 1、新建工程目录文件夹
mkdir test
  • 2、新建 build 文件夹
cd test
mkdir build
  • 3、编写 CMakeLists.txt
gedit CMakeLists.txt

CMakeLists.txt 内容如下:

cmake_minimum_required(VERSION 3.1)
project(test)

set(PYTHON_EXECUTABLE /home/hjw/anaconda3/envs/env_test/bin/python)

set(pybind11_DIR "/home/hjw/anaconda3/envs/env_test/lib/python3.9/site-packages/pybind11/share/cmake/pybind11/")
find_package(pybind11 REQUIRED)
# add_subdirectory(pybind11)

pybind11_add_module(test test.cpp)

其中,PYTHON_EXECUTABLE 和 pybind11_DIR 需要根据对应环境,进行修改适配。

  • 4、编写 test.cpp
gedit test.cpp

test.cpp 内容如下:

#include <pybind11/pybind11.h>
#include <iostream>

namespace py = pybind11;

int demo(int a, int b)
{
    int result = 0;

    result = a * b;

    std::cout << "result is " << result << std::endl;

    return result;
}

PYBIND11_MODULE(test, m)
{
    // 可选,说明这个模块的作用
    m.doc() = "pybind11 test plugin";
    //def("提供给python调用的方法名", &实际操作的函数, "函数功能说明", 默认参数). 其中函数功能说明为可选
    m.def("demo", &demo, "A function which multiplies two numbers", py::arg("a")=6, py::arg("b")=7);
}
  • 5、查看最终目录内容
(env_test) hjw@hjw-pc:~$ mkdir test
(env_test) hjw@hjw-pc:~$ cd test
(env_test) hjw@hjw-pc:~/test$ mkdir build
(env_test) hjw@hjw-pc:~/test$ gedit CMakeLists.txt
(env_test) hjw@hjw-pc:~/test$ gedit test.cpp
(env_test) hjw@hjw-pc:~/test$ ll
total 20
drwxrwxr-x  3 hjw hjw 4096 Jun  7 16:44 ./
drwxr-xr-x 45 hjw hjw 4096 Jun  7 16:44 ../
drwxrwxr-x  2 hjw hjw 4096 Jun  7 16:42 build/
-rw-rw-r--  1 hjw hjw  330 Jun  7 16:43 CMakeLists.txt
-rw-rw-r--  1 hjw hjw  449 Jun  7 16:44 test.cpp
(env_test) hjw@hjw-pc:~/test$ 

Python 和 C++ 混合编程:pybind11 使用

3.4 编译工程 test 库

cd build

cmake ..

make -j4
(env_test) hjw@hjw-pc:~/test$ cd build
(env_test) hjw@hjw-pc:~/test/build$ cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PythonInterp: /home/hjw/anaconda3/envs/env_test/bin/python (found suitable version "3.9", minimum required is "3.6") 
-- Found PythonLibs: /home/hjw/anaconda3/envs/env_test/lib/libpython3.9.so
-- Performing Test HAS_FLTO
-- Performing Test HAS_FLTO - Success
-- Found pybind11: /home/hjw/anaconda3/envs/env_test/lib/python3.9/site-packages/pybind11/include (found version "2.10.4")
-- Configuring done
-- Generating done
-- Build files have been written to: /home/hjw/test/build
(env_test) hjw@hjw-pc:~/test/build$ make -j4
Scanning dependencies of target test
[ 50%] Building CXX object CMakeFiles/test.dir/test.cpp.o
[100%] Linking CXX shared module test.cpython-39-x86_64-linux-gnu.so
[100%] Built target test
(env_test) hjw@hjw-pc:~/test/build$ 

其中 test.cpython-39-x86_64-linux-gnu.so 即为最终的 test 库 文件

3.5 Python 调用 工程 test 库

  • 编写 example.py
(env_test) hjw@hjw-pc:~/test/build$ cd ..
(env_test) hjw@hjw-pc:~/test$ gedit example.py
(env_test) hjw@hjw-pc:~/test$ 
  • example.py 内容如下:
import sys
sys.path.insert(0, '/home/hjw/test/build')
import test

if __name__ == "__main__":
    result = test.demo(3, 4)
    print(result )
  • example.py 运行结果如下:
(env_test) hjw@hjw-pc:~/test$ python3 example.py 
result is 12
12
(env_test) hjw@hjw-pc:~/test$

4. 实线小结

通过 第3节 的介绍,已经完成了一个 Python 和 C++ 混合编程的小闭环了,下面对于具体 内容,如 Numpy、Eigen 的使用也就只是细节的完善了,可以参考 第5节 参考资料详细了解。

4.1 Numpy 接口

  • 1、buffer_info 的定义,py:buffer_info的内容反映了Python缓冲区协议规范
struct buffer_info {
    void *ptr;
    ssize_t itemsize;
    std::string format;
    ssize_t ndim;
    std::vector<ssize_t> shape;
    std::vector<ssize_t> strides;
};
  • 2、两个 Numpy 数组相加示例
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>

namespace py = pybind11;

py::array_t<double> add_arrays(py::array_t<double> input1, py::array_t<double> input2) {
    py::buffer_info buf1 = input1.request(), buf2 = input2.request();

    if (buf1.ndim != 1 || buf2.ndim != 1)
        throw std::runtime_error("Number of dimensions must be one");

    if (buf1.size != buf2.size)
        throw std::runtime_error("Input shapes must match");

    /* No pointer is passed, so NumPy will allocate the buffer */
    auto result = py::array_t<double>(buf1.size);

    py::buffer_info buf3 = result.request();

    double *ptr1 = static_cast<double *>(buf1.ptr);
    double *ptr2 = static_cast<double *>(buf2.ptr);
    double *ptr3 = static_cast<double *>(buf3.ptr);

    for (size_t idx = 0; idx < buf1.shape[0]; idx++)
        ptr3[idx] = ptr1[idx] + ptr2[idx];

    return result;
}

PYBIND11_MODULE(test, m) {
    m.def("add_arrays", &add_arrays, "Add two NumPy arrays");
}

5. 参考资料

1、https://pybind11.readthedocs.io/en/stable/advanced/pycpp/numpy.html
2、https://github.com/tdegeus/pybind11_examples
3、https://blog.csdn.net/qq_28087491/article/details/128305877
4、https://www.cnblogs.com/JiangOil/p/11130670.html
5、https://zhuanlan.zhihu.com/p/383572973
6、https://zhuanlan.zhihu.com/p/192974017文章来源地址https://www.toymoban.com/news/detail-474746.html

到了这里,关于Python 和 C++ 混合编程:pybind11 使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • window下使用pybind11

    首先下载python,并且将python配置到环境变量中,如果使用window的安装程序,可以勾选自动添加到环境变量。 下载pybind11源码,https://github.com/pybind/pybind11 使用cmake-gui工具配置vs工程,并生成include头文件目录和cmake目录。 (1) 在pybind11源码目录中创建build目录和install目录。 (2) 按照

    2024年02月04日
    浏览(44)
  • visual stdio c++调用python混合编程

    关于环境创建可以参考https://blog.csdn.net/qq_36559788/article/details/123174309 这里python我用的是anaconda里的python38 ,并且没有debug库,所以我只用了release库 在vs中设置项目属性,添加 包含目录 以及 附加库目录 ,注意都是在release模式下添加的 在main.cpp中添加头文件 添加代码 编译运行

    2024年02月01日
    浏览(40)
  • C++ 混合Python编程 及 Visual Studio配置

    接手了一个C++应用程序,解析csv和生成csv文件,但是如果要把多个csv文件合并成一个Excel,分布在不同的Sheet中,又想在一次运行中完成,不想说运行完C++ 的App后,再调用一个Python脚本或程序,这需要两步操作 根据安装的Visual Studio 的版本,我安装的是64-bit的。 如何查看当前

    2024年02月13日
    浏览(43)
  • pybind11学习

    @2023.9.1 参考pybind11官方文档:https://pybind11.readthedocs.io/en/stable/index.html 参考:https://blog.csdn.net/fengbingchun/article/details/123022405 我是在wsl-ubuntu中进行测试;在python虚拟环境中安装: pip install pybind11 通过一个例子,说明基本的语法,文件example.cpp 编译命令: c++ -O3 -Wall -shared -std=

    2024年02月10日
    浏览(39)
  • C++和QML混合编程

    Qt元对象系统中注册C++类,在QML中实例化、访问。 C++中实例化并设置为QML上下文属性,在QML中直接使用。            比较: 方法1 可以使C++类在QML中作为一个数据类型,例如函数参数类型或属性类型,也可以使用其枚举类型、单例等,功能更强大。 派生自QObject类或QObject类

    2024年02月04日
    浏览(41)
  • C++和 C 混合编程处理

            原因是因为有很多功能是用 C 语言开发的,而 C++是兼容 C 的,C++应该能直接使用这些功能,那么我们把 C++调用 C 实现的功能的这个做法,称为混合编程         但是用 C 开发的功能,很可能已经用 C 编译器编程成目标文件(或打包成库了),那么目标文件中的函

    2024年02月05日
    浏览(91)
  • CUDA和C++混合编程及CMakeLists.txt

    首先认识一个问题,单从CMakeLists.txt的角度来看,无法同时使用两种编译器编译两种语言。不过直接编写Makefile是可以的,通过设置不同的任务,可以实现一个Makefile编译两个语言。但这不是这里要讨论的重点。 使用CUDA和C++进行混合编程的意思是:在cpp文件中调用CUDA函数,实

    2024年02月11日
    浏览(42)
  • QT Quick之quick与C++混合编程

            Qt quick能够生成非常绚丽界面,但有其局限性的,对于一些业务逻辑和复杂算法,比如低阶的网络编程如 QTcpSocket ,多线程,又如 XML 文档处理类库 QXmlStreamReader / QXmlStreamWriter 等等,在 QML 中要么不可用,要么用起来不方便,所以就有了quick和C++混合编程的需求。

    2024年02月12日
    浏览(40)
  • qt&python混合编程

    参考:Qt调用Python详细过程_贝勒里恩的博客-CSDN博客_qt python 1.环境搭建 1.1.python3.6 32bits 1.2.qt5.12.12 32bits 说明: (1). 务必保持版本位数一致,没有一致就得重新下载一致的版本 (2).以上软件环境的下载和安装,请自行百度,资料很多,在此重点说说混合编程遇到的错误如何解决. (3).请装

    2024年02月06日
    浏览(56)
  • Python调用Shell命令 (python,shell 混合编程)

    Python经常被称作“胶水语言”,因为它能够轻易地操作其他程序,轻易地包装使用其他语言编写的库,也当然可以用Python调用Shell命令。 用Python调用Shell命令有如下几种方式: os .system( \\\"The command you want\\\" ). os .system( \\\"lscpu\\\" ). os .system( \\\"ls -al\\\" ). 这个调用相当直接,且是同步进行的

    2024年02月16日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包