1. 程式人生 > >Lua指令碼層面呼叫外部DLL

Lua指令碼層面呼叫外部DLL

任何語言都有辦法和lua互動,原因是它們都可以和C互動,而LUA是用C寫的,所以....。比如:java可以通過jni和C/C++互動,C#可以通過平臺呼叫和native互動。所以java和C#都可以和lua互動。
首先可以把其他語言或C/C++的第三庫提供的介面,用LUA所能接受的C介面原型Lua_CFunction,進行封裝後註冊,那麼在LUA指令碼中就可以直接使用。Lua_CFunction就是 int  (*Lua_CFunction)(LuaState* L)
例子:
最近下載了一個w32.dll,包含原始碼,它是一個封裝了部分win32 api提供給lua使用。剛開始時候,我是把原始碼直接整合進LUA 原始碼重新編譯,讓生成的LUA 支援win32 api,後面發現公司的LUA遊戲指令碼程式設計師,
他們無法接觸到服務端的指令碼引擎,就無法在公司LUA 原始碼裡面加入這些程式碼,後面就想直接在LUA指令碼層面去呼叫DLL來實現。如:呼叫win32  ShellExecute執行一個批處理

(一)package.loadlib方式:

local f = package.loadlib("d://w32.dll", "luaopen_w32") --獲取DLL中丟擲函式地址
assert(f, "Failed on loading w32.dll")
f() --呼叫DLL中丟擲函式
w32.ShellOpen("地下城服務端下載.bat")

(二)require方式:

package.path = ""
package.cpath = (os.getenv ("LUA_CLIBRARY_PATH") or ".") .. "/?.dll"

require("w32") --自動呼叫w32.dll的luaopen_w32丟擲函式,w32.dll要在LUA_CPATH搜尋路徑

w32.ShellOpen("地下城服務端下載.bat")

PS:

LUA 呼叫外部DLL,DLL 中包含庫函式和丟擲函式,當不是使用package.loadlib來使用外部DLL時, 而是使用另一種方式require,那麼就需要注意一些規則:

DLL中的丟擲函式原型必須是: [extern "C" ] __declspec(dllexport) int luaopen_XXX(LuaState* L),而且XXX是DLL的檔名。[]是可選符號,而package.loadlib使用方式是不需要這些規則的,但是為了相容性好,即:DLL可以同時使用以上兩種方式使用,還是按規則命名丟擲函式。

PS:也可以參考下本blog中另一篇《Lua呼叫DLL》,轉載網路上的一個例子(被我修改過)