C++和Python混合编程——C++调用Python入门

大纲

  • 代码结构
    • 初始化 Python 解释器
    • 获取 GIL
      • 为什么需要 GIL?
      • GIL 的影响
    • 导入 Python 模块并执行代码
    • 释放 GIL
    • 终止 Python 解释器
  • 完整代码
  • 编译
  • 执行结果
  • 项目地址

在《C++和Python混合编程——Python调用C++入门》一文中,我们熟悉了Python调用C++编译的动态库的方法。但是作为混合编程,也必然要有反向的过程——C++调用Python代码。本文我们将介绍如何使用boost.python库实现该功能。

代码结构

初始化 Python 解释器

Py_Initialize();

在程序开始时初始化 Python 解释器,确保可以调用其他 Python C API 函数。它会设置 Python 解释器的内部状态,加载内置模块,并准备好执行 Python 代码。

获取 GIL

PyGILState_STATE gstate;
gstate = PyGILState_Ensure();

GIL(Global Interpreter Lock,全局解释器锁)是 Python 解释器中的一个机制,用于在多线程环境中保护访问 Python 对象的共享资源。GIL 确保在任何时刻只有一个线程可以执行 Python 字节码,从而避免了多线程访问共享资源时的竞争条件。

为什么需要 GIL?

Python 的内存管理不是线程安全的。为了避免多线程同时访问和修改共享数据导致的不一致性和崩溃,GIL 被引入来确保只有一个线程可以执行 Python 代码。

GIL 的影响

  • 多线程限制:由于 GIL 的存在,在 CPU 密集型任务中,多线程的性能提升有限,因为同一时刻只有一个线程在执行 Python 代码。
  • I/O 密集型任务:对于 I/O 密集型任务(如网络请求、文件读写),多线程仍然可以带来性能提升,因为 I/O 操作会释放 GIL,使其他线程有机会执行。

导入 Python 模块并执行代码

boost::python::object main_module = boost::python::import("__main__");
boost::python::object main_namespace = main_module.attr("__dict__");std::string python_code = R"(
def add(a, b):return a + bresult = add(3, 4)
print(f"Result of add(3, 4) is {result}")
)";
boost::python::exec(python_code.c_str(), main_namespace);int result = boost::python::extract<int>(main_namespace["result"]);
std::cout << "Result from Python: " << result << std::endl;

释放 GIL

PyGILState_Release(gstate);

在完成 Python 代码执行后释放 GIL。

终止 Python 解释器

Py_Finalize();

在程序结束时调用 Py_Finalize() 以清理 Python 解释器的状态,释放内存和其他资源。如果不调用 Py_Finalize(),可能会导致内存泄漏和其他资源未释放的问题。

完整代码

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <chrono>
#include <boost/python.hpp>class PythonInterpreter {
public:PythonInterpreter() {Py_Initialize(); // Initialize Python interpretergstate = PyGILState_Ensure(); // Acquire GILstd::cout << "Python interpreter initialized." << std::endl;}~PythonInterpreter() {PyGILState_Release(gstate); // Release GILPy_Finalize(); // Cleanup sectionstd::cout << "Python interpreter finalized." << std::endl;}private:PyGILState_STATE gstate;
};void call_python_function() {using namespace boost::python;try {// 创建 PythonInterpreter 对象,自动初始化 Python 解释器PythonInterpreter pyInterp;// 导入 Python 模块object main_module = import("__main__");object main_namespace = main_module.attr("__dict__");// 定义并执行 Python 代码std::string python_code = R"(
def add(a, b):return a + bresult = add(3, 4)
print(f"Result of add(3, 4) is {result}")
)";exec(python_code.c_str(), main_namespace);// 获取并打印结果int result = extract<int>(main_namespace["result"]);std::cout << "Result from Python: " << result << std::endl;} catch (error_already_set) {PyErr_Print();}
}int main() {call_python_function();return 0;
}

编译

以下是CMakeLists.txt的内容。

cmake_minimum_required(VERSION 3.12)# 项目信息
# 最后一级目录为项目名称
get_filename_component(ProjectName ${CMAKE_CURRENT_SOURCE_DIR} NAME)
project(${ProjectName})# 设置 CMP0148 政策
if(POLICY CMP0148)cmake_policy(SET CMP0148 NEW)
endif()# 查找 Python 解释器和库
find_package(Python3 REQUIRED COMPONENTS Interpreter Development)# 查找 Boost 库。使用 Python3_VERSION_MAJOR 和 Python3_VERSION_MINOR 变量来查找对应版本的 Boost.Python 库
find_package(Boost REQUIRED COMPONENTS python${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR})# 添加可执行文件
add_executable(${ProjectName} main.cpp)# 包含 Python 头文件
include_directories(${Python3_INCLUDE_DIRS})# 链接 Boost.Python 和 Python 库
target_link_libraries(${ProjectName} ${Boost_LIBRARIES} ${Python3_LIBRARIES})

执行结果

在这里插入图片描述

项目地址

https://github.com/f304646673/cpulsplus/tree/master/boost_python/c_call_p

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/416556.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

集成电路学习:什么是PWM脉冲宽度调制

一、PWM&#xff1a;脉冲宽度调制 PWM&#xff0c;全称为脉冲宽度调制&#xff08;Pulse Width Modulation&#xff09;&#xff0c;是一种通过调整脉冲信号的宽度来控制电路输出的技术。在PWM中&#xff0c;信号的输出由一系列等幅值的脉冲组成&#xff0c;这些脉冲的宽度根据…

上海亚商投顾:深成指、创业板指均涨超1%,华为产业链反复活跃

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 大小指数昨日走势分化&#xff0c;沪指全天震荡调整&#xff0c;2800点失而复得&#xff0c;深成指、创业板指…

golang

一.go执行流程 4&#xff09;go run运行时间明显要比第一种时间长一点 【3】编译后的文件可以替换名称 二.语法注意 1.源文件以“go”为扩展名 2.程序的执行入口是main&#xff08;&#xff09;函数。 3.严格区分大小写 4.方法由一条条语句构成&#xff0c;每个语句后不需…

Docker安全

Docker安全 和本地共享资源&#xff0c;会有安全性问题 1. Cgroups 对资源的上限进行控制 /sys/devices/system1.1 cpu资源限制 # 进行cpu控制&#xff0c;只使用20%的资源 docker run -it --rm --cpu-period 100000 --cpu-quota 20000 ubuntu# 测试cpu使用 dd if/dev/zer…

【题目全解】蓝桥杯24省赛C++中高级组题干题解

本帖只提供六道编程题的解题思路&#xff0c;部分题目并不提供实际的代码&#xff08;因为我赛时忘记把代码截图下来了&#xff09;。 T1 - 看书 题干描述&#xff1a; 一本书共 n n n 页&#xff0c;小明计划第一天看 x x x 页&#xff0c;此后每一天都要比前一天多看 y y…

【面试八股总结】MySQL 锁:全局锁、表级锁、行级锁

1. 全局锁 顾名思义&#xff0c;全局锁就是对整个数据库实例加锁。 MySQL 提供了⼀个加全局读锁的方法&#xff1a; flush tables with read lock 释放全局锁&#xff0c;执行命令&#xff1a; unlock tables 需要让整个库处于只读状态的时候&#xff0c;可以使用全局锁命…

鸿蒙(API 12 Beta6版)图形【NativeImage开发指导 (C/C++)】方舟2D图形服务

场景介绍 NativeImage是提供Surface关联OpenGL外部纹理的模块&#xff0c;表示图形队列的消费者端。开发者可以通过NativeImage接口接收和使用Buffer&#xff0c;并将Buffer关联输出到OpenGL外部纹理。 针对NativeImage&#xff0c;常见的开发场景如下&#xff1a; 通过Nati…

linux系统中USB模块鼠标驱动实现

各位开发者大家好,今天主要给大家分享一下,Linux系统中使用libusb的方法以及鼠标驱动实现。 第一:libusb概述 参考网址:* libusb GIT仓库:https://github.com/libusb/libusb.git * libusb 官网:https://libusb.info/ * libusb API接口:https://libusb.sourceforge.io/…

mysql 使用 general 开启SQL跟踪功能

查看当前状态 mysql> SHOW VARIABLES LIKE %general%; 启用 临时启用 SET GLOBAL general_logon; SET GLOBAL general_log_file/tmp/general.log; 永久启用 通过修改配置文件来启用,需要重启mysql服务 [mysqld] general_logON general_log_file/tmp/general.log 再次查看状态…

【Redis】Redis 持久化机制详解:RDB、AOF 和混合持久化的工作原理及优劣分析

目录 持久化RDB触发机制流程说明RDB ⽂件的处理RDB 的优缺点 AOF使⽤ AOF命令写⼊⽂件同步重写机制启动时数据恢复 混合持久化小结 持久化 回顾 MySQL 的事务的特性&#xff1a; 原子性一致性持久性&#xff08;持久化&#xff09;隔离性 持久化&#xff1a;把数据存储在硬盘上…

CAN总线之一篇文章讲清楚Motorala和inter格式

前言&#xff1a; 之前的工作中&#xff0c;其实对Motorala和inter格式并不是了解的十分透彻。最近由于工作需要&#xff0c;研究了一下这两种格式&#xff0c;发现里面的门道其实挺复杂的。 特此作了一些总结&#xff1a;和大家一起分享。 我查了不少文档&#xff0c;描述其…

MongoDB 向 PostgreSQL 宣战

上周 MongoDB 发布了一份亮眼的季度财报&#xff0c;盘后股价涨幅超过 18%。 值得一提的是&#xff0c;MongoDB 的 CEO Dev Ittycheria 特别提到 MongoDB 正在借助自己的数据库服务 Atlas 从 PostgreSQL 那里挖角。原话是举了一个博彩网站的例子&#xff1a; “Initially, th…

【C++ 第十八章】C++11 新增语法(4)

前情回顾&#xff1a; 【C11 新增语法&#xff08;1&#xff09;&#xff1a;1~6 点】 C11出现与历史、花括号统一初始化、initializer_list初始化列表、 auto、decltype、nullptr、STL的一些新变化 【C11 新增语法&#xff08;2&#xff09;&#xff1a;7~8 点】 右值引用和…

uniapp插槽用法

目录 什么是插槽? 基本概念 默认插槽 命名插槽 作用域插槽 场景一:子插槽向父组件传递一个字符串 场景二:子插槽向父组件传递对象 什么是插槽? 在 UniApp 中&#xff0c;插槽&#xff08;Slot&#xff09;是一种允许父组件向子组件特定位置插入HTML内容的方式。这种方式使得组…

快速便捷地解决 reCAPTCHA 的方法

reCAPTCHA 是一种流行的挑战-响应系统&#xff0c;旨在通过提供人类易于解决但机器难以解决的难题来保护网站免受机器人和自动化滥用。无论您是处理网络抓取项目中的 reCAPTCHA 的开发人员&#xff0c;还是在各种网站上浏览的用户&#xff0c;了解如何有效地处理 reCAPTCHA 都可…

每日OJ_牛客_五子棋(判断是否有赢)

目录 牛客_五子棋&#xff08;判断是否有赢&#xff09; 解析代码 牛客_五子棋&#xff08;判断是否有赢&#xff09; 五子棋__牛客网 题目&#xff1a; 用例输入&#xff1a; .................... .................... .................... .................... ....…

基础闯关4

环境配置 我们来配置LlamaIndex实验环境&#xff0c;首先创建Python环境并安装必要的库&#xff1a; conda create -n llamaindex python3.10 conda activate llamaindex conda install pytorch2.0.1 torchvision0.15.2 torchaudio2.0.2 pytorch-cuda11.7 -c pytorch -c nvid…

VBA数据库解决方案第十四讲:如何在数据库中动态删除和建立数据表

《VBA数据库解决方案》教程&#xff08;版权10090845&#xff09;是我推出的第二套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;是学完字典后的另一个专题讲解。数据库是数据处理的利器&#xff0c;教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…

Pixelmator Pro for Mac 专业图像处理软件【媲美PS的修图软件】

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功 三、运行测试安装完成&#xff01;&#xff01;&#xff01; 效果 一、下载软件 下载软件…

MySQL 使用C语言链接

mysql的基础&#xff0c;我们之前已经学过&#xff0c;后面我们只关心使用 要使用C语言连接mysql&#xff0c;需要使用mysql官网提供的库&#xff0c;大家可以去官网下载 我们使用C接口库来进行连接 要正确使用&#xff0c;我们需要做一些准备工作&#xff1a; 保证mysql服务有…