Lua模塊化編程——使用require加載自己的dll模塊


  Lua本身是一個輕量級的腳本語言,包含在Lua源碼中的庫功能通常相對單一,用戶通常需要自己內嵌Lua解釋器到自己的應用中,並且一個一個地將需要導出的函數導出給Lua使用。

  假如我們需要使用第三方的庫,比如LuaFileSystem庫——lfs、用於網絡的Socket庫或者計算Base64編碼的庫,除了找到其源碼,並拷貝到自己的應用代碼中之外,還有沒有別的什么方式呢?

  大家都知道Windows DLL,這是一種動態鏈接的方式。Lua同樣也支持這樣一種模塊加載的方式。你只需將所需的第三方庫的DLL放到Lua的環境路徑中——這個我暫時並不能窮舉出具體有哪些,期待高人解答——或者簡單地將其放入你的Lua解釋器目錄下。接着,在需要使用的腳本中,直接調用Lua的require函數,將DLL的名字去除擴展名作為參數,Lua就可以自動加載指定的DLL模塊,並將其模塊導出的內容打包到一個table中並返回。你可以使用一個全局的table來接收其引用。

  對於自己編寫的模塊,也可以采用相同的方式去編寫。只需導出一個可以通過require加載的函數符號就可以了——require內部通過Windows API GetProcAddress來尋找其地址。這個函數的格式需要遵循Lua的模塊標准,格式如下:

View Code
static int foo(lua_State *L)
{
    lua_pushnumber(L, 1);
    return 1;
}

static const struct lua_Reg modulename[] = {
    {"foo", foo},
    {NULL,NULL},
};

int luaopen_modulename(lua_State *L)
{
    luaL_newlib(L, modulename); // 5.2之前使用luaL_register(L, "modulename", modulename);
    return 1;
}

  Lua5.2修改了其導出模塊的格式,大家要注意一下。

  當你在腳本中使用require加載一個模塊xxx的時候,首先它會在Lua的環境路徑中尋找以xxx命名的DLL,如果找到了,則會在這個DLL中尋找luaopen_xxx的函數用於加載模塊。我們只需要將自己需要導出給Lua調用的C內容通過這個函數導出就可以了,具體方式可以查看Lua的源碼,參考其math數學庫luaopen_math的實現。使用起來確實相當方便。只不過要注意一下Lua5.2與之前版本的不兼容性——導出函數從LuaL_register變成了LuaL_newlib,雖然可以選擇開啟Lua5.2的兼容模式來繼續使用LuaL_register,但我嘗試的時候總是在Lua_checkversion的時候出錯,提示說Multiple VMs detected。暫時來說,我是參考lfs庫的實現方式,自己重定義宏LuaL_register。

  完整的示例我已經上傳到GitHub中了,請用Visual Studio 2010查看其中的mylib工程,歡迎指正。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM