步驟1:安裝Python開發(fā)包
成都創(chuàng)新互聯(lián)公司專注于伊州網(wǎng)站建設(shè)服務及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供伊州營銷型網(wǎng)站建設(shè),伊州網(wǎng)站制作、伊州網(wǎng)頁設(shè)計、伊州網(wǎng)站官網(wǎng)定制、微信平臺小程序開發(fā)服務,打造伊州網(wǎng)絡公司原創(chuàng)品牌,更為您提供伊州網(wǎng)站排名全網(wǎng)營銷落地服務。
由于需要訪問Python/C API,首先安裝Python開發(fā)包。
在Debian,Ubuntu或Linux Mint中:
在CentOS,F(xiàn)edora或RHEL中:
安裝成功后,Python頭文件在/usr/include/python2.7。根據(jù)Linux發(fā)行版的不同,確切的路徑可能是不相同的。例如,CentOS 6中是/usr/include/python2.6。
步驟2:初始化解釋器并設(shè)置路徑
C中嵌入Python的第一步是初始化Python解釋器,這可以用以下C函數(shù)完成。
初始化解釋器后,需要設(shè)置你的C程序中要導入的Python模塊的路徑。例如,比如你的Python模塊位于/usr/local/modules。然后使用以下C函數(shù)調(diào)用來設(shè)置路徑。
步驟3:數(shù)據(jù)轉(zhuǎn)換
C中嵌入Python最重要的方面之一是數(shù)據(jù)轉(zhuǎn)換。從C中傳遞數(shù)據(jù)到Python函數(shù),需要首先將數(shù)據(jù)從C數(shù)據(jù)類型轉(zhuǎn)換到Python數(shù)據(jù)類型。Python/C API提供各種函數(shù)來實現(xiàn)這。例如,轉(zhuǎn)換C字符串到Python字符串,使用PyString_FromString函數(shù)。
另外一個類似函數(shù)PyInt_FromLong,將C中l(wèi)ong數(shù)據(jù)類型轉(zhuǎn)換為Python int。每個Python/C API函數(shù)返回一個PyObject類型的引用。
步驟4:定義一個Python模塊
當你想嵌入Python代碼到另一種語言如C,該代碼需要被寫成Python模塊,然后用另一種語言“導入”。所以讓我們來看看如何在C中導入Python模塊。
為了進行說明,我們實現(xiàn)一個簡單的Python模塊例子如下:
以上的Python函數(shù)有一個字符串作為參數(shù)并返回兩個重復的字符串。例如,如果輸入字符串是“cyberpersons”,該函數(shù)返回'cyberpersonscyberpersons'。此模塊文件命名為“printData.py”并將它放在前面聲明的Python模塊目錄中(/usr/local/modules)。
步驟5:加載一個Python模塊
現(xiàn)在你已經(jīng)定義了Python模塊,是時候在C程序中加載它了。導入模塊的C代碼看起來像這樣:
步驟6:構(gòu)建函數(shù)的參數(shù)
當加載一個模塊時,可以調(diào)用模塊中定義的Python函數(shù)。通常,我們需要傳遞一個或多個參數(shù)到一個Python函數(shù)。我們必須構(gòu)建一個Python元組對象,它包括Python函數(shù)中的參數(shù)。
在我們的例子中,printData函數(shù)定義帶一個參數(shù)的模塊。因此,我們構(gòu)建一個大小是一的Python元組對象如下。我們可以使用PyTuple_SetItem設(shè)置元組對象的每個項。
我們已經(jīng)成功構(gòu)建一個參數(shù)傳遞到函數(shù)調(diào)用,是時候從C程序調(diào)用python函數(shù)了。
步驟7:調(diào)用Python函數(shù)
一旦成功創(chuàng)建Python元組對象作為函數(shù)參數(shù),我們可以調(diào)用一個帶參數(shù)的Python函數(shù)。為此,通過使用PyObject_GetAttrString首先獲得模塊中定義的函數(shù)的引用,然后使用PyObject_CallObject調(diào)用該函數(shù)。例如:
步驟8:錯誤檢查
避免運行時錯誤的常見方法是檢查函數(shù)的返回值并根據(jù)返回值采取適當?shù)男袆印n愃朴贑程序中的全局變量errno,Python/C API提供一個全局指示符,它報告最后發(fā)生的錯誤。當Python/C API函數(shù)失敗,全局指示符設(shè)置為指示錯誤,并且PyErr_Print可以用于顯示相應的人類可讀的trackback。例如:
在你的應用程序中,你可以輕松地將各種錯誤檢查。
這里是完整的C程序,它如本教程描述的嵌入Python代碼。
步驟9:編譯和執(zhí)行
保存以上代碼到finalCode.c,并且鏈接Python庫(-lpython2.7)編譯該代碼。根據(jù)發(fā)行版的不同,可能使用不同的版本(例如,-lpython2.6)。
下面是一個例子:
首先是python的一個簡單函數(shù)
class Hello:
def __init__(self, x):
self.a = x
def print(self, x=None):
print(x)
def xprint():
print("hello world")
if __name__ == "__main__":
xprint()
h = Hello(5)
h.print()1
下面是C語言
#include python3.4m/Python.h
#include stdio.h
#include stdlib.h
#include string.h
int main()
{
Py_Initialize();
// 將當前目錄加入sys.path
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
// 導入hello.py模塊
PyObject *pmodule = PyImport_ImportModule("hello");
// 獲得函數(shù)xprint對象,并調(diào)用,輸出“hello world\n”
PyObject *pfunc = PyObject_GetAttrString(pmodule, "xprint");
PyObject_CallFunction(pfunc, NULL);
// 獲得類Hello并生成實例pinstance,并調(diào)用print成員函數(shù),輸出“5 6\n”
PyObject *pclass = PyObject_GetAttrString(pmodule, "Hello");
PyObject *arg = Py_BuildValue("(i)", 5);
PyObject *pinstance = PyObject_Call(pclass, arg, NULL);
PyObject_CallMethod(pinstance, "print", "i", 6);
Py_Finalize();
return 0;
}
編譯命令如下:
gcc pyapi.c -lpython3.4m -o pyapi
在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下執(zhí)行出錯,“無法找到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函數(shù)原型是:void Py_Initialize(),在嵌入Python腳本時必須使用該函數(shù),它初始化Python解釋器,在使用其他的Python/C API之前必須先調(diào)用該函數(shù)??梢允褂肞y_IsInitialized函數(shù)判斷是否初始化成功,成功返回True。
PyRun_SimpleString函數(shù)原型是int PyRun_SimpleString(const char *command),用來執(zhí)行一段Python代碼。注意:是否需要維持語句間的縮進呢?
Py_Finalize函數(shù)原型是void Py_Finalize(),用于關(guān)閉Python解釋器,釋放解釋器所占用的資源。
PyRun_SimpleFile函數(shù)可以用來運行".py"腳本文件,函數(shù)原型如下:
int PyRun_SimpleFile(FILE *fp, const char *filename);
其 中fp是打開的文件指針,filename是要運行的python腳本文件名。但是由于該函數(shù)官方發(fā)布的是由visual studio 2003.NET編譯的,如果使用其他版本的編譯器,F(xiàn)ILE定義可能由于版本原因?qū)е卤罎?。同時,為簡便起見可以使用如下方式來代替該函數(shù):
PyRun_SimpleString("execfile(‘file.py’)"); //使用execfile來運行python文件
Py_BuildValue()用于對數(shù)字和字符串進行轉(zhuǎn)換處理,變成Python中相應的數(shù)據(jù)類型(在C語言中,所有Python類型都被聲明為PyObject類型),函數(shù)原型如下:
PyObject *Py_BuildValue(const char *format, …..);
PyString_String()用于將PyObject*類型的變量轉(zhuǎn)換成C語言可以處理的char*型,具體原型如下:
char* PyString_String(PyObject *p);
列表操作函數(shù):
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);
元組操作函數(shù):
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); //注意是**指針
字典操作函數(shù):
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對象應正確地處理引用計數(shù)問題,否則容易導致內(nèi)存泄漏。當使用Python/C API中的函數(shù)創(chuàng)建列表、元組、字典等后,在對其完成操作后應該使用Py_CLEAR()和Py_DECREF()等宏來銷毀這些對象。原型如下:
void Py_CLEAR(PyObject *o);
void Py_DECREF(PyObject *o);
其中,對于Py_CLEAR函數(shù),參數(shù)可以為NULL指針,表示不進行任何操作,但是Py_DECREF函數(shù)不能為NULL指針,否則導致錯誤。
使用PyImport_Import()函數(shù)可以在C中導入Python模塊,返回一個模塊對象。函數(shù)原型為:
PyObject* PyImport_Import(PyObject *name);
PyModule_GetDict()函數(shù)可以獲得Python模塊中的函數(shù)列表,返回一個字典,字典中的關(guān)鍵字為函數(shù)名,值為函數(shù)的調(diào)用地址。原型如下:
PyObject* PyModule_GetDict(PyObject *module);
使用PyObject_CallObject()函數(shù)和PyObject_CallFunction()函數(shù)可以在C中調(diào)用Python中的函數(shù),原型如下:
PyObject* PyObject_CallObject(PyObject *callable_object, PyObject *args);
//args是元組形式
PyObject* PyObject_CallFunction(PyObject *callable, char *format, ……);
//format是類似”iss”這樣的參數(shù)類型,后面是指定參數(shù)
可以使用PyCallable_Check(func)來判斷是否可以調(diào)用函數(shù),可以則返回True。
分享文章:c使用python函數(shù)的簡單介紹
網(wǎng)頁網(wǎng)址:http://chinadenli.net/article40/heejeo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應網(wǎng)站、定制網(wǎng)站、商城網(wǎng)站、企業(yè)網(wǎng)站制作、面包屑導航、響應式網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)