1. 程式人生 > >外部函數接口 LibFFI

外部函數接口 LibFFI

ali 圖片 有一個 dalvik hwnd 移植 之一 通用 一是

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指令帶的操作數往往就意味著函數一共傳入幾個參數。

技術分享圖片

圖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

https://www.oschina.net/p/libffi

外部函數接口 LibFFI