C++如何调用python并取返回值

 更新时间:2024年03月01日 10:53:01   作者:玖五二七  
这篇文章主要介绍了C++如何调用python并取返回值问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

C++调用python并取返回值

前面介绍了用python调用C++时用swig工具,现在简单介绍一下C++调用python并取返回值的过程

python文件test.py

class tester:
    def add(self, a, b):
        return a + b

新建一个VS控制台项目

main.cpp所有的源码如下:

#include <stdio.h>
#include <python.h>
#include <windows.h>
void main()
{
    Py_Initialize(); // 初始化python虚拟机
    PyObject* pyMod  = PyImport_ImportModule("test"); //  加载test.py文件
    PyObject* pyDict = PyModule_GetDict(pyMod); //  获取test模块中的字典
    PyObject* pyCls = PyDict_GetItemString(pyDict, "tester"); // 从字典中查找tester类
    PyObject* PyIns = PyInstance_New(pyCls, NULL, NULL); // 创建tester类
    PyObject* pyRet = PyObject_CallMethod(pyIns, "add", "ii", 5, 6); // 调用tester.add方法,传入2个int型参数
    int ok = -1;
    int retok = PyArg_Parse(pyRet, "i", &ok); // 从返回值从取出int型返回值
    Py_Finalize();
    system("pause");
}

整个过程最重要的是  PyBoject_CallMethod,传入的参数类型一定不能搞错。

还有取返回值的时候PyArg_Parse取单个返回值,要是取多个的可以用PyArg_ParseTuple,要取的类型也必须完全匹配。

c++调用python时参数传递和返回值解析

通过python接口在cpp中调用python函数时,构建传参和解析返回值都会用到python内的变量类型和c++的变量类型之间的转换。

返回值是numpy等复杂结构的数据时,可以通过先转换为list等类型再返回,或者单独构建一个函数,获取numpy内某个位置的变量的函数。

下面几个基础类型的返回值解析

#python
#返回一个参数
def returnInt(a,b):
    return a+b
#返回两个相同类型的参数
def returnTwoInt():
    return 1,2
#返回字符串
def returnString():
    srt = 'hello world'
    return srt
#返回list
def returnList():
	para = [1, 2, 3, 4]
    return 1,para.tolist()
#返回两个不同类型的参数
def returnTwo():
	para = [1, 2, 3, 4]
    return 1,para.tolist()
#返回矩阵
def returnMat():
    img = cv2.imread('test1.bmp',cv2.IMREAD_GRAYSCALE)
    return img
	//调用python函数,返回的数据统一为PyObject类型,需要根据实际类型进行解析
	PyObject* pReturn = PyObject_CallObject(pFunc, pArgs);
	//当不需要传参时,可以将参数位置为空
	PyObject* pReturn = PyObject_CallObject(pFunc,NULL);

PyObject为结构体,参数ob_type->tp_name 为数据的类型

//不同类型参数传递
	PyObject* p = PyTuple_New(4);
	for (int i = 0; i < 4; i++)
		PyTuple_SetItem(p, i, Py_BuildValue("i", i));
	PyObject* pArgs = PyTuple_New(2);
	PyTuple_SetItem(pArgs, 0,Py_BuildValue ("i",1));
	PyTuple_SetItem(pArgs, 0,Py_BuildValue ("O",p));
	
//返回为list
	double temp;
	int i_size = PyList_Size(pReturn); 
	for (int i = 0; i < i_size; ++i)
	{
		PyArg_Parse(PyList_GetItem(pReturn, i), "d", &temp);
		std::cout << "return result is " << (temp) << std::endl;
	}
//返回为 int 和 list 两个不同类型的参数
	PyArg_Parse(PyTuple_GetItem(pReturn, 0), "d", &temp);
	std::cout << "temp is " << (temp) << std::endl;
	PyObject* pReturnlist;
	PyArg_Parse(PyTuple_GetItem(pReturn, 1), "O", &pReturnlist);
	i_size = PyList_Size(pReturnli); 
	for (int i = 0; i < i_size; ++i)
	{
		PyArg_Parse(PyList_GetItem(pReturnli, i), "d", &temp);
		std::cout << "return result is " << (temp) << std::endl;
	}
//返回单独一个变量
	//构建输入
	PyObject* pArgs = PyTuple_New(2);
	PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 1));
	PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 1));
	PyObject* pReturn2 = PyObject_CallObject(pFunc, pArgs);
	//解析
	int nResult1;	//解析为int
	PyArg_Parse(pReturn2, "i", &nResult1);
	std::cout << "add=" << nResult1 << std::endl;
	double nResultd;	//解析为double
	PyArg_Parse(pReturn2, "d", &nResultd);
	std::cout << "add=" << nResultd << std::endl;
//返回字符串
	//解析方法1:
	PyObject* repr = PyObject_Repr(pReturn);
	PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "strict");
	char* result = PyBytes_AsString(str);
	std::cout << result << std::endl;
	//解析方法2:
	char* pstr = NULL;
	PyArg_Parse(pReturn, "s", &pstr);
	std::cout << pstr << std::endl;

//返回多个变量
	//循环解析
	int nResult;
	i_size = PyTuple_Size(pReturn); 
	for (int i = 0; i < i_size; ++i)
	{
		PyArg_Parse(PyTuple_GetItem(pReturn, i), "i", &nResult);
		std::cout << "return result is " << (nResult) << std::endl;
	}
	//直接解析
	int nResult1;
	int nResult2;
	PyArg_ParseTuple(pReturn,"i|i", &nResult1, &nResult2);   
	std::cout << "return  " << nResult5<< ' ' << nResult6 << std::endl;
//解析二维矩阵
	//获得序列长度,即行数
	Py_ssize_t rsize = PyObject_Size(pReturn);
	std::cout << rsize << std::endl;
	//转换到迭代器,用于提取数据
	PyObject* iter = PyObject_GetIter(pReturn5);
	while (true)
	{
		//获取矩阵的第一行
		PyObject* next = PyIter_Next(iter);
		if (!next) { // nothing left in the iterator
			break;
		}
		if (!PyList_Check(next))
		{ // error, we were expecting a list value }
		//获得当前行的数据数量
		Py_ssize_t foosize = PyObject_Size(next);
		std::cout << foosize << std::endl;
		//转换到迭代器,用于获取数据
		PyObject* iter2 = PyObject_GetIter(next);
		while (true)
		{
			PyObject* next2 = PyIter_Next(iter2);
			if (!next2)
				break;
			if (!PyFloat_Check(next2))
			 {// error, we were expecting a floating point value}
			double foo = PyFloat_AsDouble(next2);
			std::cout << foo << " ";
		}
		std::cout << std::endl;
	}

python手册,接口的使用示例等

https://docs.python.org/3/

	//解析常用字段:
	// b <=>char 0-255的那个char
	// c <=>char 单个字符
	// h <=>short int
	// l <=>long int
	// f <=>float
	// d <=>double
	// s <=>char*
	// O <=> PyObject 

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 一文带你掌握C++中的移动语义和完美转发

    一文带你掌握C++中的移动语义和完美转发

    这篇文章主要为大家详细介绍了C++中的移动语义和完美转发的相关知识,文中的示例代码讲解详细,对我们深入掌握C++有一定的帮助,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12
  • C语言中数据的存储详解

    C语言中数据的存储详解

    这篇文章主要介绍了C语言中数据的存储详解的相关资料,需要的朋友可以参考下
    2023-08-08
  • C语言二进制思想以及数据的存储

    C语言二进制思想以及数据的存储

    本文主要介绍了C语言的二进制思想以及数据的存储,这里对二进制和数据存储做了详细的说明,对开始学习C语言的同学比较有参考价值
    2016-07-07
  • Qt中JSON使用的详细步骤

    Qt中JSON使用的详细步骤

    本文主要介绍了Qt中JSON使用的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-08-08
  • c语言随机数函数示例

    c语言随机数函数示例

    这篇文章主要介绍了c语言随机数函数示例,需要的朋友可以参考下
    2014-04-04
  • C++ 中try finally关键字详解

    C++ 中try finally关键字详解

    本文给大家介绍C++ 中try finally关键字的相关知识,非常不错,本文介绍的非常详细,具有参考借鉴价值,感兴趣的朋友一起学习吧
    2016-05-05
  • 配置CLion管理Qt项目国际化支持的方法

    配置CLion管理Qt项目国际化支持的方法

    这篇文章主要介绍了配置CLion管理Qt项目国际化支持的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • C语言PlaySound函数使用方法

    C语言PlaySound函数使用方法

    这篇文章介绍了C语言PlaySound函数的使用方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-12-12
  • C语言开发中的常见错误详解

    C语言开发中的常见错误详解

    这个分栏是对于使用C语言编程过程中可能会出现的一些错误而进行的说明,更多的错误示例将会在后面的内容里进行演示。希望这个分栏的内容可以帮助刚学编程的小白少走一些弯路,以及吸取更多的编码经验
    2022-05-05
  • C++小游戏教程之猜数游戏的实现

    C++小游戏教程之猜数游戏的实现

    这篇文章主要和大家详细介绍如何利用C++做一个简易的猜数游戏,分为用户猜数和系统猜数。文中的示例代码讲解详细 ,感兴趣的小伙伴可以尝试一下
    2022-11-11

最新评论