C++调用Python方法

时间:2022-09-20 19:28:27

C++调用Python方法


文章来源:
1.http://blog.csdn.net/feitianxuxue/article/details/41129677
2.http://blog.csdn.net/c_cyoxi/article/details/23978007
3.http://blog.csdn.net/magictong/article/details/8947892

Python/CAPI简介

通过C++调用Python脚本,主要利用Python提供的API,实际上,C++主要调用的是Python的解释器,而Python的解释器本质就是实现在动态链接库里的,因此在调用前后要进行一些初始化和资源释放的工作,另外,要调用Python脚本里的函数等等,需要使用Python提供的一些特殊的API来包装C++调用。

(1) 初始化Python解释器,若初始化失败,继续调用会出现各种错误

void Py_Initialize(void)

(2) 检查Python解释器是否初始化,返回0表示没有经过初始化

int Py_IsInitialized(void)

(3) 反初始化解释器,包括子解释器,同时释放Python解释器占用的资源

void Py_Finalize()

(4) 实际上是一个宏,执行Python代码

int PyRun_SimpleString(const char *command)

(5) 导入一个模块,name是Python文件的文件名,不带.py,类似于Python内建的import

PyObject* PyImport_ImportModule(char *name)

(6) 相当于Python模块对象的dict属性,得到模块名称空间下的字典对象

PyObject* PyModule_GetDict( PyObject *module)

(7) 执行一段Python代码

PyObject* PyRun_String(const char* str, int start,PyObject* globals, PyObject* locals)

(8) 把Python数据类型转换为C的类型

int PyArg_Parse(PyObject* args, char* format, ...)

(9) 返回模块对象o的attr_name属性或函数,相当于Python中的表达式o.attr_name

PyObject* PyObject_GetAttrString(PyObject *o, char*attr_name)

(10) 构建一个参数列表,将C类型转换为Python对象

PyObject* Py_BuildValue(char* format, ...)

(11) 调用Python函数,两个参数都是Python对象指针,pfunc是要调用的Python函数,一般来说,可以用过PyObject_GetAttrString()获得,pargs是函数的参数列表,通常是Py_BuildValue()来构建的

PyObject* PyEval_CallObject(PyObject* pfunc, PyObject*pargs)

错误分析

编译若出现unresolved external symbol _Py_Initialize referenced in function "void __cdecl test(void)" (?test@@YAXXZ)等错误,可能是工程的platform和Python有着不同bit,将工程转换为32位或者64位与Python一致即可

Python的C模块不支持Debug模式,所以Debug下编译会出现找不到pythonxx_d.lib的错误,需要修改Python头文件pyconfig.h的配置,将Debug库文件换成pythonxx.lib即可
即将

    # ifdef _DEBUG
# pragma comment(lib,"python27_d.lib")
# else
# pragma comment(lib,"python27.lib")

修改为:

    # ifdef _DEBUG
# pragma comment(lib,"python27.lib")
# else
# pragma comment(lib,"python27.lib")

代码示例:

#include <Python.h>
#pragma comment(lib,"python27.lib")
using namespace std;
void getCurrent()
{
PyRun_SimpleString("import sys");
//对于模块和程序不在同一个目录下,执行该Python语句将模块路径加进程序
PyRun_SimpleString("sys.path.append('./Python')");
return;
}
void test()
{
//执行Python语句
Py_Initialize();
PyRun_SimpleString("print 'Hello Python'");
Py_Finalize();
return ;
}
void test2()
{
//调用函数,传入参数,无返回值
Py_Initialize();
getCurrent();
PyObject *pModule = NULL;
PyObject *pFunc = NULL;
PyObject *pArgs = NULL;
pModule = PyImport_ImportModule("pyTest");//引用模块
pFunc = PyObject_GetAttrString(pModule,"print_arg");//取出模块中的函数
pArgs = Py_BuildValue("(s)","Hello_Python");//对要传给函数的参数做类型转换
PyEval_CallObject(pFunc,pArgs);//调用函数并传递参数
Py_Finalize();
return;
}
void test3()
{
//调用函数,传递参数并接受返回值
Py_Initialize();
getCurrent();
int sum = 0;
PyObject *pModule = NULL;
PyObject *pFunc = NULL;
PyObject *pArgs = NULL;
PyObject *pResult = NULL;
pModule = PyImport_ImportModule("pyTest");//引用模块
pFunc = PyObject_GetAttrString(pModule,"add");//取出模块中的函数
pArgs = Py_BuildValue("(i,i)",3,5);//对要传给函数的参数做类型转换
pResult = PyEval_CallObject(pFunc,pArgs);//调用该函数并接受返回值
PyArg_Parse(pResult,"i",&sum);//将返回值转换为C/C++类型
Py_Finalize();
cout<<sum<<endl;
}
void test4()
{
//调用类,并接受单个返回值
Py_Initialize();
getCurrent();
char *name = NULL;
PyObject *pModule = NULL;
PyObject *pDict = NULL;
PyObject *pClass = NULL;
PyObject *pInstance = NULL;
PyObject *pResult = NULL;
pModule = PyImport_ImportModule("pyTest");//引用模块
pDict = PyModule_GetDict(pModule);//获取模块字典属性
pClass = PyDict_GetItemString(pDict,"pyTest");//通过字典属性获取模块中的类
pInstance = PyInstance_New(pClass,NULL,NULL);//实例化获取的类
//调用类的fun方法,并传入参数Sherlock
pResult = PyObject_CallMethod(pInstance,"fun","(s)","Sherlock");
PyArg_Parse(pResult,"s",&name);
cout<<name<<endl;
Py_Finalize();
}
void test5()
{
//调用类,返回值是json
Py_Initialize();
if (!Py_IsInitialized())
{
cout<<"Init fail."<<endl;
return;
}
getCurrent();
char *name = NULL;
int age = 0;
PyObject *pModule = NULL;
PyObject *pDict = NULL;
PyObject *pClass = NULL;
PyObject *pInstance = NULL;
PyObject *pResult = NULL;
PyObject *obj_content = NULL;
PyObject *obj_flag = NULL;
pModule = PyImport_ImportModule("pyTest");//引用模块
pDict = PyModule_GetDict(pModule);//获取模块字典属性
pClass = PyDict_GetItemString(pDict,"pyTest");//通过字典属性获取模块中的类
pInstance = PyInstance_New(pClass,NULL,NULL);//实例化获取的类
//调用类方法fun,并传入两个参数,注意参数类型,并获取返回值
pResult = PyObject_CallMethod(pInstance,"fun","(s,i)","Sherlock",100);
obj_content = PyDict_GetItemString(pResult,"name");/取出返回值key为name的value
name = PyString_AsString(obj_content);//将类型转换为C/C++类型
obj_flag = PyDict_GetItemString(pResult,"age");
age = PyInt_AsLong(obj_flag);
cout<<name<<endl;
cout<<age<<endl;
Py_Finalize();
}
int _tmain(int argc, _TCHAR* argv[])
{
//test();//直接执行Python语句
//test2();//调用函数并传入参数
//test3();//调用函数,传递参数并接受返回值
//test4();//调用类,并接受单个返回值
test5();//调用类,返回值是json
return 0;
}