前兩篇都是介紹Python調用C++的,換句話說,就是需要把C++封裝成Python可以“理解”的類型。這篇,我打算說一下,C++怎麼去調用Python指令碼。其實這兩者之間是相通的,就是需要可以互操作。按照慣例,先貼代碼。
test.cpp
/*<br /> * test.cpp<br /> * Created on: 2010-8-12<br /> * Author: lihaibo<br /> */<br />#include <python2.6/Python.h><br />#include <iostream><br />#include <string><br />void printDict(PyObject* obj) {<br />if (!PyDict_Check(obj))<br />return;<br />PyObject *k, *keys;<br />keys = PyDict_Keys(obj);<br />for (int i = 0; i < PyList_GET_SIZE(keys); i++) {<br />k = PyList_GET_ITEM(keys, i);<br />char* c_name = PyString_AsString(k);<br />printf("%s/n", c_name);<br />}<br />}<br />int main() {<br />Py_Initialize();<br />if (!Py_IsInitialized())<br />return -1;<br />PyRun_SimpleString("import sys");<br />PyRun_SimpleString("sys.path.append('./')");<br />//匯入模組<br />PyObject* pModule = PyImport_ImportModule("testpy");<br />if (!pModule) {<br />printf("Cant open python file!/n");<br />return -1;<br />}<br />//模組的字典列表<br />PyObject* pDict = PyModule_GetDict(pModule);<br />if (!pDict) {<br />printf("Cant find dictionary./n");<br />return -1;<br />}<br />//列印出來看一下<br />printDict(pDict);<br />//示範函數調用<br />PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi");<br />PyObject_CallFunction(pFunHi, "s", "lhb");<br />Py_DECREF(pFunHi);<br />//示範構造一個Python對象,並調用Class的方法<br />//擷取Second類<br />PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second");<br />if (!pClassSecond) {<br />printf("Cant find second class./n");<br />return -1;<br />}<br />//擷取Person類<br />PyObject* pClassPerson = PyDict_GetItemString(pDict, "Person");<br />if (!pClassPerson) {<br />printf("Cant find person class./n");<br />return -1;<br />}<br />//構造Second的執行個體<br />PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL);<br />if (!pInstanceSecond) {<br />printf("Cant create second instance./n");<br />return -1;<br />}<br />//構造Person的執行個體<br />PyObject* pInstancePerson = PyInstance_New(pClassPerson, NULL, NULL);<br />if (!pInstancePerson) {<br />printf("Cant find person instance./n");<br />return -1;<br />}<br />//把person執行個體傳入second的invoke方法<br />PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson);<br />//釋放<br />Py_DECREF(pInstanceSecond);<br />Py_DECREF(pInstancePerson);<br />Py_DECREF(pClassSecond);<br />Py_DECREF(pClassPerson);<br />Py_DECREF(pModule);<br />Py_Finalize();<br />return 0;<br />}<br />
編譯
g++ test.cpp -o test -lpython2.6
testpy.py
#!/usr/bin/python<br /># Filename: test.py<br />class Person:<br />def sayHi(self):<br />print 'hi'<br />class Second:<br />def invoke(self,obj):<br /> obj.sayHi()<br />def sayhi(name):<br />print 'hi',name;<br />
執行
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
系列文章:
Python調用C/C++函數(1)
Python調用採用Boost Python封裝的c++(2)
C++調用Python(3)
C++調用Python(4)
c++和Python互操作進階應用程式(5)