C/C++中嵌入Python

鴨脖發表於2012-04-24
在C/C++中嵌入Python也比較簡單,首先需要在VC中新增Python的include檔案目錄和lib檔案目錄:
VC6.0下,開啟 tools->options->directories->show directories for,將Python安裝目錄下的inlude目錄新增到inlude files項中,將libs目錄新增到library files項中。
VC2005下,開啟tools->options->專案和解決方案->VC++目錄,然後做相同工作。

程式碼如下:
//在debug下執行出錯,“無法找到python31_d.lib檔案”,後查到原因是:在debug下生成必須要有python31_d.lib檔案,否則只能在release下生成
#include <python.h>
int main()
{
    Py_Initialize();
    PyRun_SimpleString("Print 'hi, python!'");
    Py_Finalize();
    return 0;
}

Py_Initialize函式原型是:void Py_Initialize(),在嵌入Python指令碼時必須使用該函式,它初始化Python直譯器,在使用其他的Python/C API之前必須先呼叫該函式。可以使用Py_IsInitialized函式判斷是否初始化成功,成功返回True。
PyRun_SimpleString函式原型是int PyRun_SimpleString(const char *command),用來執行一段Python程式碼。注意:是否需要維持語句間的縮排呢?
Py_Finalize函式原型是void Py_Finalize(),用於關閉Python直譯器,釋放直譯器所佔用的資源。

PyRun_SimpleFile函式可以用來執行".py"指令碼檔案,函式原型如下:
int PyRun_SimpleFile(FILE *fp, const char *filename);
其 中fp是開啟的檔案指標,filename是要執行的python指令碼檔名。但是由於該函式官方釋出的是由visual studio 2003.NET編譯的,如果使用其他版本的編譯器,FILE定義可能由於版本原因導致崩潰。同時,為簡便起見可以使用如下方式來代替該函式:
PyRun_SimpleString("execfile(‘file.py’)");      //使用execfile來執行python檔案

Py_BuildValue()用於對數字和字串進行轉換處理,變成Python中相應的資料型別(在C語言中,所有Python型別都被宣告為PyObject型別),函式原型如下:
PyObject *Py_BuildValue(const char *format, …..);
PyString_String()用於將PyObject*型別的變數轉換成C語言可以處理的char*型,具體原型如下:
char* PyString_String(PyObject *p);

列表操作函式:
PyObject * PyList_New(Py_ssize_t len);
int PyList_SetItem(PyObject *list, Py_ssize_t index, PyObject *item);
PyObject * PyList_GetItem(PyObject *list, Py_ssize_t index);
int PyList_Append(PyObject *list, PyObject *item);
int PyList_Sort(PyObject *list);
int PyList_Reverse(PyObject *list);
Py_ssize_t PyList_Size(PyObject *list);

元組操作函式:
int PyTuple_New(Py_ssize_t len);
int PyTuple_SetItem(PyObject *p, Py_ssize_t pos, PyObject *o);
PyObject * PyTuple_GetItem(PyObject *p, Py_ssize_t pos);
int _PyTuple_Resize(PyObject **p, Py_ssize_t newsize);             //注意是**指標

字典操作函式:
PyObject * PyDict_New();
int PyDict_SetItem(PyObject *p, PyObject *key, PyObject *val);
int PyDict_SetItemString(PyObject *p, const char *key, PyObject *val);
PyObject* PyDict_GetItem(PyObject *p, PyObject *key);
PyObject* PyDict_GetItemString(PyObject *p, const char *key); 
//與PyDict_SetItemString對應
int PyDict_DelItem(PyObject *p, PyObject *key);
int PyDict_DelItemString(PyObject *p, char *key);
//與PyDict_SetItemString對應
int PyDict_Next(PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue);
PyObject* PyDict_Items(PyObject *p);
PyObject* PyDict_keys(PyObject *p);
PyObject* PyDict_Values(PyObject *p);

在C/C++中使用Python物件應正確地處理引用計數問題,否則容易導致記憶體洩漏。當使用Python/C API中的函式建立列表、元組、字典等後,在對其完成操作後應該使用Py_CLEAR()和Py_DECREF()等巨集來銷燬這些物件。原型如下:
void Py_CLEAR(PyObject *o);
void Py_DECREF(PyObject *o);
其中,對於Py_CLEAR函式,引數可以為NULL指標,表示不進行任何操作,但是Py_DECREF函式不能為NULL指標,否則導致錯誤。

使用PyImport_Import()函式可以在C中匯入Python模組,返回一個模組物件。函式原型為:
PyObject* PyImport_Import(PyObject *name);
PyModule_GetDict()函式可以獲得Python模組中的函式列表,返回一個字典,字典中的關鍵字為函式名,值為函式的呼叫地址。原型如下:
PyObject* PyModule_GetDict(PyObject *module);
使用PyObject_CallObject()函式和PyObject_CallFunction()函式可以在C中呼叫Python中的函式,原型如下:
PyObject* PyObject_CallObject(PyObject *callable_object, PyObject *args);
//args是元組形式
PyObject* PyObject_CallFunction(PyObject *callable, char *format, ……);
//format是類似”iss”這樣的引數型別,後面是指定引數
可以使用PyCallable_Check(func)來判斷是否可以呼叫函式,可以則返回True。

相關文章