最近在研究如何在Windows 下嵌入Lua來完成業務模塊編寫的時候 發現Lua的一些問題,首先Lua作為一門腳本語言,其靈活性和可擴展性是很高的,要不然Cocos2d-x中也不會嵌入他來編寫業務邏輯,但是由於國內資料相當的少,很少有人去正八經研究完了之後 寫一篇文章 來分享自己的成果,想要去深入理解應用一些東西得時候,顯得很無力,很多Lua擴展都是直接寫擴展庫來完成,如果不理解原理甚至你都不會靈活運用,這就是本文寫作的目的。
第一 我需要Lua嵌入我的應用程序,這一點很容易的做到。
第二 我需要使用Lua進行數據層的操作,我希望有一個類似 Java PHP中的ORM框架來完成我的Sqlite3數據庫操作,但是研究來研究去發現 好坑爹,只有下面兩個庫還算可以。 LuaSql 已經好幾年沒有更新了,Github上最新的代碼 都是基於Sqlite3以及Lua5.1之前的版本,另一個lsqlite3也是 ,雖然相對強悍些 ,但是 貌似文檔上說 只在Linux下測試通過。。。所以面對這些坑爹問題的時候 去勉強編譯這些古老的代碼還不如 自己去根據sqlite3編寫自己的Lua 擴展。
下面進入正題:
一步一步編寫自己的Lua擴展程序,到此我假設大家已經具有Lua嵌入開發的基礎 。
首先新建我們自己的DLL項目作為Lua擴展庫,設置好Lua庫的路徑 ,頭文件包含路徑,之後 在擴展庫項目源文件中添加入下代碼 用作Lua初始化 。
extern "C" { #include "lua.h" #include "lualib.h" #include "lauxlib.h" }; ///打開Lua Libs lua_State *GetLua() { lua_State *lua=luaL_newstate() ; luaL_openlibs(lua); return lua; }如下圖
vcq9vfjQ0MCp1bkgsru5/dXitrzO3sv5zr3By6GjPC9zdHJvbmc+PC9wPgo8cD48c3Ryb25nPs/Cw+a45svfseDS68b3IM7SyrnTwyA1LjG85sjdwKnVucn6s8kgRExMubLP7b/ioaM8L3N0cm9uZz48YnI+CjwvcD4KPHA+PC9wPgo8cHJlIGNsYXNzPQ=="brush:java;">#define LUA_COMPAT_MODULE
#define LUA_CORE
#define LUA_BUILD_AS_DLL這個時候我麼開始按照Lua的方式來編寫我們的擴展庫。。可以有兩種方式
第一種內嵌式擴展就是直接 將擴展寫到我們的應用程序中,我們開發的時候通常這麼做。 而不是DLL中,代碼如下 。
#define LUA_COMPAT_MODULE extern "C" { #include "lua.h" #include "lualib.h" #include "lauxlib.h" }; ///打開Lua Libs lua_State *GetLua() { lua_State *lua=luaL_newstate() ; luaL_openlibs(lua); return lua; } static int extFunc(lua_State* L) { printf("i am a embed Lua Extension By Programmer小衛!\n"); return 0; } const luaL_Reg reg[]= { {"func",extFunc}, {NULL, NULL} }; LUALIB_API int luaopen_usher_luaex(lua_State *L) { //lua 函數 luaL_openlib(L, "usher", reg, 0); return 0;//沒有返回值 } int _tmain(int argc, _TCHAR* argv[]) { lua_State *lua=GetLua(); luaopen_usher_luaex(lua); if(0!=luaL_dofile(lua,"./luaext.lua")){ printf("load error!\n"); } return 0; }Lua測試代碼如下
require("usher") //關於require加載機制 在後續講解 usher.func()
第二種 插件式擴展我們用到的好多第三方Lua擴展就是按照此種方式開發DLL擴展
代碼如下:
#define LUA_COMPAT_MODULE extern "C" { #include "lua.h" #include "lualib.h" #include "lauxlib.h" }; lua_State *GetLua() { lua_State *lua=luaL_newstate() ; luaL_openlibs(lua); return lua; } static int extFunc(lua_State* L) { printf("i am a Lua Extension By Programmer小衛!"); return 0; } static const luaL_Reg reg[]= { {"func",extFunc}, {NULL, NULL} }; //模塊名字 dll名字 //被加載器加載 extern "C" _declspec(dllexport) int luaopen_usher_luaex(lua_State *L) { //lua 函數 luaL_openlib(L, "usher", reg, 0); return 0;//沒有返回值 } BOOL WINAPI DllMain( __in HINSTANCE hinstDLL, __in DWORD fdwReason, __in LPVOID lpvReserved ) { return TRUE ; }
//lua插件調用代碼如下 require("usher.luaex") //加載當前package.cpath下的usher\luaex.dll 插件 並且 加載入口函數從而加載 lua擴展庫 usher.func()
便已生成的dll我們可以發現 導出了如下函數 luaopen_usher_luaex用給lua模塊進行加載
生成的擴展模塊dll如下
最終運行結果如下
好了到現在開始你也可以為Lua 寫 擴展庫了,下一張詳細分析Lua的 require 包含機制