C++调用Python方法

来源:互联网 发布:c 构造函数编程例子 编辑:程序博客网 时间:2024/06/07 11:00

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;}
0 0
原创粉丝点击