C++调用 Python
采用Python脚本解释器进行脚本编译及脚本解释执行,而MT中主要采用C++编写,C++需要import py_compile模块进行脚本编译。
C++调用Python的实例如下:
/* * test.cpp * Created on: 2010-12-12 * Author: Handy_Zhou */ #include <python2.6/Python.h> #include <iostream> #include <string> void printDict(PyObject* obj) { if (!PyDict_Check(obj)) return; PyObject *k, *keys; keys = PyDict_Keys(obj); for (int i = 0; i < PyList_GET_SIZE(keys); i++) { k = PyList_GET_ITEM(keys, i); char* c_name = PyString_AsString(k); printf("%s\n", c_name); } } int main() { Py_Initialize(); if (!Py_IsInitialized()) return -1; PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append('./')"); //导入模块 PyObject* pModule = PyImport_ImportModule("testpy"); if (!pModule) { printf("Cant open python file!\n"); return -1; } //模块的字典列表 PyObject* pDict = PyModule_GetDict(pModule); if (!pDict) { printf("Cant find dictionary.\n"); return -1; } //打印出来看一下 printDict(pDict); //演示函数调用 PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi"); PyObject_CallFunction(pFunHi, "s", "lhb"); Py_DECREF(pFunHi); //演示构造一个Python对象,并调用Class的方法 //获取Second类 PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second"); if (!pClassSecond) { printf("Cant find second class.\n"); return -1; } //获取Person类 PyObject* pClassPerson = PyDict_GetItemString(pDict, "Person"); if (!pClassPerson) { printf("Cant find person class.\n"); return -1; } //构造Second的实例 PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL); if (!pInstanceSecond) { printf("Cant create second instance.\n"); return -1; } //构造Person的实例 PyObject* pInstancePerson = PyInstance_New(pClassPerson, NULL, NULL); if (!pInstancePerson) { printf("Cant find person instance.\n"); return -1; } //把person实例传入second的invoke方法 PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson); //释放 Py_DECREF(pInstanceSecond); Py_DECREF(pInstancePerson); Py_DECREF(pClassSecond); Py_DECREF(pClassPerson); Py_DECREF(pModule); Py_Finalize(); return 0; }
Python 源码
#!/usr/bin/python # Filename: test.py class Person: def sayHi(self): print 'hi' class Second: def invoke(self,obj): obj.sayHi() def sayhi(name): 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/
Extending and Embedding
Python/C API
比较特殊的是调用Python函数时,参数的传递,就是c++的类型,怎么转换成Python的类型;另外一个问题是,Python函数的返回值,怎么转换成C++中的类型。
C++转换成Python类型,Py_BuildValue()
http://www.python.org/doc/1.5.2p2/ext/buildValue.html
PyObject* pArgs=PyTuple_New( 1 ); //有几个参数,就是几
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://hi.baidu.com/zhouhanqing/blog/item/75b6134f2bddd91cb2de051a.html