一、环境配置
开发工具: VS2015、python 3.7 64位
系统:windows 64位
下载和安装64位 python3.7 https://www.python.org/ftp/python/3.7.4/python-3.7.4-amd64.exe
我的是安装到了“E:\workspace\pythonLibX64\ ” 如下图:
VS2015属性页配置如下,包含目录“E:\workspace\pythonLibX64\include”,库目录“E:\workspace\pythonLibX64\libs”。链接器>>输入>>附加依赖项中添加 “python37.lib”:
二、代码
python:文件名 hello.py
def HelloWorld():
print("py_print>>Hello world!")
return "return>>Hello world!"
def Add(a,b):
print("py_print>> run {} + {}".format(a,b))
return a+b
def TestDict(input_dict):
print("py_print>>input: {}".format(input_dict))
input_dict['Age']=100
return input_dict
class Person(object):
name="chaoen hu"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def greet(self, you):
print("py_print>> 我是 {}, 欢迎 {} 来到CASMI.".format(self.name, you))
C++ 文件名 main.cpp
注意
1) 使用QT时#include "python.h" 请放在其它#include "Q*.h"之前,目的是为了防止命名冲突。
2) 把Python安装目录下的python37.dll 复制到本工程生成的exe 目录下。
/*
1) 初始化Python调用环境
2) 加载对应的Python模块
3) 加载对应的Python函数
4) 将参数转化为Python元组类型
5) 调用Python函数并传入参数元组
6) 获取返回值
7) 根据Python函数的定义解析返回值
*/
#include "python.h"
#include <iostream>
// Python安装目录
#define Py_Home L"E:/workspace/pythonLibX64"
// python 工作空间(你的Python文件所在目录)
#define Pysys_Path "sys.path.append('E:/workspace/pyDLL/')"
#define Py_ErrorAndExit(X) printf(X); PyErr_Print(); return -1;
int HelloWorld(PyObject *pmodule);
int Add(PyObject *pmodule, int a, int b);
int TestTransferDict(PyObject *pmodule, char *name, int age);
int TestClass(PyObject *pmodule);
int main()
{
/*>>>>>1) 初始化Python调用环境<<<<<<<<<*/
Py_SetPythonHome(Py_Home);
Py_Initialize();
if (!Py_IsInitialized()) {
Py_ErrorAndExit("初始化失败");
}
// python 工作空间(你的Python文件所在目录)
PyRun_SimpleString("import sys");
// PyRun_SimpleString 函数执行Python命令
PyRun_SimpleString(Pysys_Path);
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<*/
/*>>>>>2) 加载对应的Python模块<<<<<<<<<*/
// 导入hello.py模块
PyObject *pmodule = PyImport_ImportModule("hello");
if (!pmodule)
{
Py_ErrorAndExit("加载模型失败");
}
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<*/
std::cout << "/______测试调用HelloWorld______/" << std::endl;
HelloWorld(pmodule);
std::cout << "/____________________________/" << std::endl;
std::cout << std::endl;
std::cout << "/______测试调用ADD__5 + 7______/" << std::endl;
Add(pmodule,5,7);
std::cout << "/____________________________/" << std::endl;
std::cout << std::endl;
std::cout << "/______测试调用TestDict______/" << std::endl;
TestTransferDict(pmodule, "casmi", 18);
std::cout << "/____________________________/" << std::endl;
std::cout << std::endl;
std::cout << "/______测试调用TestClass______/" << std::endl;
TestClass(pmodule);
std::cout << "/____________________________/" << std::endl;
std::cout << std::endl;
/*>>>>>>>>> 结束和释放<<<<<<<<<*/
Py_DECREF(pmodule);
Py_Finalize();
system("pause");
return 0;
}
int HelloWorld(PyObject *pmodule)
{
// 3) 加载对应的Python函数
PyObject * pFunc_HelloWorld = NULL;
pFunc_HelloWorld = PyObject_GetAttrString(pmodule, "HelloWorld");
if (!pFunc_HelloWorld)
{
Py_ErrorAndExit("加载HelloWorld函数失败");
}
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<*/
// 5) 调用函数 6) 获取返回值
PyObject *pReturn = NULL;
pReturn = PyEval_CallObject(pFunc_HelloWorld, NULL);
if (!pReturn)
{
Py_ErrorAndExit("获取返回值失败");
}
// 可以释放函数
Py_DECREF(pFunc_HelloWorld);
// 7) 根据Python函数的定义解析返回值
char *result = "";
PyArg_Parse(pReturn, "s", &result);
Py_DECREF(pReturn); // 释放
std::cout << "C 函数获取的返回值: ";
std::cout << result << std::endl;
}
int Add(PyObject *pmodule,int a,int b)
{
// 3) 加载对应的Python函数
PyObject * pFunc = NULL;
pFunc = PyObject_GetAttrString(pmodule, "Add");
if (!pFunc)
{
Py_ErrorAndExit("加载Add函数失败");
}
//4) 创建2个参数:将参数转化为Python元组类型
PyObject *pArgs = PyTuple_New(2);
//0---序号 "i" 表示创建int型变量, a 参数值
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", a));
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", b));
// 5) 调用函数 6) 获取返回值
PyObject *pReturn = NULL;
pReturn = PyEval_CallObject(pFunc, pArgs);
Py_DECREF(pFunc);// 释放
Py_DECREF(pArgs);// 释放
//将返回值转换为int类型
int result;
PyArg_Parse(pReturn, "i", &result); //i表示转换成int型变量
Py_DECREF(pReturn);// 释放
std::cout << "C 函数获取的返回值: ";
std::cout << result << std::endl;
}
int TestTransferDict(PyObject *pmodule,char*name,int age)
{
PyObject * pFunc = PyObject_GetAttrString(pmodule, "TestDict");
if (!pFunc)
{
Py_ErrorAndExit("加载TestDict函数失败");
}
// 创建字典类型变量
PyObject *pDict = PyDict_New();
PyDict_SetItemString(pDict, "Name", Py_BuildValue("s", name)); //往字典类型变量中填充数据
PyDict_SetItemString(pDict, "Age", Py_BuildValue("i", age)); //往字典类型变量中填充数据
// 把要输入的字典转为元组参数
PyObject *pArgs = PyTuple_New(1); // 输入为1个字典
PyTuple_SetItem(pArgs, 0, pDict); //0---序号 将字典类型变量添加到参数元组中
// 调用函数
PyObject *pReturn = NULL;
pReturn = PyEval_CallObject(pFunc, pArgs);
Py_DECREF(pFunc);// 释放
Py_DECREF(pArgs);
// 处理返回值
char *newName = "";
int newAge = 0;
int size = PyDict_Size(pReturn);
std::cout << "返回字典的大小为: " << size << std::endl;
/*PyObject *pReturn_keys = PyDict_Keys(pReturn);
for (int i = 0;i < size;++i)
{
PyObject *key = PyList_GetItem(pReturn_keys, i);
PyObject *value = PyDict_GetItem(pReturn, key);
}*/
// 推荐这种方式
PyObject *key = 0;
PyObject *value = 0;
key = Py_BuildValue("s", "Name");
if (PyDict_Contains(pReturn, key))
{
value = PyDict_GetItem(pReturn, key);
PyArg_Parse(value, "s", &newName);
}
key = Py_BuildValue("s", "Age");
if (PyDict_Contains(pReturn, key))
{
value = PyDict_GetItem(pReturn, key);
PyArg_Parse(value, "i", &newAge);
}
// 也可以使用这种方式
//PyObject *pNewName = PyDict_GetItemString(pReturn, "Name");
//PyObject *pNewAge = PyDict_GetItemString(pReturn, "Age");
//PyArg_Parse(pNewName, "s", &newName);
//PyArg_Parse(pNewAge, "i", &newAge);
Py_DECREF(pReturn);// 释放
std::cout << "C 函数获取的返回值: ";
std::cout << "{Name: " << newName <<", Age: "<< newAge <<" }"<< std::endl;
// 结束
}
int TestClass(PyObject *pmodule)
{
PyObject * pClass = NULL, *pDict = NULL;
//获取模块字典属性
pDict = PyModule_GetDict(pmodule);
// 通过字典属性获取模块中的类
pClass = PyDict_GetItemString(pDict, "Person");
Py_DECREF(pDict);
if (!pClass)
{
Py_ErrorAndExit("获取模块中的类失败");
}
// 实例化获取的类
PyObject *pInstance = PyInstanceMethod_New(pClass);
if (!pInstance)
{
Py_ErrorAndExit("");
}
//调用类的方法
PyObject *result = PyObject_CallMethod(pInstance, "greet", "(O, s)", pInstance, "hao hao");
if (!result)
{
Py_ErrorAndExit("");
}
Py_DECREF(pClass);
Py_DECREF(pInstance);
Py_DECREF(result);
}
三、运行结果
/______测试调用HelloWorld______/
py_print>>Hello world!
C 函数获取的返回值: return>>Hello world!
/____________________________/
/______测试调用ADD__5 + 7______/
py_print>> run 5 + 7
C 函数获取的返回值: 12
/____________________________/
/______测试调用TestDict______/
py_print>>input: {'Name': 'casmi', 'Age': 18}
返回字典的大小为: 2
C 函数获取的返回值: {Name: casmi, Age: 100 }
/____________________________/
/______测试调用TestClass______/
py_print>> 我是 chaoen hu, 欢迎 hao hao 来到CASMI.
/____________________________/
请按任意键继续. . .