江苏宜安建设有限公司网站,网络市场调研的方法,销售管理软件排行,wordpress mo文件不起作用一、注意事项
explicit c中#xff0c;一个参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数)#xff0c;承担了两个角色#xff0c;构造器、类型转换操作符#xff0c; c提供关键字explicit#xff0c;阻止转换构造函数进行的隐式转换的发生#…一、注意事项
explicit c中一个参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数)承担了两个角色构造器、类型转换操作符 c提供关键字explicit阻止转换构造函数进行的隐式转换的发生声明explicit的构造函数不能在隐式转换中使用。c 函数前面和后面 使用const 的作用 前面使用const 表示返回值为const 后面加 const表示函数不可以修改class的成员 const成员函数可以被非const对象和const对象调用 非const成员函数只能被非const对象调用类外补充函数的定义要加作用域限定符::
二、重要知识cmake 在QT中选择cmake方式构建c项目最好提前了解cmake相关知识以方便理解如何导入外部库推荐学习视频链接B站爱编程的大丙 重要细节静态库的链接要放在add_executable之前
三、c代码调用python步骤
设置python配置 CMakeList.txt文件中输入python文件的相关信息头文件夹路径、库文件夹路径、需要连接的库文件名称有没有.lib后缀都可
include_directories(C:/programming/anaconda3/envs/pytorch/include)
link_directories(C:/programming/anaconda3/envs/pytorch/libs)
link_libraries(python3)
link_libraries(python38)2. c代码.cpp中调用python注下面代码中功函数invokePython的调用只可执行一次再次调用程序会崩溃
#include My_Functions.h
#include QDir
#include Python.hMy_Functions::My_Functions(QObject *parent) : QObject(parent){}
My_Functions:: ~My_Functions(){}bool My_Functions :: invokePython(){QDir dir;const char* pythonFilePath (dir.currentPath().append(/).append(dir.currentPath().split(/).last().split(-)[1])).toUtf8();Py_SetPythonHome(LC:/programming/anaconda3/envs/pytorch);//调用前必须初始化python解释器Py_Initialize();if(!Py_IsInitialized()){qDebug()初始化失败; return 0;}// 将路径转换为Python对象PyObject *py_path_str PyUnicode_FromWideChar(Py_DecodeLocale(pythonFilePath, NULL), -1);// 加载 python 脚本// 获取sys模块以进行项目.py文件的搜索PyObject *sys_module PyImport_ImportModule(sys);// 获取sys.pathPyObject *sys_path PyObject_GetAttrString(sys_module, path);if (!PyList_Check(sys_path)) {// sys.path不是列表错误处理qDebug()获取py搜索路径失败 ;// 释放python所用内存Py_Finalize();return 0;} else {// 将自定义路径添加到sys.pathint appended PyList_Append(sys_path, py_path_str);if (appended -1) {// 错误处理qDebug()添加py搜索路径失败 ;// 释放python所用内存Py_Finalize();return 0;}}PyObject *pModule PyImport_ImportModule(onnxUse);if (pModule NULL) {// 模块导入失败处理错误qDebug() 脚本加载失败;// 释放python所用内存Py_Finalize();return 0;} else {qDebug() 脚本加载成功;}// 创建函数指针PyObject* pFunc PyObject_GetAttrString(pModule, detect_images); // 方法名称if (pFunc NULL) {// 函数导入失败处理错误qDebug() 函数创建失败;// 释放python所用内存Py_Finalize();return 0;}else {qDebug() 函数创建成功;}// 调用有参函数// 创建函数参数// s 将C字符串转换成Python对象如果C字符串为空返回NONE// z: 类似于 s但允许转换为 NULLPython 的 None// c 将C类型的char转换成长度为1的Python字符串对象// b: C unsigned char将布尔值转换为 0 或 1// i 将一个C类型的int转换成Python int对象// k: C unsigned long转换为无符号长整数// l 将C类型的long转换成Pyhon中的int对象// f 将C类型的float转换成python中的浮点型对象// d 将C类型的double转换成python中的浮点型对象// O 通用对象引用接收任意 Python 对象而不转换// O!: 类型对象和转换标志用于接收特定类型的 Python 对象// O: 自定义回调函数用于自定义对象转换// (ii)两个 C 整型变量构成的元组或列表// [ii]两个 C 整型变量构成的列表// {ss}键值对都是 C 字符串的字典// #:s, #i, #d 等带有长度指示的字符串、整数或浮点数// n: 接收 None检查参数是否为 None// PyObject* args Py_BuildValue((i,s), 110, hello); // 参数为整数 110 和字符串 hello// PyObject *result PyObject_CallObject(pFunc, args);// 调用无参函数PyObject *result PyObject_CallObject(pFunc, NULL);// 检查并处理有参函数调用的返回结果if (result NULL) {// 处理错误qDebug() 函数调用失败;// 释放python所用内存Py_Finalize();return 0;} else {// 使用返回值qDebug() 函数调用成功;// const char *result_str;// if (!PyArg_Parse(result, s, result_str)) {// // 错误处理无法将Python对象转换为字符串// qDebug() 函数返回值处理失败;// // 释放python所用内存// Py_Finalize();// return 0;// } else {// // 使用result_str// }}// 释放引用计数Py_DECREF(result);// // 释放参数元组// Py_DECREF(args);// 释放函数指针Py_DECREF(pFunc);// 不再需要模块时减少引用计数Py_DECREF(pModule);// 释放python所用内存Py_Finalize();qDebug()调用完成;return false;
}局部多次调用python脚本 改造 invokePython 函数
bool My_Functions :: invokePython(){PyGILState_STATE gil_state; // 用以保存获取的Global Interpreter Lock (GIL)gil_state PyGILState_Ensure(); // 获取GIL只有拥有GIL的线程才可以执行python代码PyObject *pModule PyImport_ImportModule(onnxUse);if (pModule NULL) {// 模块导入失败处理错误qDebug() 脚本加载失败;return 0;} else {qDebug() 脚本加载成功;}// 创建函数指针PyObject* pFunc PyObject_GetAttrString(pModule, detect_images); // 方法名称if (pFunc NULL) {// 函数导入失败处理错误qDebug() 函数创建失败;PyErr_Print();return 0;}else {qDebug() 函数创建成功;}// 调用无参函数PyObject *result PyObject_CallObject(pFunc, NULL);// 检查并处理有参函数调用的返回结果if (result NULL) {// 处理错误qDebug() 函数调用失败;return 0;} else {// 使用返回值qDebug() 函数调用成功;// const char *result_str;// if (!PyArg_Parse(result, s, result_str)) {// // 错误处理无法将Python对象转换为字符串// qDebug() 函数返回值处理失败;// // 释放python所用内存// Py_Finalize();// return 0;// } else {// // 使用result_str// }}// 释放引用计数Py_DECREF(result);// // 释放参数元组// Py_DECREF(args);// 释放函数指针Py_DECREF(pFunc);// 不再需要模块时减少引用计数Py_DECREF(pModule);PyGILState_Release(gil_state); // 释放GIL释放前确保获取到了GIL同时最好主动释放各计数以防发生内存泄漏return false;
}同时不要忘记初始化python解释器注整个程序只可初始化一次结束程序前再释放否则再次初始化程序会崩溃下面是改造后的初始化函数 头文件
#ifndef INVOKE_PYTHON_INIT_H
#define INVOKE_PYTHON_INIT_H
#include QObject
#include Python.hclass Invoke_Python_Init
{
public:Invoke_Python_Init();~Invoke_Python_Init();
private:QString pythonDirectoryPath;bool init();void initPythonDirectoryPath();bool pythonDirectoryIsInit false;bool pythonIsInited false;
};#endif // INVOKE_PYTHON_INIT_H
源码文件
#include invoke_python_init.h
#include qDebug
#include QDirInvoke_Python_Init :: Invoke_Python_Init() {init();}
Invoke_Python_Init :: ~Invoke_Python_Init() {// 释放python所用内存Py_Finalize();qDebug()释放python解释器完成;
}bool Invoke_Python_Init :: init() {initPythonDirectoryPath();if (!pythonDirectoryIsInit) {qDebug()路径初始化失败 ; return 0;}Py_SetPythonHome(LC:/programming/anaconda3/envs/pytorch);//调用前必须初始化python解释器Py_Initialize();if(!Py_IsInitialized()){qDebug()python解释器初始化失败; return 0;}// 将路径转换为Python对象PyObject *py_path_str PyUnicode_FromWideChar(Py_DecodeLocale(pythonDirectoryPath.toLocal8Bit().constData(), NULL), -1);// 加载 python 脚本// 获取sys模块以进行项目.py文件的搜索PyObject *sys_module PyImport_ImportModule(sys);// 获取sys.pathPyObject *sys_path PyObject_GetAttrString(sys_module, path);if (!PyList_Check(sys_path)) {// sys.path不是列表错误处理qDebug()获取py搜索路径失败\n ;return 0;} else {// 将自定义路径添加到sys.pathint appended PyList_Append(sys_path, py_path_str);if (appended -1) {// 错误处理qDebug()添加py搜索路径失败 ;return 0;}// 将sys.path转换为QStringListQStringList pythonPathList;// 遍历sys.path列表for (Py_ssize_t i 0; i PyList_Size(sys_path); i) {PyObject *path_item PyList_GetItem(sys_path, i);// 将路径元素转换为QStringQString path_str QString::fromUtf8(PyUnicode_AsUTF8(path_item));// 添加到QStringListpythonPathList.append(path_str);// 减少引用计数Py_DECREF(path_item);}// 输出所有搜索路径到QDebugforeach (const QString path, pythonPathList) {qDebug() path \n;}}PyEval_ReleaseThread(PyThreadState_Get());pythonIsInited true;qDebug(Python解释器初始化成功);return true;
}
void Invoke_Python_Init :: initPythonDirectoryPath(){QDir dir;// 构建新的路径QString Path dir.currentPath().append(/).append(dir.currentPath().split(/).last().split(-)[1]);// 将QString赋值给pythonFilePathpythonDirectoryPath Path;pythonDirectoryIsInit true;
}在认为合适的地方初始化 Invoke_Python_Init 类初始化完成后便可重复调用 invokePython 函数即重复调用 python 脚本。
未完待续