最近在研究如何在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 包含機制