便攜式外部函數接口庫:LibFFI

jopen 11年前發布 | 12K 次閱讀 LibFFI C/C++開發

FFI” 的全名是 Foreign Function Interface,通常指的是允許以一種語言編寫的代碼調用另一種語言的代碼。而 “Libffi” 庫只提供了最底層的、與架構相關的、完整的”FFI”,因此在它之上必須有一層來負責管理兩種語言之間參數的格式轉換。

高級語言編譯器產生代碼時都會依據一系列的規則,這些規則十分必要,特別是對獨立編譯來說。其中之一是“調用約定” (Calling Convention),它包含了編譯器關于函數入口處的函數參數、函數返回值的一系列假設。它有時也被稱作“ABI”(Application Binary Interface)。調用約定(Calling Conventions)定義了程序中調用函數的方式,它決定了在函數調用的時候數據(比如說參數)在堆棧中的組織方式。

通常來說函數調用要用到的兩條基本的指令:”CALL”指令和”RET”指令。”CALL”指令將當前的指令指針(這個指針指向緊接在CALL指令 后面的那條指令)壓入堆棧,然后執行一條無條件轉移指令轉移到新的代碼地址。”RET”是與”CALL”指令配合使用的指令,在絕大多數函數中它是最后一 條指令。”RET”指令彈出返回地址(就是早些時候”CALL”指令壓入堆棧的地址)并將其加載到”EIP”寄存器中,然后從這個地址開始繼續執行。

圖1-1 說明調用約定”stdcall”的調用過程,調用時,最末一個參數最先壓入堆棧,而由被調用函數使用RET指令清棧。RET指令帶有一個操作數,該操作數 指明在EIP跳回主要函數之前需要釋放的堆棧空間的字節數。這就是說,stdcall調用約定中RET指令帶的操作數往往就意味著函數一共傳入幾個參數。

便攜式外部函數接口庫:LibFFI

圖1-1 stdcall調用

獨立編譯時,調用一個函數除了要知道函數的簽名外,還要知道其調用約定。比如 Delphi 中調用”Stdcall”的”VC++”的函數,需對調用約定加以聲明。

Procedure ShowMess (h :HWND; mess :PChar ); Stdcall; external LibName;

LibFFI”針對這些不同的調用約定,提供一個高層次的可移植的API,只需調用這些API就可以在運行時進行動態的函數調用。(這種方式和函數指針不同,函數指針比如在編譯時就決定了函數的類型,而”libffi”可以在運行時是才決定被調用函數的類型)。有了 libffi ,我們就有可能寫出一個通用而且簡潔的調用 C 函數的方法。

目前有許多項目都使用了 libff ,包括 ruby,cpython, openjdk,dalvik vm 等等。例如在 Ruby 中,利用 rubyffi (包裝了 libffi )可以如此動態地調用一個 dll

來自:http://blogs.ejb.cc/archives/1502/libffi-example-of-the-use


項目主頁:http://www.baiduhome.net/lib/view/home/1384496482680

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!