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的办法 的相关文章

随机推荐

  • 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