目录
借鉴几位大佬(吐槽一下各种坑啊)
混合编程之——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博客