1. 程式人生 > >手動使用C/C++編寫Lua擴充套件外掛

手動使用C/C++編寫Lua擴充套件外掛

最近在研究如何在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;
}
如下圖


第二步驟編寫 Lua 擴充套件原型 我這裡 使用的是 相容Lua5.1擴充套件方式,那麼 請在Lua庫以及 我們的擴充套件庫專案新增這樣我們可以使用 Lua5.1方式來擴充套件Lua,

當然我們也可以使用Lua5.2最新方式進行擴充套件 不過這都無所謂了。

下面告訴編譯器 我使用 5.1相容擴充套件生成 DLL共享庫。

#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")  //<span style="color:#FF0000;">關於require載入機制 在後續講解</span>
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 包含機制