C++与Python混合编程

C++与Pyhon混合调在现实中有很多的应用场景,特别是对基于深度学习的产品开发上。所以无论是VS或者是QT都提供了相应的库来调用Python,本篇将以VS2019为例,大致讲述Python3.7在VS上混合编程的实现(注意:VS混合编程有很多的软件和硬件上的限制,特别是python版本,切勿使用3.9以上的python版本,以免个别函数调用出现问题)

1、Python环境的搭建
Python环境的搭建是混合编程实现的基础必要条件,这里主要包括,解释器的路径、解释器的debug模式(这点最容易出现问题)、python依赖包等,具体如下:
A、下载 Python 解释器并记录解释器位置
B、下载并安装 Debug 包(好多次调用失败就是这里出的错)
在这里插入图片描述
其中特别注意安装python版本的debug模式,具体安装如下:
a、右键点击更改
在这里插入图片描述
b、增加配置在这里插入图片描述
c、下一步
在这里插入图片描述
d、选择debug模式并安装
在这里插入图片描述
C、安装代码运行所需依赖的 python 包
在这里插入图片描述
2、VS 开发环境的搭建
1、打开项目属性
在这里插入图片描述
2、添加库目录
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3、常见函数的作用与使用
A、初始化 Py_Initialize(),使用函数前必做动作,可能产生错误,需要进行验证
B、变量申明 PyObject* pModule = NULL;
C、导入包或直接执行 python 指令 PyRun_SimpleString();
D、调用外部包或.py 文件 pModule = PyImport_ImportModule(“mytest”);
E、调用外部函数名或类 pFunc = PyObject_GetAttrString(pModule, “hello”);
F、调用函数 PyEval_CallObject(pFunc, NULL);
G、结束 python 调用 Py_Finalize();

4、参考代码

// testPython.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <Python.h>
using namespace std;

//调用hello函数,测试调用外部函数及外部Python sys包的调用
void hello()
{
	Py_Initialize();//使用python之前,要调用Py_Initialize();这个函数进行初始化
	PyObject* pModule = NULL;//声明变量
	PyObject* pFunc = NULL;// 声明变量
	pModule = PyImport_ImportModule("mytest");//这里是要调用的文件名
	pFunc = PyObject_GetAttrString(pModule, "hello");//这里是要调用的函数名
	PyEval_CallObject(pFunc, NULL);//调用函数
	Py_Finalize();//调用Py_Finalize,这个根Py_Initialize相对应的。
}

//调用add函数,传两个int型参数  
void add()
{
	Py_Initialize();
	PyObject* pModule = NULL;
	PyObject* pFunc = NULL;
	pModule = PyImport_ImportModule("mytest");      //Python文件名  
	pFunc = PyObject_GetAttrString(pModule, "add");  //Python文件中的函数名  
	//创建参数:  
	PyObject* pArgs = PyTuple_New(2);               //函数调用的参数传递均是以元组的形式打包的,2表示参数个数  
	PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 5));//0---序号  i表示创建int型变量  
	PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 7));//1---序号  
	//返回值  
	PyObject* pReturn = NULL;
	pReturn = PyEval_CallObject(pFunc, pArgs);      //调用函数  
	//将返回值转换为int类型  
	int result;
	PyArg_Parse(pReturn, "i", &result);    //i表示转换成int型变量  
	cout << "5+7 = " << result << endl;

	Py_Finalize();
}

//Python测试列表
void testList()
{
	Py_Initialize();
	PyObject* pModule = NULL;
	PyObject* pList = NULL;
	PyObject* pFunc = NULL;
	PyObject* pArgs = NULL;

	pModule = PyImport_ImportModule("mytest");
	pFunc = PyObject_GetAttrString(pModule, "testList");
	pArgs = PyTuple_New(1); // 函数调用的参数传递均是以元组的形式打包的, 1表示参数个数

	double array[] = { 1.2, 4.5, 6.7, 8.9, 1.5, 0.5 };

	//创建list
	pList = PyList_New(6);
	for (int i = 0; i < PyList_Size(pList); i++)
	{
		PyList_SetItem(pList, i, PyFloat_FromDouble(array[i]));
	}

	PyTuple_SetItem(pArgs, 0, pList);

	//返回值  
	PyObject* pReturn = NULL;
	pReturn = PyEval_CallObject(pFunc, pArgs);//调用函数  

	Py_Finalize();
}
void TestOpencv() 
{
	Py_SetPythonHome(L"C:\\Users\\****\\Anaconda3");
	Py_Initialize();//使用python之前,要调用Py_Initialize();这个函数进行初始化
	PyObject* pModule = NULL;//声明变量
	PyObject* pFunc = NULL;// 声明变量
	PyRun_SimpleString("import sys");
	PyRun_SimpleString("print(sys.executable)");
	pModule = PyImport_ImportModule("change background");//这里是要调用的文件名
	pFunc = PyObject_GetAttrString(pModule, "ChangeBackground");//这里是要调用的函数名
	if (pFunc==NULL)
	{
		cout << "func exe erre!!" << endl;
	}
	PyEval_CallObject(pFunc, NULL);//调用函数
	Py_Finalize();//调用Py_Finalize,这个根Py_Initialize相对应的。
}
int main()
{
	cout << "Starting Test..." << endl;
	cout << "hello()-------------" << endl;
	hello();
	cout << "add()---------------" << endl;
	add();
	cout << "testList()----------" << endl;
	testList();
	TestOpencv();
	return 0;

}

python参考代码:

这里需要将python代码放置在VS生成的exe文件所在目录内,或者自己指定目录

### mytest.py代码
# -*- coding: utf-8 -*-
import sys

def hello():
    print(sys.executable)
def add(a,b):
    return a+b
def testList(mylist):
    print(mylist)

def GetValue():
    array_1 = [1,2,3,4,5]
    array_2 = [3, 4, 5, 6, 7]
    return array_1+array_2
print(GetValue())

基于Python的opencv测试代码:

## change background.py测试代码
#!/user/bin/env python
# -*-coding/utf-8 -*-
# Aouher Tao Hong

import cv2
import  numpy as np

def ChangeBackground():
    img = cv2.imread('photo.jpg')
    img_back = cv2.imread('background.png')
    # 日常缩放
    rows, cols, channels = img_back.shape
    img_back = cv2.resize(img_back, None, fx=0.7, fy=0.7)
    cv2.imshow('img_back', img_back)

    rows, cols, channels = img.shape
    img = cv2.resize(img, None, fx=0.4, fy=0.4)
    cv2.imshow('img', img)
    rows, cols, channels = img.shape  # rows,cols最后一定要是前景图片的,后面遍历图片需要用到

    # 转换hsv
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    # 获取mask
    lower_blue = np.array([78, 43, 46])
    upper_blue = np.array([110, 255, 255])
    mask = cv2.inRange(hsv, lower_blue, upper_blue)
    cv2.imshow('Mask', mask)

    # 腐蚀膨胀
    erode = cv2.erode(mask, None, iterations=1)
    cv2.imshow('erode', erode)
    dilate = cv2.dilate(erode, None, iterations=1)
    cv2.imshow('dilate', dilate)

    # 遍历替换
    center = [50, 50]  # 在新背景图片中的位置
    for i in range(rows):
        for j in range(cols):
            if dilate[i, j] == 0:  # 0代表黑色的点
                img_back[center[0] + i, center[1] + j] = img[i, j]  # 此处替换颜色,为BGR通道
    cv2.imshow('res', img_back)
    cv2.imwrite('output.jpg', img_back)

    cv2.waitKey(0)
    cv2.destroyAllWindows()

运行结果:
在这里插入图片描述

Qt是一个跨平台的应用程序开发框架,常用于C++开发Python是一种动态类型的脚本语言混合编程指的是在一个项目中同时使用Qt/C++Python进行开发混合编程的好处是可以充分发挥Qt和Python各自的优势。Qt/C++可以提供高性能和可靠性,适用于底层开发和系统级编程Python则提供了简洁易懂、高效编程以及大量的第三方库,适用于快速开发和原型设计。 混合编程的打包过程可以分为以下几个步骤: 首先,需要安装相应的编译工具和开发环境,如Qt、C++编译器和Python解释器。确定使用的Qt版本与Python版本兼容。 其次,需要为C++部分编写Qt代码,并将其编译成dll或so动态链接库,以供Python调用。这需要使用Qt提供的相关工具和库进行编译和链接。 然后,使用Python的相关库(如PyQt或PySide)来调用C++部分的Qt代码,并将其与Python代码结合起来。这样,就可以实现Qt界面与Python逻辑的交互。 最后,将项目打包成可执行文件、二进制文件或安装包。这可以使用Qt提供的打包工具,如Qt Installer Framework,或者使用第三方工具和脚本来完成。 需要注意的是,在混合编程和打包过程中,需要仔细处理Qt的信号与槽机制与Python的回调机制之间的交互,以确保二者能够正常工作。 总之,Qt C++Python混合编程可以充分利用两者的优势,打包则需要注意兼容性和交互的处理。这种方式可以更灵活地开发应用程序,并能够适应不同的需求和平台。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值