C++中调用Python的办法

2023-05-16

1 背景

一直采用C++作为主语言开发,最近遇到一个项目需要解析PDF文件中的文本内容,直接采用C++来做显得不是很方便,但用python来做就显得很简单了。

难点在于如何C++语言环境下调用python来实现功能。

2 开发环境

Python版本为: 3.7.3(32 bit)版本。

 QT版本为:Qt 5.12.2(MSVC 2017, 32bit)

 QtCreator中项目的配置如下:

重要的事情(版本匹配): 

       请确保Python版本与QT版本的位数相一致,要么同为32bit,要么同为64bit。否则可能会出现代码能编译,但是debug的时候,会出现the cdb process terminated之类莫名其妙的错误。

        这里确实是一个坑,最开始本人安装的是64bit版本的python,程序也选的是64bit编译器和64bitdebugger。

        但由于QTcreator本身的版本(Based on Qt 5.12.2 (MSVC 2017, 32 bit))就是32bit的,就导致了莫名的错误。后来我都以QTcreator本身的版本为基准,全部换成32bit的,问题就解决了。

3 动手建立工程!

       方便起见,本文将python 3.7的安装目录中的几个必要文件夹(文件)直接拷贝到工程目录下,方便使用相对路径,也方便后续直接制作安装包。

当然,采用绝对路径也是香的,看个人喜好吧。

3.1 添加头文件包含目录、附加库目录、依赖库

在pro文件中:

添加

INCLUDEPATH += "./include"
LIBS += -L./libs -l_tkinter -lpython3 -lpython37
#消除中文乱码问题
msvc:QMAKE_CXXFLAGS += -execution-charset:utf-8
msvc:QMAKE_CXXFLAGS += -source-charset:utf-8

显然这里是使用了相对路径的方式。

3.2 在工程中引入头文件

#include "Python.h"

不出意外的话,这时候编译会出错!”error: C2238: 意外的标记位于“;”之前“.....

此外,还有 error: LNK1104: 无法打开文件“python36_d.lib”,甚至还有其他的...

莫慌,这里有一个很好的解决办法:

点这里错误解决,详细!

3.3 创建Python文件和工程内的C++调用

        创建一个python文件,放在当前工程exe文件的同级目录下(又是绝对和相对路径的小问题),只要让你的程序能找的到就行,其余随意!

parsepdf.py:

# -*- coding: utf-8 -*-

def readPDF(pdfpath):
	import pdfplumber
	import re
	pdf = pdfplumber.open(pdfpath)
	result=''
	for page in pdf.pages:
		result+= page.extract_text() + "\n\n"#页与页之间靠"\n\n"做间隔.
	
	pdf.close()
	return (result)

在C++中调用:

/*
*pdfpathName: 所要解析的PDF的绝对路径,同时也是传给python脚本的参数(注意如何传参)
*/
int MainWindow::PDFParserAndGenerate(QString pdfpathName)
{
    int ret = 0;
    do
    {
        //尝试加载python模块
        Py_SetPythonHome((const wchar_t *)(L"./Python37"));//发布时候加上这一句
        Py_Initialize();//初始化py模块
        if ( !Py_IsInitialized() )
        {
            ret = -1;
            break;
        }

        QString dirpath = QApplication::applicationDirPath();
        dirpath = QDir::toNativeSeparators(dirpath);

        PyRun_SimpleString("import sys");
        PyRun_SimpleString("sys.path.append('./')");//当前路径
        PyObject* pModule = PyImport_ImportModule("parsepdf");// parsepdf.py
        if (!pModule)
        {
            qDebug()<< "Cant open python file!\n";
            ret = -2;
            break;
        }
        PyObject* pFunparse= PyObject_GetAttrString(pModule,"readPDF");  // 这里的readPDF就是python文件定义的函数
        if(!pFunparse)
        {
             qDebug()<<"Get function readPDF failed";
             ret = -3;
             break;
        }
        // 创建元组设置参数
        QTextCodec *tc = QTextCodec ::codecForName("UTF-8");
        QByteArray ba = pdfpathName.toUtf8();
        char *path = ba.data();

        PyObject*  arg1 = PyUnicode_FromString(path);
        PyObject*  args = PyTuple_New(1);
        PyTuple_SetItem(args, 0, arg1);

        PyObject* fshowc = PyObject_CallObject(pFunparse,args);//调用main函数
        //PDFReportInfo reportInfo;
        if (!fshowc)
        {
            qDebug()<<"PyObject_CallObject error";
            ret = -4;
            break;
        }
        QString resultPDF = PyUnicode_AsUTF8(fshowc);/*整份PDF文档解释出来的内容 */
        QStringList  pages =resultPDF.split("\n\n");/*分割出每页内容 */

        QVector<QString>  lines;
        for (int i = 0; i < pages.size(); ++i)//遍历每一页
        {
            QStringList  listContent =pages.at(i).split("\n");/*分割单页内容 */
            for (QString s : listContent)
                lines.append(s);//每一行
        }
        // ToDo ....这里加上自己的业务代码....
    }
    while(0);

    //好同志总是在最后不忘释放资源!
    if ( Py_IsInitialized() )
    {
        Py_Finalize();
    }


    return ret;
}

4 工程打包

编译调试完毕之后,就要打包发布出去,搞到其他电脑上运行了。

注意发布包内的内容。Python37文件夹就是 “3 动手建立工程!”小节一上来就提到的部分。

保险起见,下图中的python3.dll    python37.dll  和 vcruntime140.dll是重复放进来了(Python37文件夹)中也有。可能不重复也可以,但没去尝试。

​​​​​​​

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++中调用Python的办法 的相关文章

  • 如何使用 Python 和 Selenium WebDriver 获取 localStorage

    相当于什么 driver get cookies 获取 LocalStorage 而不是 ookies python API没有提供直接读 写本地存储的方法 但可以通过execute script class LocalStorage de
  • 出现异常时进行截图

    嘿 有没有一种方法可以在异常 任何异常 时捕获屏幕截图 我的 失败 解决方案位于BaseTestCase unittest TestCase子类 class BaseTestCase unittest TestCase classmetho
  • 在numpy中,[:,None]选择有什么作用?

    我正在学习 Udacity 的深度学习课程 我遇到了以下代码 def reformat dataset labels dataset dataset reshape 1 image size image size astype np flo
  • pandas 系列值之间的过滤

    If s is a pandas Series http pandas pydata org pandas docs stable dsintro html series 我知道我可以这样做 b s lt 4 or b s gt 0 但我做
  • 我应该将Python的pyc文件添加到.dockerignore吗?

    我见过几个例子 dockerignorePython 项目的文件 其中 pyc文件和 或 pycache 文件夹被忽略 pycache pyc 由于无论如何这些文件 文件夹都会在容器中重新创建 我想知道这样做是否是一个好习惯 是的 这是一个
  • 合并一个对(元组)列表?

    从链接对的列表中 我想将这些对组合成公共 ID 组 这样我就可以将 group ids 写回数据库 例如 UPDATE table SET group n WHERE id IN Example 1 2 3 4 1 5 6 3 7 8 be
  • Python 2.7从非默认目录打开多个文件(对于opencv)

    我在 64 位 win7 上使用 python 2 7 并拥有 opencv 2 4 x 当我写 cv2 imread pic 时 它会在我的默认 python 路径中打开 pic 即C Users Myname 但是我如何设法浏览不同的目
  • 如何获取一个类的所有实例

    我是一名初学者 正在学习 Python 我想创建一个课程Person 在构造函数中 我想将我创建的每个实例放入一个名为 实例 的集合中 然后我希望实例 方法返回所有实例 我怎样才能做到这一点 class Person Type annota
  • 使用 ruamel.yaml,如何使带有 NEWLINE 的变量成为不带引号的多行

    我正在生成用作协议的 YAML 其中包含一些生成的 JSON import json from ruamel import yaml jsonsample id 123 type customer account other myyamel
  • Python 请求包含有值的参数和没有值的参数

    我正在为 API 编写一个 Python 包装器 该 API 支持具有值的查询参数 例如param1如下 和查询参数do not有价值观 例如param2如下 即 https example com service param1 value
  • 如何在Python中的字符串中插入变量值

    这是一个简单的例子 amount1 input Insert your value amount2 input Insert your value print Your first value is amount1 your second
  • Keras CNN 回归模型损失低,准确度为 0

    我在 keras 中遇到这个 NN 回归模型的问题 我正在研究一个汽车数据集 以根据 13 个维度预测价格 简而言之 我已将其读取为 pandas 数据帧 将数值转换为浮点数 缩放值 然后对分类值使用 one hot 编码 这创建了很多新列
  • 有没有比 ` except: pass` 更简洁的替代方案?

    我有一个函数 可以按偏好顺序返回多个组的随机成员 事情是这样的 def get random foo or bar I d rather have a foo than a bar if there are foos return get
  • Python 正则表达式中的 \B+ 与 [\B]+ 与 [^\b]+

    我在回答 SO 问题时遇到了一个我不明白的问题 我创建了一个简化的示例来说明该问题 场景 我正在测试两个标记 不是随机的英语单词 在字符串中至少相距一定距离 在这个例子中 我们有一个动物列表 我们要确保在羊和狼之间至少还有其他三种动物 否则
  • 如何导入 boto3 ssm ParameterNotFound 异常?

    我想import the exception当一个boto3 ssm找不到参数get parameter 我正在尝试添加一些额外的内容ssm的功能moto图书馆 但我现在很困惑 gt gt gt import boto3 gt gt gt
  • 为什么使用 LAMP 托管时避免使用 CGI for Python?

    我已经使用 PHP 多年了 最近我在论坛上看到很多帖子说PHP 已经过时了 现代编程语言更简单 更安全等等 所以 我决定开始学习Python 由于我习惯使用 PHP 因此我刚刚开始通过上传 htaccess 文件来构建页面 addtype
  • 在 pandas DataFrame 中使用比较列表的问题

    我在 pandas 中有一个 DataFrame 其列类型之一是 int 上的列表 如下所示 df pandas DataFrame 1 2 3 4 5 6 7 8 9 10 columns a b c d gt gt gt df a b
  • 在 envoy 中使用 rm *(通配符):没有这样的文件或目录

    我正在使用 Python 和 Envoy 我需要删除目录中的所有文件 除了一些文件外 该目录是空的 在终端中 这将是 rm tmp my silly directory 常识表明 在特使中 这转化为 r envoy run rm tmp m
  • 捕获 subprocess.run() 的输入

    我在 Windows 上有一个交互式命令行 exe 文件 是由其他人编写的 当程序出现异常时 它会终止 并且我对程序的所有输入都会丢失 所以我正在编写一个 python 程序 它调用一个阻塞子进程subprocess run 并捕获所有输入
  • python nltk从句子中提取关键字

    我们要做的第一件事 就是杀掉所有律师 威廉 莎士比亚 鉴于上面的引用 我想退出 kill and lawyers 作为两个突出的关键词来描述句子的整体含义 我提取了以下名词 动词 POS 标签 First NNP thing NN do V

随机推荐

  • 7_资源文件添加

    资源文件添加 在QMainWindow中我们已经设立了一些部件 xff0c 现在我们来设置图标 通常有相对路径读取和资源文件读取两种方法 QAction actionNew 61 new QAction 基本格式 ui gt actionN
  • 智能除草机

    专利设计 xff1a 智能除草机 1 除草机背景 业界主要采用滚刀式草坪修剪车来进行运动场的除草 除草不仅浪费人力 xff0c 而且也受到天气状况的限制 传统割草机产生的环境污染也较大 随着社会经济的不断发展 xff0c 人力成本也不断攀升
  • nodejs解析http协议源码解析

    上篇文章讲到nodejs创建一个服务并且建立tcp连接的过程 接下来分析一下 xff0c 在建立tcp连接后 xff0c nodejs是如何解析http协议的 我们首先看一下nodejs在建立tcp连接时执行net js层的回调时做了什么操
  • template模板及模板类的实例化

    模板template 通常 xff0c 当我们调用一个函数时 xff0c 编译器只需要掌握函数的声明 类似的 xff0c 当我们使用一个类类型的对象时 xff0c 类定义必须是可用的 xff0c 但成员函数的定义不必已经出现 因此我们将类定
  • java学习简记录(四)

    java学习简记录 xff08 四 xff09 Java 程序是一系列对象的集合 xff0c 这些对象通过调用彼此的方法来协同工作 对象 xff1a 对象是类的一个实例 xff0c 有状态和行为 类 xff1a 类是一个模板 xff0c 它
  • VS2015+QT5.6.1环境配置后,在VS中双击无法打开*.ui文件

    在环境都搭建好以后 xff0c 在VS中新建了一个QT界面工程 双击 ui后 xff0c 期望得到Qt designer那种直接进入拖拉控件进行编辑的操作界面 but 并不能得到预期结果 解决方法如下 第1步 xff1a 在 解决方案资源管
  • 求字符串的最长回文

    主要锻炼的就是动态规划的思想 xff01 xff01 xff01 掌握这种思想 xff0c 工作中不一定用得上 xff0c 但是多一种思想就多一种可能 span class token comment dp i j 表示s的子串 xff08
  • C++查找指定目录下的特定后缀文件并按照创建时间排序

    在一个项目中 xff0c 遇到了这个需求 于是windows 43 vs平台上实现了这个功能Demo 测试完毕后移植到了具体的项目中 span class token macro property span class token dire
  • Ubuntu下Qt程序生成Core文件便于调试

    需要在运行时生成core dump文件 xff0c 以排查出错的代码行 首先在pro结尾里加入 xff1a QMAKE CC 43 61 g QMAKE CXX 43 61 g QMAKE LINK 43 61 g 在终端输入 ulimit
  • linux查看进程所有子进程和线程

    线程是现代操作系统上进行并行执行的一个流行的编程方面的抽象概念 当一个程序内有多个线程被叉分出用以执行多个流时 xff0c 这些线程就会在它们之间共享特定的资源 xff08 如 xff0c 内存地址空间 打开的文件 xff09 xff0c
  • 一款二进制文件查看器

    由于使用的是Notepad 43 43 64位版本 xff0c 在网上找了很多二进制查看插件HexEditor dll要么是32位不兼容 xff0c 要么是出现除零的错误 xff08 以前找到过一次支持Notepad 43 43 64位版本
  • YOLO目标检测

    一 背景 基于深度学习技术的视觉目标检测近年去的长足发展 但仍然有许多方面问题需要优化 二 YOLO算法的特点 YOLO作为一种性能优异的通用目标检测系统 xff0c 为了保证检测的效率 xff0c 提出one stage的思想 xff0c
  • (Qt中添加编译选项)QT在交叉编译时出现parameter passing for argument of type ‘std::_Rb_tree xxxxx changed in GCC 7.1

    QT版本都是5 1x 先是在Ubuntu机器上写的代码 xff0c GCC版本为5 4 xff0c 代码编译无 任何警告 后来移植到开发板 xff08 GCC版本为7 1 xff09 进行编译时 xff0c 提示这种警告 发生在代码中对st
  • C++按行读取文本并解析

    项目中需要按行读取文本文件 xff0c 并对每一行内容进行解析 每一行都是固定的字段数 xff0c 字段之间用空格隔开 span class token macro property span class token directive k
  • error C2447: “{”: 缺少函数标题(是否是老式的形式表?)

    error C2447 缺少函数标题 是否是老式的形式表 网上有人说 这个BUG是因为在win7上使用了 LF 的格式编码导致的 使用Notepad 43 43 修改成 BOM UTF8 和 windows 的 CR LF 格式一切正常 确
  • Visual Studio 2017 代码自动对齐

    点 编辑 高级 设置选定内容的格式 或者按Ctrl 43 K 然后再按Ctrl 43 F 就好了 你可以在常用快捷键自定义 窗口中进行查看 1 进入工具 选项 对话框 2 选择 环境 键盘 3 在 显示命令包含 下面的对话框中输入 对齐 关
  • CSDN 排版之颜色、字体、字号及背景色

    颜色 xff1a span class token operator lt span font color span class token operator 61 span blue span class token operator g
  • 使用QTCreator编程时,如何利用dmp文件定位程序奔溃

    写这篇文章之前 xff0c 看了一些其他人的博客 xff0c 但不是很详细 xff0c 缺这少那的 xff0c 好多都是复制粘贴别人的东西 自己动手弄了弄 xff0c 可以使用 xff0c 就记下来备忘与分享 前言 开发环境说明 编程IDE
  • Pytorch中transforms.RandomResizedCrop使用说明

    加载数据 训练集数据扩充 数据增强 和归一化 数据扩充 数据增强 的意义在于通过人为的随机范围裁剪 缩放 旋转等操作 增大训练集中的数据多样性 全面性 进而提高模型的泛化能力 训练集数据扩充和归一化 在验证集上仅需要归一化 data tra
  • C++中调用Python的办法

    1 背景 一直采用C 43 43 作为主语言开发 xff0c 最近遇到一个项目需要解析PDF文件中的文本内容 xff0c 直接采用C 43 43 来做显得不是很方便 xff0c 但用python来做就显得很简单了 难点在于如何C 43 43