C++调用Python(3)

本文详细介绍了一种通过C++来调用Python脚本的方法,包括初始化Python解释器、导入Python模块、创建Python对象及调用其方法等关键步骤。

    前两篇都是介绍Python调用C++的,换句话说,就是需要把C++封装成Python可以“理解”的类型。这篇,我打算说一下,C++怎么去调用Python脚本。其实这两者之间是相通的,就是需要可以互操作。按照惯例,先贴代码。
test.cpp

[cpp]  view plain copy
  1. /* 
  2.  * test.cpp 
  3.  *  Created on: 2010-8-12 
  4.  *      Author: lihaibo 
  5.  */  
  6. #include <python2.6/Python.h>  
  7. #include <iostream>  
  8. #include <string>  
  9. void printDict(PyObject* obj) {  
  10.     if (!PyDict_Check(obj))  
  11.         return;  
  12.     PyObject *k, *keys;  
  13.     keys = PyDict_Keys(obj);  
  14.     for (int i = 0; i < PyList_GET_SIZE(keys); i++) {  
  15.         k = PyList_GET_ITEM(keys, i);  
  16.         char* c_name = PyString_AsString(k);  
  17.         printf("%s/n", c_name);  
  18.     }  
  19. }  
  20. int main() {  
  21.     Py_Initialize();  
  22.     if (!Py_IsInitialized())  
  23.         return -1;  
  24.     PyRun_SimpleString("import sys");  
  25.     PyRun_SimpleString("sys.path.append('./')");  
  26.     //导入模块  
  27.     PyObject* pModule = PyImport_ImportModule("testpy");  
  28.     if (!pModule) {  
  29.         printf("Cant open python file!/n");  
  30.         return -1;  
  31.     }  
  32.     //模块的字典列表  
  33.     PyObject* pDict = PyModule_GetDict(pModule);  
  34.     if (!pDict) {  
  35.         printf("Cant find dictionary./n");  
  36.         return -1;  
  37.     }  
  38.     //打印出来看一下  
  39.     printDict(pDict);  
  40.     //演示函数调用  
  41.     PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi");  
  42.     PyObject_CallFunction(pFunHi, "s""lhb");  
  43.     Py_DECREF(pFunHi);  
  44.     //演示构造一个Python对象,并调用Class的方法  
  45.     //获取Second类  
  46.     PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second");  
  47.     if (!pClassSecond) {  
  48.         printf("Cant find second class./n");  
  49.         return -1;  
  50.     }  
  51.     //获取Person类  
  52.     PyObject* pClassPerson = PyDict_GetItemString(pDict, "Person");  
  53.     if (!pClassPerson) {  
  54.         printf("Cant find person class./n");  
  55.         return -1;  
  56.     }  
  57.     //构造Second的实例  
  58.     PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL);  
  59.     if (!pInstanceSecond) {  
  60.         printf("Cant create second instance./n");  
  61.         return -1;  
  62.     }  
  63.     //构造Person的实例  
  64.     PyObject* pInstancePerson = PyInstance_New(pClassPerson, NULL, NULL);  
  65.     if (!pInstancePerson) {  
  66.         printf("Cant find person instance./n");  
  67.         return -1;  
  68.     }  
  69.     //把person实例传入second的invoke方法  
  70.     PyObject_CallMethod(pInstanceSecond, "invoke""O", pInstancePerson);  
  71.     //释放  
  72.     Py_DECREF(pInstanceSecond);  
  73.     Py_DECREF(pInstancePerson);  
  74.     Py_DECREF(pClassSecond);  
  75.     Py_DECREF(pClassPerson);  
  76.     Py_DECREF(pModule);  
  77.     Py_Finalize();  
  78.     return 0;  
  79. }  

编译

g++ test.cpp -o test -lpython2.6

 

testpy.py

[python]  view plain copy
  1. #!/usr/bin/python  
  2. # Filename: test.py  
  3. class Person:  
  4.     def sayHi(self):  
  5.         print 'hi'  
  6. class Second:  
  7.     def invoke(self,obj):  
  8.         obj.sayHi()  
  9. def sayhi(name):  
  10.     print 'hi',name;  

执行

lhb@localhost:~/maplib/clib/pyc/invokepy$ ./test 
sayhi
__builtins__
__file__
__package__
Person
Second
__name__
__doc__
hi lhb
hi

我简单解释一下

  • 这个例子演示了,创建python中Person类的实例,并作为参数调用Second的方法。
  • Py_Initialize()和 Py_Finalize()是初始和销毁Python解释器
  • PyRun_SimpleString( "import sys" )导入sys,接着设置py文件的路径PyRun_SimpleString("sys.path.append('./')" )
  • 导入模块PyImport_ImportModule( "testpy" ),就是testpy.py模块。
  • 获取模块字典列表,PyModule_GetDict(pModule),可以打印出来看一下如 void  printDict(PyObject* obj)函数
  • 从字典中获取类的类型 PyDict_GetItemString(pDict, "Second" ),如函数也是这样获取的
  • 创造类的实例 PyInstance_New(pClassSecond,NULL,NULL)
  • 调用实例的方法PyObject_CallMethod(pInstanceSecond, "invoke" , "O" ,pInstancePerson)

整个流程就是这样的,并不复杂,如果要进一步研究可以参考:http://www.python.org/doc/

比较特殊的是调用Python函数时,参数的传递,就是c++的类型,怎么转换成Python的类型;另外一个问题是,Python函数的返回值,怎么转换成C++中的类型。
C++转换成Python类型,Py_BuildValue()
http://www.python.org/doc/1.5.2p2/ext/buildValue.html

  1. PyObject* pArgs=PyTuple_New( 1 ); //有几个参数,就是几
  2. PyTuple_SetItem(pArgs, 0 ,Py_BuildValue( "i" , 3 ));  //初始第一个参数,数据类型是i,就是int,值是 3

返回值转换如,PyArg_ParseTuple,请参考
http://www.python.org/doc/1.5.2p2/ext/parseTuple.html


转自:http://blog.youkuaiyun.com/marising/article/details/2917892

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值