前兩篇都是介紹Python調(diào)用C++的,換句話說,就是需要把C++封裝成Python可以“理解”的類型。這篇,我打算說一下,C++怎么去調(diào)用Python腳本。其實(shí)這兩者之間是相通的,就是需要可以互操作。按照慣例,先貼代碼。 test.cpp view plain /* * test.cpp * Created on: 2010-8-12 * Author: lihaibo */ #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('./')"); //導(dǎo)入模塊 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); //演示函數(shù)調(diào)用 PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi"); PyObject_CallFunction(pFunHi, "s", "lhb"); Py_DECREF(pFunHi); //演示構(gòu)造一個Python對象,并調(diào)用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; } //構(gòu)造Second的實(shí)例 PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL); if (!pInstanceSecond) { printf("Cant create second instance./n"); return -1; } //構(gòu)造Person的實(shí)例 PyObject* pInstancePerson = PyInstance_New(pClassPerson, NULL, NULL); if (!pInstancePerson) { printf("Cant find person instance./n"); return -1; } //把person實(shí)例傳入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; } 編譯 g++ test.cpp -o test -lpython2.6 testpy.py view plain #!/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; 執(zhí)行 lhb@localhost:~/maplib/clib/pyc/invokepy$ ./test sayhi __builtins__ __file__ __package__ Person Second __name__ __doc__ hi lhb hi 我簡單解釋一下 這個例子演示了,創(chuàng)建python中Person類的實(shí)例,并作為參數(shù)調(diào)用Second的方法。 Py_Initialize()和 Py_Finalize()是初始和銷毀Python解釋器 PyRun_SimpleString( "import sys" )導(dǎo)入sys,接著設(shè)置py文件的路徑PyRun_SimpleString( "sys.path.append('./')" ) 導(dǎo)入模塊PyImport_ImportModule( "testpy" ),就是testpy.py模塊。 獲取模塊字典列表,PyModule_GetDict(pModule),可以打印出來看一下如 void printDict(PyObject* obj)函數(shù) 從字典中獲取類的類型 PyDict_GetItemString(pDict, "Second" ),如函數(shù)也是這樣獲取的 創(chuàng)造類的實(shí)例 PyInstance_New(pClassSecond,NULL,NULL) 調(diào)用實(shí)例的方法PyObject_CallMethod(pInstanceSecond, "invoke" , "O" ,pInstancePerson) 整個流程就是這樣的,并不復(fù)雜,如果要進(jìn)一步研究可以參考:http://www./doc/ Extending and Embedding Python/C API 比較特殊的是調(diào)用Python函數(shù)時,參數(shù)的傳遞,就是c++的類型,怎么轉(zhuǎn)換成Python的類型;另外一個問題是,Python函數(shù)的返回值,怎么轉(zhuǎn)換成C++中的類型。 C++轉(zhuǎn)換成Python類型,Py_BuildValue() http://www./doc/1.5.2p2/ext/buildValue.html PyObject* pArgs=PyTuple_New( 1 ); //有幾個參數(shù),就是幾 PyTuple_SetItem(pArgs, 0 ,Py_BuildValue( "i" , 3 )); //初始第一個參數(shù),數(shù)據(jù)類型是i,就是int,值是 3 返回值轉(zhuǎn)換如,PyArg_ParseTuple,請參考 http://www./doc/1.5.2p2/ext/parseTuple.html 系列文章: Python調(diào)用C/C++函數(shù)(1) Python調(diào)用采用Boost Python封裝的c++(2) C++調(diào)用Python(3) C++調(diào)用Python(4) c++和Python互操作高級應(yīng)用(5) |
|