Python扩展(pybind11混编)
背景介绍
pybind11是一个基于C++11标准的模版库. 与Boost.Python类似, pybind11主要着眼于创建C++代码的Python封装, 并为其提供了一套轻量级的解决方案.安装与代码示例
①. 安装C++编译器(各平台略有不同, 支持C++11标准即可)
②. 安装cmake工具(官网下载安装即可, 用于组织C++工程)
③. 安装Python解释器(官网下载安装即可)
④. 安装pybind11库
终端运行: pip3 install pybind11
⑤. 获取pybind11库相关目录
解释器内运行:import pybind11
pybind11.get_cmake_dir() # 获取cmake目录
pybind11.get_include() # 获取include目录⑥. 待封装之C++源码
本文以一个main.cpp源文件为例, 简要给出一个函数与一个类的封装示例, 代码如下,#include <string>
#include <iostream> #include <pybind11/pybind11.h>
#include <pybind11/eigen.h> int MyFunc(int i, int j)
{
return i + j;
} class MyClass
{
public:
MyClass(const std::string& msg) : msg_(msg) {} void printMsg()
{
std::cout << this->msg_ << std::endl;
} Eigen::VectorXd add(const Eigen::VectorXd& lhs, const Eigen::VectorXd& rhs)
{
Eigen::VectorXd ret = lhs + rhs;
return ret;
} std::string msg_;
}; PYBIND11_MODULE(testlib, m) // 此处设置模块名为testlib
{
m.doc() = "This is a test library"; m.def("MyFunc", &MyFunc, "my first function",
pybind11::arg("i") = 1, pybind11::arg("j") = 2); pybind11::class_<MyClass>(m, "MyClass")
.def(pybind11::init<const std::string&>())
.def("printMsg", &MyClass::printMsg)
.def("add", &MyClass::add, pybind11::arg("lhs"), pybind11::arg("rhs"))
.def_readwrite("msg_", &MyClass::msg_);
}其中, MyFunc是待导出函数, MyClass是待导出类. 注意, 上例含eigen库(C++)与numpy库(Python)之映射, 无eigen库的小伙伴可以注释相关内容.
cmake工程示例
配合上述main.cpp源文件, CMakeLists.txt文件内容如下,cmake_minimum_required(VERSION 3.15) set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_CXX_STANDARD 11)
project(test_lib) set(test_srcs
main.cpp
) set(pybind11_DIR "/opt/homebrew/lib/python3.9/site-packages/pybind11/share/cmake/pybind11") # 此处设置pybind11之cmake目录, 即: pybind11.get_cmake_dir()
find_package(pybind11 REQUIRED)
pybind11_add_module(testlib ${test_srcs}) # 此处设置模块名为testlib
target_include_directories(testlib PUBLIC "/Users/xxhbdk/MyLibs/eigen-3.4.0") # 此处附加包含eigen库目录当前工程结构如下,

编译及效果展示
终端运行如下命令编译Python动态库:mkdir build # 创建编译目录
cd build
cmake ..
make运行完成后, 笔者build目录下生成了Python动态库文件"testlib.cpython-39-darwin.so". 随后即可在Python环境中使用之, 测试效果如下,

可以看到, 接口导出整体符合预期.注意事项
①. C++源文件中模块名需要与cmake工程文件中模块名保持一致;
②. 本文着重阐述pybind11配合cmake之通用流程, 具体API使用细节, 请大家参考官方文档等资料.参考文档
①. https://pybind11.readthedocs.io/en/stable/②. https://cmake.org/cmake/help/latest/- 补充1(C++调用Python)
①. 待调用之Python源码
本文以一个my_func.py源文件为例, 简要给出一个函数示例, 代码如下,
def MyFunc(i, j):
return i + j②. 待编译之C++源码
本文以一个main.cpp源文件为例, 简要给出一个C++调用Python函数之示例, 代码如下,#include <iostream>
#include <pybind11/embed.h> int main()
{
pybind11::scoped_interpreter guard; // 初始化python解释器 pybind11::module my_func = pybind11::module::import("my_func");
int i = 11;
int j = 22;
pybind11::object ret = my_func.attr("MyFunc")(i, j);
int n = ret.cast<int>();
std::cout << i << " + " << j << " = " << n << std::endl;
}③. cmake工程示例
配合上述main.cpp源文件, CMakeLists.txt文件内容如下,cmake_minimum_required(VERSION 3.15) set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_CXX_STANDARD 11)
project(test_cppInvokePy) set(test_srcs
main.cpp
) add_executable(main ${test_srcs})
set(pybind11_DIR "/opt/homebrew/lib/python3.9/site-packages/pybind11/share/cmake/pybind11") # 此处设置pybind11之cmake目录, 即: pybind11.get_cmake_dir()
find_package(pybind11 REQUIRED)
target_link_libraries(main PUBLIC pybind11::embed)④. 编译及效果展示
当前工程结构如下,
终端运行如下命令编译C++可执行文件,
mkdir build # 创建编译目录
cd build
cmake ..
make运行完成后, 笔者build目录下生成了可执行文件"main". 随后将Python文件my_func.py拷贝至此build目录下.终端运行可执行文件main, 测试效果如下,

可以看到, 执行结果符合预期, Python模块调用成功.
- 补充1 - 参考文档
①. https://www.yuque.com/u461675/pcadi1/hf4fha#e82c4d4d - 补充2(Global Interpreter Lock)
当执行流从Python侧进入C++侧时, GIL总是持有的. 因此, 如果C++侧代码长时间运行, 且不释放GIL, 则Python侧多线程可能无法达到预期的运行效果(如: UI运行阻塞等).
因此, 通过Python调用C++时, 若C++侧代码执行时间较长且具备Python侧多线程需求, 建议在C++代码入口处释放GIL.
释放GIL之方法①(功能代码执行处): pybind11::gil_scoped_release release;
释放GIL之方法②(模块接口定义处): pybind11::call_guard<pybind11::gil_scoped_release>(); - 补充2 - 注意事项
①. C++侧多线程不受GIL影响. - 补充2 - 参考文档
①. https://pybind11.readthedocs.io/en/stable/advanced/misc.html#global-interpreter-lock-gil
Python扩展(pybind11混编)的更多相关文章
- python 与 matlab 混编
用于 Python 的 MATLAB 引擎 API 快速入门 安装用于 Python 的 MATLAB 引擎 API Matlab的官方文档中介绍了 Matlab 与其余编程语言之间的引擎接口,其中包 ...
- python和C语言混编的几种方式
Python这些年风头一直很盛,占据了很多领域的位置,Web.大数据.人工智能.运维均有它的身影,甚至图形界面做的也很顺,乃至full-stack这个词语刚出来的时候,似乎就是为了描述它. Pytho ...
- Python+C混编
Python最慢!C最快!Python+C混编?结果可想而知! 樱桃种子 百家号04-1712:11 共享库 使用C语言编译产生共享库,然后python使用ctype库里的cdll来打开共享库. 举例 ...
- Python和C|C++的混编(二):利用Cython进行混编
还能够使用Cython来实现混编 1 下载Cython.用python setup.py install进行安装 2 一个实例 ① 创建helloworld文件夹 创建helloworld.pyx,内 ...
- python扩展实现方法--python与c混和编程 转自:http://www.cnblogs.com/btchenguang/archive/2012/09/04/2670849.html
前言 需要扩展Python语言的理由: 创建Python扩展的步骤 1. 创建应用程序代码 2. 利用样板来包装代码 a. 包含python的头文件 b. 为每个模块的每一个函数增加一个型如PyObj ...
- python扩展实现方法--python与c混和编程
前言 需要扩展Python语言的理由: 创建Python扩展的步骤 1. 创建应用程序代码 2. 利用样板来包装代码 a. 包含python的头文件 b. 为每个模块的每一个函数增加一个型如PyObj ...
- swift objective-及c语言 混编
在xocde6出来我们大部分代码都是用objective-c写的(部分C/C++),现在出生来了一个新的语言叫swift,那么如何既能使用我们之前的代码,还可以使用新语言呢, 本文就此做一下说明. 关 ...
- [ios][swift]swift混编
http://blog.csdn.net/iflychenyang/article/details/8876542(如何在Objective-C的头文件引用C++的头文件) 1.将.m文件扩展名改为. ...
- Xcode中C、C++、Object-C3种语言的混编
转自: http://hi.baidu.com/onejw/item/f34390c997cdc226a1b50ae http://www.cocoachina.com/ask/questions/s ...
- Swift & OC 混编 浅析
转载自:http://www.infoq.com/cn/articles/wangyi-cartoon-swift-mixed-practice?utm_campaign=rightbar_v2&am ...
随机推荐
- 精美的web前端源码的特效
1.JS自定义烟花特效 这是一款基于JS和Canvas的自定义烟花特效,初始化界面的时候特效是不带声效的绽放,当你点击顶部中间的播放,即可以看到美丽的烟火也可以听到烟花绽放的声音,让你脑海浮现过年团圆 ...
- C#NPOI操作Excel,实现Excel数据导入导出(支持多个sheet)
首先在项目中引用NPOI,通过管理NuGet程序包,搜索NPOI,选择版本2.3.0(支持.NET Framework 4.0)根据自己项目选择适当版本. 1.NpoiExcelHelper.cs ...
- 织梦DedeCMS 0day RCE
前言 原文链接:https://mp.weixin.qq.com/s/bwBc4I9GeY6M_WlEDx83TA 复现记录时间: 下载当前最新版本DedeCMS V5.7.105进行漏洞复现以及漏洞 ...
- 题解 [SCOI2008]斜堆
好题.一道很有趣的性质提. 因为自己搞错结论然后改了 1h(悲 闲话少说,切入正题-- 这是不断插入的,所以根据套路我们会考虑最后一个插入的节点的性质.显然满足: 它是从根不停往左走的路上. 它没有右 ...
- php pdo如何查询记录条数
转载php中文网:https://www.php.cn/php-ask-457710.html php pdo查询记录条数的方法:1.使用fetchAll函数查询,其语法如"$rows=$q ...
- SpringBoot多数据源以及事务处理
背景 在高并发的项目中,单数据库已无法承载大数据量的访问,因此需要使用多个数据库进行对数据的读写分离,此外就是在微服化的今天,我们在项目中可能采用各种不同存储,因此也需要连接不同的数据库,居于这样的背 ...
- linux系统安装MySQL服务,详细图文教程
注:linux系统在安装操作系统时,如果选择了开发工具和兼容库后,一般默认都会安装MySQL服务的部分程序包.如果我们要自定义的安装全新的MySQL服务,就必须先把这些已经安装的程序包都卸载掉.否则, ...
- 记录篇-浪潮服务器raid卡
在说raid卡之前,首先,我们要明确,不同的raid卡型号,会有不同的配置方式,但是总体来说是大同小异的 这里举例浪潮机架式服务器经常用到的raid卡型号: PM8204 (其实像3108 ...
- JavaScript查找两个节点的最近的一个共同父节点,可以包括节点自身
- mybatis处理多对一的映射关系
创建数据库t_emp和t_dept 创建对应实体类 package org.example.entity; public class Emp { private Integer empId; priv ...