当前位置: 首页 > article >正文

C/C++调用Python程序代码实现混合编程笔记教程

0、引言

        Python‌在基础开发、数据科学、人工智能、Web框架开发等领域具有广泛的支持工具和开发教程,极大的缩短了产品原型开发周期、降低了开发难度。

        有许多的功能,通过C/C++实现,非常的复杂并且不方便,但是Python可能就是几行代码就搞定了。

        为了避免处处重复造轮子,又希望在原先的C/C++通用轻松简单的实现一些功能,因此探索在C/C++中如何嵌入调用Python的API及应用程序非常有必要。

1、开发环境搭建

①、Python

        本文以当前最新的Python 3.13.3版本为例进行讲解,本教程的Python下载地址如下:

Download Python | Python.orghttps://www.python.org/downloads/

        由于Python的版本也一直在更新,如果找查阅到本教程时,最新版本已不是Python3.13.3,可以滑动找到Python的历史版本进行安装。

        并在安装完成后,建议通过终端命令行查询一下具体的版本信息:python --version

②、MinGW

        简单来说,MinGW是一个编译器,提供了gcc和g++编译工具,可以对C/C++程序代码编译调试。

        在之前的很多博客笔记文章中已经对MinGW进行了非常多的讲解了,如果对MinGW编译器有疑惑的,可以通过博主的如下笔记链接,搭建安装MinGW开发环境。

MinGW编译器任意版本使用配置经验教程-CSDN博客https://blog.csdn.net/weixin_49337111/article/details/140274770?spm=1001.2014.3001.5502

③、CMake

        CMake(Cross-platform Make)是一款开源的跨平台构建系统生成工具,广泛应用于C、C++、Fortran等编程语言的项目构建中。

        在VScode,可以直接安装VScode插件构建工具,即可实现在VScode中使用CMake。

        提醒:在一些环境中,可能无法正常使用CMake插件,需要下载最新的CMake程序软件才能辅助使用。

2、工程代码配置

        在上面的开发环境搭建好之后,当在程序代码中加入Python相关的头文件时,大概率会出现如下情况,找不到相关头文件,并且编译会直接报错。

        上面这个情况也就是说明,并没有和Python建立联系,需要我们自己将Python的路径加入到工程代码的配置中。

        通过python --path命令,即可找到python的实际安装路径

        python实际的文件所在路径,include包含了C/C++中需要使用的xxx.h头文件。

        在libs中提供的是_tkinter.lib、python3.lib、python313.lib

        如果在MinGW中不能直接使用xxx.lib库文件,要进行文件格式转换,对于没有接触过了开发者,可能处理起来较为麻烦,如有需要,可以访问博主在下面这篇文章中提到的方法。

Windows中xxx.dll动态链接库文件转xxx.a静态库文件-CSDN博客https://blog.csdn.net/weixin_49337111/article/details/147171368?sharetype=blogdetail&sharerId=147171368&sharerefer=PC&sharesource=weixin_49337111&spm=1011.2480.3001.8118

        如果觉得不方便,可以采取直接在Visual Studio程序中包含xxx.lib文件,同样可以实现C/C++中嵌入Python程序进行开发。

        在完成上面的操作后,即可创建C/C++工程了,然后配置CMakeLists.txt文件。博主在一系列试错了,最终成功运行的文件如下:

        CMakeLists.txt

cmake_minimum_required(VERSION 3.10.0)
project(convert VERSION 0.1.0 LANGUAGES C CXX)# 设置Python路径
set(PYTHON_INCLUDE_DIR "C:/Users/Administrator/AppData/Local/Programs/Python/Python313/include")
set(PYTHON_LIBRARY "C:/Users/Administrator/AppData/Local/Programs/Python/Python313/libs/python313.lib")# 添加可执行文件
add_executable(convert main.cpp)# 包含Python头文件目录
target_include_directories(convert PRIVATE ${PYTHON_INCLUDE_DIR})# 链接Python库
target_link_libraries(convert PRIVATE ${PYTHON_LIBRARY})# 在Windows上需要定义PYTHON_LIBRARY宏
if(WIN32)target_compile_definitions(convert PRIVATE PYTHON_LIBRARY)
endif()

        提醒:如果在Windows环境中,发现存在MSVC会和当前MinGW编译器混用,建议直接换更新版本的MinGW,经过反复试错,最终得出来的正确解决办法,惨痛的教训!!!

        在编译正常运行后,说明环境搭建完毕,工程配置正常,可以开始C/C++中正常调用Python进行开发了。

3、C/C++中调用Python

        对于在C/C++中如何使用Python的API接口,Python官方已经出来非常详细的教程,有需要的博客朋友可以访问如下链接对该教程参考学习。

        Python的C/C++外部扩展官方教程:

1. Embedding Python in Another Application — Python 3.13.3 documentationhttps://docs.python.org/3.13/extending/embedding.html

①、常用API接口

(1)初始化 Python 解释器

//用于初始化 Python 解释器,它会设置 Python 运行所需的环境,加载内置模块等。
void Py_Initialize(void);

(2)终止 Python 解释器

//程序结束时,要调用此函数来终止解释器,释放相关资源。
void Py_Finalize(void);

(3)命令行参数处理

//将 C/C++ 程序的命令行参数传递给 Python 解释器。
void PySys_SetArgv(int argc, char **argv);

(4)执行Python简单语句

//使用此函数接口可以在 C/C++ 代码中执行简单的 Python 语句。
int PyRun_SimpleString(const char *command);

(5)执行 Python 文件

//使用此函数接口,可以在C/C++代码中间接执行 Python 文件
int PyRun_SimpleFile(FILE *fp, const char *filename);

(6)导入 Python 模块

//此函数接口,可以实现导入 Python 模块。
PyObject* PyImport_ImportModule(const char *name);

(7)调用 Python 函数

//用于在 C/C++ 中调用 Python 的可调用对象(函数、方法、类等)。
PyObject* PyObject_CallObject(PyObject *callable, PyObject *args);

②、程序实例

(1)Python语句执行

//    C/C++测试 HTTP 请求和 HTML 解析功能效果如下:
#include <Python.h>
#include <iostream>
#include <string>
#include <stdexcept>class PythonHttpParser {
public:PythonHttpParser() {Py_Initialize();// 确保 requests 和 bs4 可用PyRun_SimpleString("import sys\n""try:\n""    import requests\n""    from bs4 import BeautifulSoup\n""except ImportError as e:\n""    print(f'Error: {e}')\n""    sys.exit(1)\n");}~PythonHttpParser() {Py_Finalize();}std::string fetch_title(const std::string& url) {PyObject *pFunc, *pArgs, *pResult;// 获取 main 模块PyObject* main_module = PyImport_AddModule("__main__");PyObject* global_dict = PyModule_GetDict(main_module);// 准备 Python 代码const char* code = "def get_page_title(url):\n""    try:\n""        response = requests.get(url)\n""        soup = BeautifulSoup(response.text, 'html.parser')\n""        return soup.title.string if soup.title else 'No title found'\n""    except Exception as e:\n""        return f'Error: {str(e)}'\n";PyRun_SimpleString(code);// 获取函数pFunc = PyDict_GetItemString(global_dict, "get_page_title");if (!pFunc || !PyCallable_Check(pFunc)) {throw std::runtime_error("Failed to get Python function");}// 准备参数pArgs = PyTuple_New(1);PyTuple_SetItem(pArgs, 0, PyUnicode_FromString(url.c_str()));// 调用函数pResult = PyObject_CallObject(pFunc, pArgs);if (!pResult) {PyErr_Print();throw std::runtime_error("Python function call failed");}// 获取结果std::string result = PyUnicode_AsUTF8(pResult);// 清理Py_DECREF(pArgs);Py_DECREF(pResult);return result;}
};int main() {try {PythonHttpParser parser;std::string title = parser.fetch_title("https://en.wikipedia.org/wiki/Main_Page");std::cout << "Page title: " << title << std::endl;} catch (const std::exception& e) {std::cerr << "Error: " << e.what() << std::endl;return 1;}return 0;
}

        C/C++测试 HTTP 请求和 HTML 解析功能效果如下:

(2)Python代码文件调用

#include <Python.h>
#include <cstdio>
#include <cstdlib>int main(int argc, char* argv[]) {// 初始化 Python 解释器Py_Initialize();// 创建一个 wchar_t** 数组来存储转换后的命令行参数wchar_t** wargv = (wchar_t**)malloc(argc * sizeof(wchar_t*));if (!wargv) {perror("Failed to allocate memory");Py_Finalize();return 1;}for (int i = 0; i < argc; ++i) {wargv[i] = Py_DecodeLocale(argv[i], nullptr);if (!wargv[i]) {perror("Failed to decode argument");for (int j = 0; j < i; ++j) {PyMem_RawFree(wargv[j]);}free(wargv);Py_Finalize();return 1;}}// 将转换后的参数传递给 PythonPySys_SetArgv(argc, wargv);// 指定要运行的 Python 脚本文件名const char* script_file = "../script.py";// 打开 Python 脚本文件FILE* fp = fopen(script_file, "r");if (!fp) {perror("Failed to open file");for (int i = 0; i < argc; ++i) {PyMem_RawFree(wargv[i]);}free(wargv);Py_Finalize();return 1;}// 运行 Python 脚本int result = PyRun_SimpleFile(fp, script_file);fclose(fp);// 释放分配的内存for (int i = 0; i < argc; ++i) {PyMem_RawFree(wargv[i]);}free(wargv);// 终止 Python 解释器Py_Finalize();return result;
}

        script.py

import sys# 打印接收到的命令行参数
print(f"Received arguments: {sys.argv}")# 检查是否包含 --help 参数
if "--help" in sys.argv:print("Usage: script.py [--input <file>] [--verbose]")

        程序执行结果:

相关文章:

C/C++调用Python程序代码实现混合编程笔记教程

0、引言 Python‌在基础开发、数据科学、人工智能、Web框架开发等领域具有广泛的支持工具和开发教程&#xff0c;极大的缩短了产品原型开发周期、降低了开发难度。 有许多的功能&#xff0c;通过C/C实现&#xff0c;非常的复杂并且不方便&#xff0c;但是Python可能就是几行代码…...

LeetCode hot 100—子集

题目 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[],[1],[2…...

Linux网络编程——数据链路层详解,以太网、MAC地址、MTU、ARP、DNS、NAT、代理服务器......

目录 一、前言 二、以太网 二、以太网帧格式 三、 MAC地址 四、MTU 1、数据链路层的数据分片 2、MTU对UDP协议的影响 3、MTU对TCP协议的影响 五、ARP协议 1、什么是ARP 2、ARP的作用 3、ARP协议的工作流程 4、ARP缓存表 5、ARP请求报文 6、中间人 六、DNS&…...

MySQL 5.7.30 Linux 二进制安装包详解及安装指南

MySQL 5.7.30 Linux 安装包详解 mysql-5.7.30-linux-glibc2.12-x86_64.tar 是 MySQL 服务器 5.7.30 版本的 Linux 二进制发行包。 mysql-5.7.30-linux-glibc2.12-x86_64.tar 安装包下载 链接&#xff1a;https://pan.quark.cn/s/2943cd209ca5 包信息 版本: MySQL 5.7.30 平…...

基于springboot+vue的秦皇岛旅游景点管理系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;Maven3.3.9 系统展示 用户登录 旅游路…...

Linux网络编程——TCP通信的四次挥手

一、前言 上篇文章讲到了TCP通信建立连接的“三次握手”的一些细节&#xff0c;本文再对TCP通信断开连接的“四次挥手”的过程做一些分析了解。 二、TCP断开连接的“四次挥手” 我们知道TCP在建立连接的时需要“三次握手”&#xff0c;三次握手完后就可以进行通信了。而在通…...

634SJBH苏州旅游网站

1 绪论 1.1 课题的提出、研究现状及研究意义 旅游业具有“无烟产业”和“永远的朝阳产业”的美称&#xff0c;它已经和石油业、汽车业并列为世界三大产业&#xff1b;根据WTTC的统计&#xff0c;它每年产出4.7万亿美金的收入&#xff0c;直接或间接地为2亿700万人提供了就业机…...

计算机视觉算法实现——SAM实例分割:原理、实现与应用全景

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​ ​​​​​​​​​ ​​ 1. 实例分割领域概述 实例分割(Instance Segmentation)是计算机视觉领域最具挑战性的任务之一&#xff0c…...

基于SpringBoot的宠物健康咨询系统(源码+数据库+万字文档)

502基于SpringBoot的宠物健康咨询系统&#xff0c;系统包含三种角色&#xff1a;管理员、用户&#xff0c;顾问主要功能如下。 【用户功能】 1. 首页&#xff1a;查看系统主要信息和最新动态。 2. 公告&#xff1a;浏览系统发布的公告信息。 3. 顾问&#xff1a;浏览可提供咨询…...

vue2 el-element中el-select选中值,数据已经改变但选择框中不显示值,需要其他输入框输入值才显示这个选择框才会显示刚才选中的值

项目场景&#xff1a; <el-table-column label"税率" prop"TaxRate" width"180" align"center" show-overflow-tooltip><template slot-scope"{row, $index}"><el-form-item :prop"InquiryItemList. …...

pgsql:关联查询union(并集)、except(差集)、intersect(交集)

pgsql:关联查询union(并集)、except(差集)、intersect(交集)_pgsql except-CSDN博客...

CCF CSP 第35次(2024.09)(2_字符串变换_C++)(哈希表+getline)

CCF CSP 第35次&#xff08;2024.09&#xff09;&#xff08;2_字符串变换_C&#xff09; 解题思路&#xff1a;思路一&#xff08;哈希表getline&#xff09;&#xff1a; 代码实现代码实现&#xff08;思路一&#xff08;哈希表getline&#xff09;&#xff09;&#xff1a; …...

PostgreSQL 的 COPY 命令

PostgreSQL 的 COPY 命令 PostgreSQL 的 COPY 命令是高效数据导入导出的核心工具&#xff0c;性能远超常规 INSERT 语句。以下是 COPY 命令的深度解析&#xff1a; 一 COPY 命令基础 1.1 基本语法对比 命令类型语法示例执行位置文件访问权限服务器端COPYCOPY table FROM /p…...

Docker--利用dockerfile搭建mysql主从集群和redis集群

Docker镜像制作的命令 链接 Docker 镜像制作的注意事项 链接 搭建mysql主从集群 mysql主从同步的原理 MySQL主从同步&#xff08;Replication&#xff09;是一种实现数据冗余和高可用性的技术&#xff0c;通过将主数据库&#xff08;Master&#xff09;的变更操作同步到一个…...

Context的全面解析:在不同技术应用中的通用作用与差异

Context的全面解析&#xff1a;在不同技术应用中的通用作用与差异 引言&#xff1a; 在软件开发中&#xff0c;“Context”这个概念被广泛使用。它不仅限于某个特定的技术或编程语言&#xff0c;实际上&#xff0c;Context 作为一种抽象的设计模式&#xff0c;贯穿在许多开发领…...

蓝桥杯嵌入式考前模块总结

一.RTC 使用RTC直接再cubeMX中配置启动时钟和日历 如第六届省赛 想要让RTC的秒每隔一秒递增1需要在时钟树界面观察RTC的主频 由于RTC时钟主频为32KHZ将异步预分频计数器的值设为31&#xff0c;将同步预分频计数器的值设为999这样就可以将RTC的时钟信号分频为1HZ达到1秒自增的…...

关于举办“2025年第五届全国大学生技术创新创业大赛“的通知

赛事含金量 大赛获奖即可有机会为你的大学里的“创新创业”加分&#xff01;这是每个大学要求必须修满的学分&#xff01; 中国“互联网&#xff0b;”大学生创新创业大赛磨刀赛&#xff01;“挑战杯”中国大学生创业计划大赛必参赛&#xff01; 国赛获奖&#xff0c;“互联…...

spark安装过程问题

1. Spark-local模式 - 适用于单节点环境&#xff0c;无需启动Hadoop集群。 - 实验步骤包括解压文件、启动Local环境、运行命令行工具、提交测试应用等。 - 通过bin/spark-shell启动本地环境&#xff0c;通过sc.textFile等命令测试功能。 - 提交应用时使用--master loca…...

Ingress蓝绿发布

Ingress蓝绿发布 Ingress常用注解说明yaml资源清单绿色版本yml资源清单蓝色版本yaml资源清单 主Ingress金丝雀Ingress基于客户端请求头的流量切分结果验证 基于客户端来源IP的流量切分结果验证 基于服务权重的流量切分结果验证 基于IP来源区域来切分IP---方案未验证基于User-Ag…...

基于AOP+Log4Net+AutoFac日志框架

1.项目概述 这是一个基于 C# 的 WPF 项目 WpfApp12log4net&#xff0c;它综合运用了依赖注入、日志记录和接口实现等多种技术&#xff0c;同时使用了 Autofac、Castle.Core 和 log4net 等第三方库。 2.配置log4net 新建一个Log4Net.config&#xff0c;配置需要记录的日志信息…...

python推箱子游戏

,--^----------,--------,-----,-------^--,-------- 作者 yty---------------------------^----------_,-------, _________________________XXXXXX XXXXXX XXXXXX ______(XXXXXXXXXXXX(________(------ 0 [[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], [1,0,0,0,0,0,0,0,0,0,0,0,…...

华为hcie证书的有效期怎么判断?

在ICT行业&#xff0c;华为HCIE证书堪称含金量极高的“敲门砖”&#xff0c;拥有它往往意味着在职场上更上一层楼。然而&#xff0c;很多人在辛苦考取HCIE证书后&#xff0c;却对其有效期相关事宜一知半解。今天&#xff0c;咱们就来好好唠唠华为HCIE证书的有效期怎么判断这个关…...

关于 Spring Boot 部署到 Docker 容器的详细说明,涵盖核心概念、配置步骤及关键命令,并附上表格总结

以下是关于 Spring Boot 部署到 Docker 容器的详细说明&#xff0c;涵盖核心概念、配置步骤及关键命令&#xff0c;并附上表格总结&#xff1a; 1. Docker 核心概念 概念描述关系镜像&#xff08;Image&#xff09;预定义的只读模板&#xff0c;包含运行环境和配置&#xff08…...

PowerBI 条形图显示数值和百分比

数据表: 三个度量值 销售额 SUM(销量表[销售量])//注意, 因为Y轴显示的产品&#xff0c;会被筛选&#xff0c;所以用ALLSELECTED来获取当前筛选条件下&#xff0c;Y轴显示的产品 百分比 FORMAT(DIVIDE([销售额],CALCULATE([销售额],ALLSELECTED(销量表[产品编码]))),"0…...

基于YOLOv8的火车轨道检测识别系统:技术实现与应用前景

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​ ​​​​​​​​​ ​​ 1. 引言&#xff1a;火车轨道检测领域概述 铁路运输作为国民经济的大动脉&#xff0c;其安全运行至关重要…...

css使用mix-blend-mode的值difference实现内容和父节点反色

1. 使用场景 往往开发过程中&#xff0c;经常遇到产品说你这个背景图和文字颜色太接近了&#xff0c;能不能适配下背景图&#xff0c;让用户能够看清具体内容是啥。 这么说吧&#xff0c;这种需求场景非常合理&#xff0c;因为你做开发就是要给用户一个交代&#xff0c;给他们…...

【从零开始学习JVM | 第二篇】HotSpot虚拟机对象探秘

对象的创建 1.类加载检查 虚拟机遇到一条new的指令&#xff0c;首先去检查这个指令的参数能否在常量池中定位到这个类的符号引用&#xff0c;并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有&#xff0c;那必须先执行类的加载过程。 2.分配内存 在类…...

Pytest多环境切换实战:测试框架配置的最佳实践!

你是否也遇到过这种情况&#xff1a;本地测试通过&#xff0c;一到测试环境就翻车&#xff1f;环境变量错乱、接口地址混乱、数据源配置丢失……这些「环境切换」问题简直像定时炸弹&#xff0c;随时引爆你的测试流程&#xff01; 测试人员每天都跟不同的环境打交道&#xff0…...

单细胞多组学及空间组学数据分析与应用

一、引言 生命科学研究正处于快速发展的阶段&#xff0c;随着技术的不断革新&#xff0c;对生物系统的理解也在逐步深入到单细胞和空间层面。单细胞多组学及空间组学技术应运而生&#xff0c;它们突破了传统研究手段在细胞异质性和空间结构解析上的局限&#xff0c;为我们打开…...

[ctfshow web入门] web39

信息收集 题目发生了微妙的变化&#xff0c;只过滤flag&#xff0c;include后固定跟上了.php。且没有了echo $flag;&#xff0c;虽说本来就没什么用 if(isset($_GET[c])){$c $_GET[c];if(!preg_match("/flag/i", $c)){include($c.".php");} }else{…...