這篇文章
的基礎上編寫的,由於原文章採用的是lua-5.2以下的版本,但是lua-5.2的版本進行了很大的改動,導致之前的很多函式不能再使用。本文就解決了採用lua-5.3.0中的api函式之後,原文章中**存在的一些問題。
這裡只講原文章中提到的第二種方法c函式庫成為lua的模組,以實現lua呼叫c函式,另外一種方法可以參考原文章。
c函式庫成為lua的模組其實就是將包含c函式的**生成庫檔案,如linux的so。將其放至相應目錄,以便於lua解析器可以正確定位到它們。下面以**進行解釋。
以下是test.c的**:
#include#include#include#include#includeint add(lua_state* l) //去掉了原**中的extern "c",後面也是類似去掉了
int sub(lua_state* l)
//lual_reg結構體的第乙個欄位為字串,在註冊時用於通知lua該函式的名字。
//第乙個欄位為c函式指標。
//結構體陣列中的最後乙個元素的兩個欄位均為null,用於提示lua註冊函式已經到達陣列的末尾。
static lual_reg mylibs =, ,
};//該c庫的唯一入口函式。其函式簽名等同於上面的註冊函式。見如下幾點說明:
//1. 我們可以將該函式簡單的理解為模組的工廠函式。
//2. 其函式名必須為luaopen_***,其中***表示library名稱。lua**require "***"需要與之對應。
//3. 在lual_setfuncs的呼叫中,其第二個引數為待註冊函式的陣列。
//4. 需要強調的是,所有需要用到"***"的**,不論c還是lua,都必須保持一致,這是lua的約定,
// 否則將無法呼叫。
int luaopen_mytestlib(lua_state* l)
在test.c中去掉了源**中的extern 「c」,如若不去掉會報錯:/usr/local/include/lua.hpp:5:8: error: expected identifier or 『(』 before string constant extern "c"
以下是test.lua的**:
local mylib = require("mytestlib") --對應於teste.c中的包名
print(mylib.add(1.0,2.0))
print(mylib.sub(20.1,19))
在原文章的test.lua**中沒有定義變數mylib,是直接requier("mytestlib"),再用mytestlib.add去呼叫函式c中的函式add。反正我用原**執行的時候會報錯,在網上找了很久這個問題,最終改為了現在的**。
原文章**的報錯資訊為:lua: test.lua:4: attempt to index a nil value (global 'mytestlib')
至此**編寫部分就這些,這裡再記錄一下這段**的編譯鏈結過程,使可以看到**的執行結果,以證明**的正確性。
將test.c編譯成.o檔案:gcc -c -fpic -o test.o test.c
將test.o編譯成.so檔案:gcc -shared -o mytestlib.so test.o
執行test.lua**:lua test.lua
編譯鏈結之後資料夾中的檔案如下圖所示:
lua呼叫c函式
最近在進入lua程式設計的狀態,一度令我困惑的是,lua提供的功能少的可憐,跟自備電池的python相比,可說是簡陋了。連table的列印,都需要自己實現,也因此有了一打的第三方方案。後來我想明白了,以lua和c如此緊密的關係,只需要建立lua的binding,那麼豐富而效能強大的c庫資源完全可以為...
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棧狀態需要自己進行維護,若...