C++调用Python方法

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值