vs2019 Qt C++中调用python代码

目录

1.添加依赖库,.lib,include

2.修改python.h文件

3.环境搭建好了下面是测试代码部分

4.如果按照面上走可能会出现的问题:

5.Qt+vs+python

6.说一下这里调py的主要步骤


借鉴几位大佬(吐槽一下各种坑啊)

混合编程之——C++调用python2.7&python3.5-CSDN博客

c++调用python(复杂版)_c++ 调用python复杂库-CSDN博客

环境配置:

1.添加依赖库,.lib,include

环境系统是win64位,python是win32位的。

vc++目录:

C/C++:

链接器->常规:

链接器->输入:

2.修改python.h文件

在python安装文件include下

#ifndef Py_PYTHON_H
#define Py_PYTHON_H

下面追加一行#define MS_NO_COREDLL或者#define Py_NO_ENABLE_SHARED

如果不进行此步骤:可能会出现以下报错信息cannot open file 'python35_d.lib'

3.环境搭建好了下面是测试代码部分

C++代码:

#include "stdafx.h"
#include "Python.h"
//#pragma comment(lib, "python37.lib")
int main()
{
	//Py_SetPythonHome(L"C:/Python37");
	Py_Initialize();
	PyRun_SimpleString("import sys; sys.path.append('.')");
	PyRun_SimpleString("import mytest;");
	PyRun_SimpleString("print(mytest.myabs(-2.0))");
	Py_Finalize();
	while (1) {
		//死循环,防止程序自动退出。
			int i = 0;
	}
	return 0;
}

python代码(python代码要放到与.h同意目录下): 

import math

def myabs(x):
    return math.fabs(x)

4.如果按照面上走可能会出现的问题:

原因就是python环境跟你的环境不搭,把你的解决方案平台修改一下,改成X86就可以运行了。

5.Qt+vs+python

其实准备的来说是vs+python,Qt跟跟vs配置大致相似,这里不做讨论。

先说一下py的库,打开py的目录,大致位置../Python/Python311,主要关注一下几个文件,一个是include和lib文件

 上面配置基本上没有什么变化,有改动地方应该是这里

 这里需要注意的地方python的库要与VS的位数要一致,否则会提示

x86与计算机当前模块x64不符

或明明选了libs文件夹还报错“未能解析的外部符号”LINK2019这种错误,也是位数不同导致的

其次,在使用Qt的时候

需要修改一些底层代码py的../include/object.h

typedef struct{
    const char* name;
    int basicsize;
    int itemsize;
    unsigned int flags;
#undef slots
    PyType_Slot *slots; /* terminated by slot==0. */
#define slots Q_SLOTS
} PyType_Spec;

上述做完在需要做的地方添加头文件#include "Python.h",编译一下,看是否出错,如果有问题就检查以上步骤.

6.说一下这里调py的主要步骤

以下步骤当然也有其他函数,这里只是说下大致流程,如果在在以下流程崩溃,根据这个流程检查就可以了,需要注意流程基本用的是Pyobject*指针,Python使用引用计数机制对内存进行管理,实现自动垃圾回收。在C/C++中使用Python对象时,应正确地处理引用计数,否则容易导致内存泄漏。在Python/C API中提供了Py_CLEAR()、Py_DECREF()等宏来对引用计数进行操作.

初始化py库

Py_Initialize()

加载自己写的py模块

PyImport_ImportModule

//调用模块函数

PyObject_GetAttrString

//获取数据

PyEval_CallObject

释放库

Py_Finalize

下面例子为例

    Py_Initialize();
    // 将Python脚本所在路径添加到sys.path中
	PyRun_SimpleString("import sys;sys.path.append('.')");
	

    // 导入Python脚本,如果这里返回空,8成就是路径问题
	PyObject* pModule = PyImport_ImportModule("pdf_extractor");  
    if (!pModule)
	{
        // 这里如果pModule位NUll,检查上面.py文件在那,其实就是sys.path.append('.')
		PyErr_Print();
		return;
	}
    // 获取Python函数对象
	PyObject* pFunc = PyObject_GetAttrString(pModule, "extract_text");
    if (!pFunc)
	{
        // 同上检查文件里面有extract_text函数没
		PyErr_Print();
		return;
	}
	PyObject* pFunc1 = PyObject_GetAttrString(pModule, "extract_prin");  // 获取Python函数对象
	if (pFunc && PyCallable_Check(pFunc)) {
		string fileName = str.toStdString();// "/path/to/pdf_file.pdf";
        // 这里也可以是 其中第一个参数可以看下面截图
        // 如果第一个参数与后面参数不匹配,指针也会是NULL
        //PyObject* args = Py_BuildValue("ss", "123", str);
        
        // 创建一个包含一个参数的元组
		PyObject* pArgs = PyTuple_New(1);  
        // 设置参数值为字符串类型
		PyTuple_SetItem(pArgs, 0, PyUnicode_FromString(fileName.c_str())); 
 
        // 调用Python函数
        // 这里必须说一下如果pResult为空,有好几种情况
        // 1.脚本本身就有错误
        // 2.传参不对,就上步
		PyObject* pResult = PyObject_CallObject(pFunc, pArgs);  
		if (pResult) {
			int iResult = 0;
            // 如果返回的值也就是iResult不正确,就要检查返回值,以及编码    
            // 字符编码特别麻烦,特别是多国语言的,会遇到无法识别的字符串,大概率就是字符串问题
			PyArg_Parse(pResult, "i", &iResult);
			Py_DECREF(pResult);
			if (iResult == -1)
			{
				return;
			}
		}
		else {
			return;
		}
		Py_DECREF(pArgs);
	}
	else {
		return;
	}
	Py_DECREF(pFunc);
	Py_DECREF(pModule);
	Py_Finalize();

 py脚本主要读pdf提取文字,里面有8国语言字符,你们可以试下,用C++调脚本获取能不能获取到,如果能获取到,把方法写到评论里

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#import PdfReader
from PyPDF2 import PdfReader
import os

# .py文件无明显问题,但需要注意以下几点:
# 1.函数名extract_text需要更改为更具有描述性的名称,以便更好地表达函数的作用。
# 2.Path变量应该是函数的参数而不是硬编码在函数中的。
# 3.函数应该返回一个列表而不是一个字符串,以便更好地处理提取的文本。
# 4.需要导入PdfReader模块。
def extract_text(filename):
    Path = filename
    text = ""
    try:
        pdf = PdfReader(Path)
        for page in pdf.pages:
            text = text + page.extract_text()
        text_path = os.getcwd()
        file = open(text_path + "\\pdf_text.txt", "w", encoding="utf-8")
        file.write(text)
        file.close()
    except FileNotFoundError:
        return -1
    return 1
    
#test print
def extract_prin(name):
    return '8  '

#'May I write \'I Love You\' in 8 different languages  \nPosso scrivere \'Ti amo\' in 8 lingue diverse  \n8カ国語で「愛してる」と書いてください  \nPosso escrever \'Eu te amo\' em 8 idiomas diferentes  \nÉcrivez "Je t\'aime" en 8 langues.  \nDarf ich \'I Love You\' in 8 verschiedenen Sprachen schreib en \n请问用 8国语言来写”我爱你”  \nPor favor, escriba "te amo" en el idioma de ocho pa íses. '


#if __name__ == '__main__':
#    text1 = extract_text("C:/Users/admin/Desktop/1.pdf")
#    print(extract_prin(""))

 Py_BuildValue函数第一个参数含义图

 报错tip: warning: mpd_setminalloc: ignoring request to set MPD_MINALLOC a second time

是因为多次调用Py_Initialize导致的

参考文档:

C++调用python(执行py文件)的全过程_C 语言_脚本之家

C++调用Python(混合编程)函数整理总结_jindayue的博客-CSDN博客

C++调用Python的API_pyinstance_new-CSDN博客

Python 扩展中的Py_BuildValue()函数-CSDN博客

C/C++和python之间相互调用的讲解***_51CTO博客_c++调用python

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路奇怪

有钱出钱,没钱多出编程主意啊

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值