最近在進入lua程式設計的狀態,一度令我困惑的是,lua提供的功能少的可憐,跟自備電池的python相比,可說是簡陋了。連table的列印,都需要自己實現,也因此有了一打的第三方方案。後來我想明白了,以lua和c如此緊密的關係,只需要建立lua的binding,那麼豐富而效能強大的c庫資源完全可以為lua所用,這樣就不愁功能缺失了。
關於c呼叫lua,前段時間已經寫過一篇短文了:《多語言協作與二進位制互動》,現在補上從lua呼叫c的這一篇。先上一段lua**:
#!/usr/bin/lua在這段**裡,我引用了乙個power模組,並且呼叫了power模組裡的square函式和cube函式。由此可知,在c語言編寫的power模組裡面,需要有相關的函式可以註冊本模組提供的函式,並且讓lua可以「感知」到自身是乙個模組。回憶一下lua的路徑搜尋,可以看到除了字尾名為*.lua的檔案之外,還有*.so檔案,所以c擴充套件是編譯為.so的。實際情況是,在執行require語句的時候,系統會呼叫luaopen_power函式,這個函式名是通過luaopen_與power這個模組名拼接得到的。require("
power")
print(square(1.414213598
))print(cube(5))
現在看看luaopen_power函式的定義:
int luaopen_power(lua_state *l)可以看到,通過呼叫lua_register函式,我們在l這個lua虛擬機器裡面註冊了兩個函式,乙個是square,乙個是cube,他們分別對應到isquare和icube這兩個c函式。
回過頭來看一看,lua指令碼裡,這條簡單的require語句,執行了兩個步驟:一是先把名字為power.so的檔案載入起來,二是呼叫其中的luaopen_power函式。下面來看一下具體的函式如何定義:
static注釋的講解比較詳細了,可以看到為lua定義的c函式格式都是比較統一的,首先接受乙個lua虛擬機器變數l,然後從l裡取出相應的引數(需要指定資料型別),最後將返回值再次壓回虛擬機器裡面,通過返回int告訴lua虛擬機器,自己的返回值有多少個。int isquare(lua_state *l)
好,到這裡就只差最後一步了,現在把這段c**編譯成.so檔案。使用如下的編譯引數:
ubuntu@ubuntu:~$ gcc -wall -shared -fpic -o power.so -i/usr/include/lua5.1 -llua5.1 hellofunc.c(hellofunc.c記得要include lua.h, lauxlib.h, lualib.h三個標頭檔案哦)
這裡解釋一下兩個引數的意思,-shared是告訴gcc,需要編譯成.so檔案,並且這個原始檔裡面不會有main函式,不要大驚小怪。另乙個-fpic,是position independent code的意思,具體的含義可以參考這篇,主要用來避免同乙份**因為重定位位置不同而在記憶體中存在多個例項。
呼叫的結果:
ubuntu@ubuntu:~$ ./hellofunc.lua當然,如果機器安裝有多個版本的lua,需要指定執行hellofunc.lua的lua直譯器版本。因為本篇教程是針對lua5.1的,所以需要指定lua5.1來執行,例如lua5.1 hellofunc.lua,否則用lua5.2呼叫會引起core dumptop of square(), nbr=1.414214
2.0000002687177
top of cube(), number=5.000000
125
lua呼叫c函式
lua可以呼叫c函式的能力將極大的提高lua的可擴充套件性和可用性。對於有些和作業系統相關的功能,或者是對效率要求較高的模組,我們完全可以通過c函式來實現,之後再通過lua呼叫指定的c函式。對於那些可被lua呼叫的c函式而言,其介面必須遵循lua要求的形式,即 typedef int lua cfu...
lua呼叫C函式
lua採取的是利用棧進行互動,利用各種lua push 將不同的值壓入棧中,然後呼叫lua指令碼時自然會退棧取出引數執行,對於lua的虛擬機器來說,就像是發生了一次正常的函式呼叫。這裡採用的棧是lua棧,因為若是c棧的話呼叫lua的c api就會出錯了。需要注意的是,lua棧狀態需要自己進行維護,若...
Lua呼叫C 函式
現在很多伺服器研發為了節約開發成本,邏輯業務採用lua編寫,下面講講工作上遇到的一些問題,記錄方便以後查閱。我們知道用lua寫癩子胡牌演算法可能執行不是很高效,當你有現成的麻將庫,是不是可以繫結給lua使用呢,答案肯定。胡牌演算法,主要是傳遞陣列,下面就實現乙個lua傳遞陣列到c 之後就能使用胡牌演...