python與C互相調(diào)用的方法詳解
前言
最近因?yàn)楣ぷ鞯男枰诳紤]基于udp做一個(gè)用于網(wǎng)游戰(zhàn)斗中的數(shù)據(jù)同步協(xié)議,為了前期測(cè)試數(shù)據(jù),決定先做一個(gè)外部的代理tunnel,原理是在server端和client端分別建立網(wǎng)絡(luò)轉(zhuǎn)發(fā)proxy,即原來(lái)的C/S連接改為兩個(gè)proxy之間數(shù)據(jù)快速傳輸。因?yàn)閡dp庫(kù)是用C++寫(xiě)的代碼,在測(cè)試數(shù)據(jù)的時(shí)候需要不斷地修改參數(shù),重新編譯,修改輸出統(tǒng)計(jì)數(shù)據(jù)制表等,不勝其煩,最終決定導(dǎo)出接口由python腳本來(lái)進(jìn)行邏輯調(diào)用。下面話不多說(shuō),來(lái)一起看看詳細(xì)的介紹:
C/C++導(dǎo)出到python有多種方法,根據(jù)不同的需求,可以使用下面不同的方式:
1、ctypes綁定。ctypes就包含在萬(wàn)能的python標(biāo)準(zhǔn)庫(kù)模塊里面,它可以運(yùn)行時(shí)載入動(dòng)態(tài)鏈接庫(kù)(dll,so),在CPython 2.x/3.x和PyPy上都支持。這種方式好處就是不用針對(duì)性地用python api寫(xiě)導(dǎo)出函數(shù),可以直接加載動(dòng)態(tài)鏈接庫(kù)的符號(hào)表,在python中就可以直接調(diào)用了。
2、第三方的python binding。例子有boost-python,實(shí)現(xiàn)方式是工具自動(dòng)化用Python/C api生成一系列C++ wrapper函數(shù)。特別適用于大型的庫(kù)或引擎導(dǎo)出到python。
3、手動(dòng)寫(xiě)python binding函數(shù)。如果對(duì)Python C api熟悉的話,這種方式應(yīng)該是最靈活的,讀一遍API文檔就可以使用。理論上效率應(yīng)該是最好的,但對(duì)于我這種python初學(xué)者,可能需要花上不少時(shí)間。
以之前折騰C函數(shù)導(dǎo)出到Lua腳本的經(jīng)歷,本以為要先研究一番python c api,再搞上半天才能搞定。后面發(fā)現(xiàn)python標(biāo)準(zhǔn)庫(kù)模塊的ctypes已經(jīng)非常強(qiáng)大,雖然性能應(yīng)該是三種方式里面最差的,但在這個(gè)最高60fps的tunnel里面,C/Python接口邊界調(diào)用的損耗先忽略。跟其他兩種方式設(shè)計(jì)不一樣的是,ctypes采用的是非入侵式調(diào)用接口的方式,不需要修改原來(lái)的C接口或者寫(xiě)一些綁定代碼,直接對(duì)編譯出來(lái)的動(dòng)態(tài)庫(kù)進(jìn)行調(diào)用。ctypes使用過(guò)程也是非常愉悅的。
下面介紹下ctypes的使用:
1、加載DLL動(dòng)態(tài)鏈接庫(kù)
這里需要注意區(qū)分動(dòng)態(tài)鏈接庫(kù)函數(shù)是使用cdecl還是stdcall的調(diào)用約定,分別使用cdll或windll加載動(dòng)態(tài)庫(kù)。
例如:
# 加載udp庫(kù)函數(shù) udp_server = cdll.LoadLibrary("./udp_server.so") init_udp_server = udp_server.init_udp_server destroy_udp_server = udp_server.destroy_udp_server update_udp_server = udp_server.update_udp_server SendMsg = udp_server.SendMsg SetConnectCallback = udp_server.SetConnectCallback SetDisconnectCallback = udp_server.SetDisconnectCallback SetTimeoutCallback = udp_server.SetTimeoutCallback SetRecvCallback = udp_server.SetRecvCallback
2、數(shù)據(jù)類型映射
除了ctypes定義的基本數(shù)據(jù)類型(c_char, c_int, c_double等),還能使用pointer函數(shù)轉(zhuǎn)換成指針類型。對(duì)于要導(dǎo)出的網(wǎng)絡(luò)庫(kù),設(shè)置回調(diào)函數(shù)是必不可少的,在C++庫(kù)里面,回調(diào)函數(shù)是通過(guò)設(shè)置一個(gè)函數(shù)指針完成的,ctypes同樣支持函數(shù)指針的聲明。如:recv_cb = CFUNCTYPE( None, c_char_p, c_int )
,表示一個(gè)返回值為void,參數(shù)為char*和int類型的回調(diào)函數(shù)。
def __init__(self, port, ip="127.0.0.1"): self._port = port self._ip = ip self._clients = {} self.c_connect_cb = connect_cb(self.server_connect) self.c_disconnect_cb = disconnect_cb(self.server_disconnect) self.c_timeout_cb = timeout_cb(self.server_timeout) self.c_recv_cb = recv_cb(self.server_recv) def create(self): if self._port: if init_udp_server(self._ip, self._port) == 0: print "server listen %s:%d" % (self._ip, self._port) SetConnectCallback( self.c_connect_cb ) SetDisconnectCallback( self.c_disconnect_cb ) SetTimeoutCallback( self.c_timeout_cb ) SetRecvCallback( self.c_recv_cb ) return True print "[error] init_udp_server error", self._ip, self._port return False
綁定回調(diào)參數(shù)需要注意的是,綁定的回調(diào)函數(shù)需要保存為成員變量(上面的寫(xiě)法),目的是避免python垃圾回收導(dǎo)致回調(diào)函數(shù)變成野指針。這算是一個(gè)小小的坑吧?;旧弦粋€(gè)小小的庫(kù)也就用到這些功能。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Python實(shí)現(xiàn)監(jiān)控一個(gè)程序的運(yùn)行情況
這篇文章主要為大家介紹了Python如何實(shí)現(xiàn)監(jiān)控一個(gè)程序的運(yùn)行情況,然后視情況將進(jìn)程殺死并重啟,文中的示例代碼簡(jiǎn)潔易懂,需要的可以參考一下2023-05-05Python中常用的GUI(圖形用戶界面)庫(kù)用法詳細(xì)介紹
GUI圖形用戶界面是一種允許用戶通過(guò)圖形元素(如圖標(biāo)、按鈕、窗口等)與電子設(shè)備進(jìn)行交互的用戶界面,下面這篇文章主要給大家介紹了關(guān)于Python中常用的GUI(圖形用戶界面)庫(kù)用法的相關(guān)資料,需要的朋友可以參考下2024-08-08python 根據(jù)csv表頭、列號(hào)讀取數(shù)據(jù)的實(shí)現(xiàn)
這篇文章主要介紹了python 根據(jù)csv表頭、列號(hào)讀取數(shù)據(jù)的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05詳解Python如何利用pdfplumber提取PDF中的表格
pdfplumber 是一個(gè)開(kāi)源的 python 工具庫(kù) ,它可以輕松的獲取 PDF 文本內(nèi)容、標(biāo)題、表格、尺寸等各種信息,今天來(lái)介紹如何使用它來(lái)提取 PDF 中的表格,文中通過(guò)代碼和圖片講解的非常詳細(xì),需要的朋友可以參考下2024-04-04使用Python操作Excel中圖片的基礎(chǔ)示例(插入、替換、提取、刪除)
Excel是主要用于處理表格和數(shù)據(jù)的工具,我們也能在其中插入、編輯或管理圖片,為工作表增添視覺(jué)效果,提升報(bào)告的吸引力,本文將詳細(xì)介紹如何使用Python操作Excel中的圖片,文中有詳細(xì)代碼示例供大家參考,需要的朋友可以參考下2024-07-07python定時(shí)任務(wù) sched模塊用法實(shí)例
這篇文章主要介紹了python定時(shí)任務(wù) sched模塊用法實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11