Ruby FFI
Ruby 解析器的性能一般,在一些對性能要求很高的場合我們必須用C語言來編寫,然后使用Ruby去調(diào)用C庫。但是,Ruby調(diào)用C庫并不是一件輕松的事,需要你對Ruby的內(nèi)部數(shù)據(jù)結(jié)構(gòu)有比較深入的了解,甚至需要你仔細閱讀Ruby相關(guān)的源代碼,然后用C語言編程作為黏合劑,用Ruby特有的C API去給外部的C庫增加一層封裝。
對程序員的要求很高。而且一旦Ruby內(nèi)部的數(shù)據(jù)結(jié)構(gòu)隨著版本升級發(fā)生變動,你的這些程序就必須重寫。比方說現(xiàn)在Ruby 1.9出來以后,絕大部分Ruby的C擴展庫統(tǒng)統(tǒng)無法正常編譯。所以給Ruby寫C的擴展庫一件非常痛苦的事情,而且也是Ruby社區(qū)程序員一直抱怨的問題之一。然而隨著FFI的出現(xiàn),我們即將告別這些痛苦的歷史!
FFI即Foreign Function Interface,外部函數(shù)調(diào)用接口,并非Ruby獨有的概念,只不過因為Ruby擴展庫帶來的痛苦,使得Ruby的FFI顯得格外迫切。FFI最早已 經(jīng)在 Rubinius 虛擬機平臺上實現(xiàn)了,隨后在JRuby上面也得以實現(xiàn),而今天:2008年11月1日,在Ruby官方版本的解析器Ruby 1.8.6/1.8.7和1.9版本上也可以使用FFI了。
安裝 FFI 的方法: gem install ffi
使用FFI也很簡單,比方說調(diào)用C語言標(biāo)準(zhǔn)庫的printf函數(shù),我們可以這樣來寫:
require 'ffi'
module MyExtModule
extend FFI::Library
attach_function :printf, [:string], :void
end
MyExtModule.printf("Hello Ruby FFI\n")
用attach_fuction就可以把C語言標(biāo)準(zhǔn)庫的printf函數(shù)綁定到ruby里面來了,后面的參數(shù)分別聲明C函數(shù)的傳入?yún)?shù)和返回值。如果需要 引入其他C庫,可以預(yù)先使用ffi_lib指定庫的名稱。(我使用ffi_lib未能綁定非標(biāo)準(zhǔn)庫,有可能是FFI的bug?也有可能是我沒有設(shè)置對?)
有了FFI,在Ruby語言里面調(diào)用C庫,就變成了一件異常輕松的事情,完全不需要ruby程序員再去學(xué)習(xí)C語言了,只要你手里捧著C庫的 API手冊能看清楚函數(shù)的參數(shù)定義就夠用了,然后你就可以直接在ruby里面隨心所欲的調(diào)用它了,在調(diào)用之前,只需要用attach_function進 行一次函數(shù)綁定聲明即可。
