c++调用python(附代码)

本文详细介绍了如何在VisualStudio2019环境下配置C++项目以使用Python,包括添加Pythoninclude和lib目录,处理Pythondebug库缺失的问题,以及提供了一个简单的C++调用Python脚本的示例代码。
摘要由CSDN通过智能技术生成

环境:vs2019,python-3.7.9

本人目前用c++做一个测试工具,打算加入脚本,首当其冲就是python,后面是java和js,java应该是使用jni,js的话网上看到了个v8,后面有深入再说

配置

首先要装好python环境,然后在右键项目->属性->配置属性->vc++目录:在包含目录添加入python安装位置下的include目录,在库目录中添加python安装位置下的libs目录

本人python安装位置为D:\CodeApp\python\python-3.7,所以包含目录为D:\CodeApp\python\python-3.7\include,库目录为D:\CodeApp\python\python-3.7\libs

在这里要注意活动和平台,平台的版本位数要和python安装的位数一样,python安装如果是32位的,平台要改成win32,运行要用x86。python如果是64位,也是一样

一个简单的运行代码

#include <Python.h>

int main()
{
    Py_Initialize();    

    PyRun_SimpleString("print('hello')");

    Py_Finalize(); 
}

可能的问题 :无法打开python37_d.lib

 到上述的libs目录下看,发现没有python37_d.lib文件

这是因为当初安装python时没有勾选下面这个选项

 已经安装好的启动安装的程序,点击modify,点击next,勾选上,点击install

 出现这个问题,可以点击log file打开日志查看问题

 这里说一下,这个问题其实是它需要去访问https://www.python.org/ftp/python/3.8.1/win32/core_d.msi来进行下载和安装,这个网址时外网,所以失败(这个路径和下图的内容使用python3.8.1来演示,python3.7.9已经安装好了,不想重新在弄一遍)

 遇到这种问题,去官网下载所需要的文件

 地址:Index of /ftp/python/

选择你的python版本

选择你的安装python的位数,32位还是64位

将.msi文件下载到python安装包存放的目录(本人下载时没有全部下载,一般像是core.msi和core_d.msi两个文件,只需要下载core_d.msi,一般是下载_d.msi结尾,但有个别例外,如果不清楚的可以去查看报错的日志,或者全部下载)

 下载好点击跟上面一样点击modify,点击next,勾选,点检install

 这时在libs目录下就可以找到python37_d.lib文件

另一种解决办法

将debug改成release,但是这没办法调试,不提倡

 运行结果

代码

这代码算是学习中的代码,还没来得及重构(其实是懒),需要的人自行使用,代码最初均来源于网络,后面自己修改

irg3_python.h



#ifndef _IRG3_PYTHON_H_
#define _IRG3_PYTHON_H_
#include <Python.h>
#include<unordered_map>
#include <string>


/*
Py_BuildValue使用举例:

Py_BuildValue("")  None
Py_BuildValue("i", 123)  123
Py_BuildValue("iii", 123, 456, 789)  (123, 456, 789)
Py_BuildValue("s", "hi")  'hi'
Py_BuildValue("ss", "hello", "world")  ('hello', 'world')
Py_BuildValue("s#", "hello", 4) 'hell'
Py_BuildValue("()")  ()
Py_BuildValue("(i)", 123)  (123,)
Py_BuildValue("(ii)", 123, 456) (123, 456)
Py_BuildValue("(i,i)", 123, 456) (123, 456)
Py_BuildValue("[i,i]", 123, 456) [123, 456] 
Py_BuildValue("{s:i,s:i}", "abc", 123, "def", 456) {'abc': 123, 'def': 456}
Py_BuildValue("((ii)(ii)) (ii)", 1, 2, 3, 4, 5, 6) (((1, 2), (3, 4)), (5, 6))
*/

/*
常用的几个解析参数与C类型的对应关系:

s:char*
b:unsigned char
c:char
d:double
f:float
h:short int
i:int
l:long
k:unsigned long
L:long long
K:unsigned long long
*/


class Irg3_Py_Script {
private:
	Irg3_Py_Script() {}
public:

	struct py_node {
		std::string path_;	//文件所在路径
		std::string file_;	//文件名(无后缀)
		std::string class_n;	//类名
		std::vector<std::pair<std::string, void*> >cla_vecs_;	//类传递参数
		std::string method_;	//方法名
		std::vector<std::pair<std::string, void *> >met_vecs_;	//方法参数
		std::vector<std::string> ret_vecs_;	//返回值

	};

	virtual ~Irg3_Py_Script() {}
	static Irg3_Py_Script* getInstance() {
		static Irg3_Py_Script cus_;
		return &cus_;
	}
public:
	//python要求,传入位任意字符串参数,无返回
	bool excute(py_node& node_);
	//python要求,传入位任意字符串参数,返回为字符串列表
	bool excute_list(py_node& node_);
	//传入任意参数,返回为字典类型
	bool excute_direct(py_node& node_, std::unordered_map<std::string, std::string>* map_ = nullptr);
	//python要求,传入位任意字符串参数,返回为元组(s+i)
	int excute_s_i(py_node& node_, char* buf_);
	//python要求,传入位s+i,返回为元组(s+i)
	int excute_s_i(py_node& node_, const char* msg_, int msg_len_, char* buf_);
	

private:
	void create_args(PyObject* cla_args, std::vector<std::pair<std::string, void*> >& vecs_);
};


#endif





irg3_python.cpp

#include "irg3_python.h"
#include <jni.h>



bool Irg3_Py_Script::excute(Irg3_Py_Script::py_node& node_)
{
	Py_Initialize();
	//2、初始化python系统文件路径,保证可以访问到 .py文件
	PyRun_SimpleString("import sys");
	std::string val_;
	val_.assign("sys.path.append('").append(node_.path_.c_str()).append("')");
	PyRun_SimpleString(val_.c_str());
	{
		PyObject* pFunc = NULL;
		PyObject* pObject = NULL;

		pObject = PyImport_ImportModule(node_.file_.c_str());               //注意文件名字大小写

		//获取类名
		if (node_.class_n != "") {
			pObject = PyObject_GetAttrString(pObject, node_.class_n.c_str());     //先获取类名
			// 定义变量 
			PyObject* cla_args = PyTuple_New(node_.cla_vecs_.size());
			create_args(cla_args, node_.cla_vecs_);
			pObject = PyEval_CallObject(pObject, cla_args);              //根据类名实例化对象
		}
		//获取函数
		pFunc = PyObject_GetAttrString(pObject, node_.method_.c_str());

		PyObject* met_args = PyTuple_New(node_.met_vecs_.size());
		create_args(met_args, node_.met_vecs_);
		//函数调用
		PyObject* pyValue = PyEval_CallObject(pFunc, met_args);
	}
	Py_Finalize();
	return true;
}

bool Irg3_Py_Script::excute_list(Irg3_Py_Script::py_node&node_)
{
	Py_Initialize();
	bool flag_ = false;
	//2、初始化python系统文件路径,保证可以访问到 .py文件
	PyRun_SimpleString("import sys");
	std::string val_;
	val_.assign("sys.path.append('").append(node_.path_.c_str()).append("')");
	PyRun_SimpleString(val_.c_str());
	{
		PyObject* pFunc = NULL;
		PyObject* pObject = NULL;

		pObject = PyImport_ImportModule(node_.file_.c_str());               //注意文件名字大小写

		//获取类名
		if (node_.class_n != "") {
			pObject = PyObject_GetAttrString(pObject, node_.class_n.c_str());     //先获取类名
			// 定义变量 
			PyObject* cla_args = PyTuple_New(node_.cla_vecs_.size());
			create_args(cla_args, node_.cla_vecs_);
			pObject = PyEval_CallObject(pObject, cla_args);              //根据类名实例化对象
		}
		//获取函数
		pFunc = PyObject_GetAttrString(pObject, node_.method_.c_str()); 

		PyObject* met_args = PyTuple_New(node_.met_vecs_.size());
		create_args(met_args, node_.met_vecs_);
		//函数调用
		PyObject* pyValue = PyEval_CallObject(pFunc, met_args);
		//获取结果
		if (pyValue&& PyList_Check(pyValue)){
			for (Py_ssize_t i = 0; i < PyList_Size(pyValue); ++i) {
				char* p = nullptr;
				PyObject* next = PyList_GetItem(pyValue, i);
				PyArg_Parse(next, "s", &p);
				if(p!=nullptr)
					node_.ret_vecs_.push_back(p);
			}
			flag_ = true;
		}
	}
	Py_Finalize();
	return flag_;

}

int Irg3_Py_Script::excute_s_i(Irg3_Py_Script::py_node&node_,char*buf_)
{
	Py_Initialize();
	//2、初始化python系统文件路径,保证可以访问到 .py文件
	PyRun_SimpleString("import sys");
	std::string val_;
	val_.assign("sys.path.append('").append(node_.path_.c_str()).append("')");
	PyRun_SimpleString(val_.c_str());
	{
		PyObject* pFunc = NULL;
		PyObject* pObject = NULL;

		pObject = PyImport_ImportModule(node_.file_.c_str());               //注意文件名字大小写

		//获取类名
		if (node_.class_n != "") {
			pObject = PyObject_GetAttrString(pObject, node_.class_n.c_str());     //先获取类名
			// 定义变量 
			PyObject* cla_args = PyTuple_New(node_.cla_vecs_.size());
			create_args(cla_args, node_.cla_vecs_);
			pObject = PyEval_CallObject(pObject, cla_args);              //根据类名实例化对象
		}
		//获取函数
		pFunc = PyObject_GetAttrString(pObject, node_.method_.c_str());
		//构建参数
		PyObject* met_args = PyTuple_New(node_.met_vecs_.size());
		create_args(met_args, node_.met_vecs_);
		//函数调用
		PyObject* pyValue = PyEval_CallObject(pFunc, met_args);
		
		//获取结果
		if (pyValue) {
			char* val_str_;
			int val_len_;
			PyArg_ParseTuple(pyValue, "(s,i)", &val_str_, &val_len_);
			if (val_str_ == nullptr) {
				return -1;
			}
			memcpy(val_str_, buf_, val_len_);
			return val_len_;
		}
	}
	Py_Finalize();
	return -1;
}

int Irg3_Py_Script::excute_s_i(Irg3_Py_Script::py_node&node_, const char* msg_, int msg_len_, char* buf_)
{
	int ret_val_ = -1;
	Py_Initialize();
	//2、初始化python系统文件路径,保证可以访问到 .py文件
	PyRun_SimpleString("import sys");
	std::string val_;
	val_.assign("sys.path.append('").append(node_.path_.c_str()).append("')");
	PyRun_SimpleString(val_.c_str());
	do{
		PyObject* pFunc = NULL;
		PyObject* pObject = NULL;

		pObject = PyImport_ImportModule(node_.file_.c_str());               //注意文件名字大小写

		//获取函数
		pFunc = PyObject_GetAttrString(pObject, node_.method_.c_str());

		PyObject* met_args = PyTuple_New(2);
		PyTuple_SetItem(met_args, 0, Py_BuildValue("s", msg_));
		PyTuple_SetItem(met_args, 1, Py_BuildValue("i", msg_len_));
		//函数调用
		PyObject* pyValue = PyEval_CallObject(pFunc, met_args);

		//获取结果
		if (pyValue) {
			char* val_str_;
			PyArg_ParseTuple(pyValue, "si", &val_str_, &ret_val_);
			if (val_str_ == nullptr) {
				break;
			}
			memcpy(buf_, val_str_, ret_val_);
		}
	} while (false);
	Py_Finalize();
	return ret_val_;
}

void Irg3_Py_Script::create_args(PyObject* args_, std::vector<std::pair<std::string, void*> >&vecs_)
{
	for (int i = 0; i < vecs_.size(); i++) {
		auto& p = vecs_.at(i);
		if (p.first[0] == 'i') {
			//int整形
			PyTuple_SetItem(args_, i, Py_BuildValue(p.first.c_str(), *((int*)p.second)));
		}
		else if (p.first[0] == 's') {
			//std::string字符串
			PyTuple_SetItem(args_, i, Py_BuildValue(p.first.c_str(), (char*)p.second));
		}
		else if (p.first[0] == 'd') {
			//double浮点型
			PyTuple_SetItem(args_, i, Py_BuildValue(p.first.c_str(), *((double*)p.second)));
		}
		else if (p.first[0] == 'l') {
			//std::vector<std::string>字符串列表
			PyObject* pyParams = PyList_New(0);           //初始化一个列表
			std::vector<std::string>* val_ = (std::vector<std::string> *)p.second;
			for (auto& t : *val_) {
				PyList_Append(pyParams, Py_BuildValue("s", t.c_str()));
			}
			PyTuple_SetItem(args_, 0, pyParams);// 变量格式转换成python格式
		}
		
	}
}

bool Irg3_Py_Script::excute_direct(Irg3_Py_Script::py_node& node_, std::unordered_map<std::string, std::string>*map_) {
	bool ret_flag = false;
	Py_Initialize();
	//2、初始化python系统文件路径,保证可以访问到 .py文件
	PyRun_SimpleString("import sys");
	std::string val_;
	val_.assign("sys.path.append('").append(node_.path_.c_str()).append("')");
	PyRun_SimpleString(val_.c_str());
	do {
		PyObject* pFunc = NULL;
		PyObject* pObject = NULL;

		pObject = PyImport_ImportModule(node_.file_.c_str());               //注意文件名字大小写
		if (pObject == nullptr) {
			break;
		}
		//获取函数
		pFunc = PyObject_GetAttrString(pObject, node_.method_.c_str());
		if (pFunc == nullptr) {
			break;
		}
		PyObject* met_args = PyTuple_New(node_.met_vecs_.size());
		create_args(met_args, node_.met_vecs_);


		//函数调用
		PyObject* pyValue = PyEval_CallObject(pFunc, met_args);

		//获取结果
		if (pyValue) {

			PyObject* items = PyMapping_Items(pyValue);
			if (items == nullptr) {
				break;
			}
			PyObject* item = nullptr;
			int len = PyMapping_Length(items);
			const char* key;
			const char* val;
			for (int i = 0; i < len; i++) {
				item = PySequence_GetItem(items, i);
				PyArg_ParseTuple(item, "ss", &key, &val);
				if (map_ != nullptr) {
					(*map_)[key] = val;
				}
				Py_DECREF(item);
			}
			Py_DECREF(items);
			ret_flag = true;
		}
	} while (false);
	Py_Finalize();
	return ret_flag;
}

main.cpp


#include"irg3_python.h"

// 测试
int main(int argc, char* argv[]) {
    Irg3_Py_Script::py_node node;
    node.file_ = "1";
    node.path_ = "d:/test_2";
    node.method_ = "method";
    char buf[] = "hello";
    node.met_vecs_.push_back({ "s",buf });
    Irg3_Py_Script::getInstance()->excute(node);
    return 0;
}

1.py



def method(name):
    print(name)

附录

PyArg_ParseTuple与Py_BuildValue常用的几个解析参数与C类型的对应关系

s:char*
b:unsigned char
c:char
d:double
f:float
h:short int
i:int
l:long
k:unsigned long
L:long long
K:unsigned long long

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值