Lua5.3 与C交互学习(一)
- C++中引入lua環境搭建
- C++調用Lua函數
- Lua中調用C++函數
- .lua文件文間之間的全局變量調用
- 引入C模塊到 lua
- lua5.3 C++注冊函數或模塊到lua
- 注冊C++類到lua
- C++ struct對應到lua table
C++中引入lua環境搭建
- 第一種: 聯合的方式(不方便)
- 下載lua5.3.1 tar.gz
- 創建控制臺項目, 靜態庫, 取消預編譯頭;
- C/C++>常規>附加包含目錄: 加入5.3.1\src
- 編譯得到lublib.lib
- 創建新工程
- 在vc++目錄里添加包含目錄 和庫目錄;
- 連接器里添加lualib.lib
- 編譯; 如果失敗則拷貝lualib.lib到根目錄dubug下;
- OK
- 第二中: 生成靜態庫
- 新建控制臺項目, 靜態庫, 取消預編譯頭;
- 將5.3.2的src中添加到項目中, 但 不要添加lua.c
- 編譯得到xxx.lib, 這就是所得到的靜態庫
- 建立一個文件夾如lua5.3,分別在子文件夾lib里放入剛生成的xxx.lib(可以改名為lua5.3.2.lib)和include子文件夾里放入lua頭文件: lauxlib.h, lua.h, luaconf.h, lualib.h
- 新建C++項目, 在”項目屬性>VC++目錄>包含目錄和庫目錄里”添加上面的lib和include路徑;
- “項目屬性>連接器>輸入”里添加lua5.3.2.lib
- OK
C++調用Lua函數
要在C++中調用lua函數,則有如下函數可以利用:
lua_getglobal()就是從lua中取得函數,壓入棧中;隨后壓入函數的參數;
如在test.lua中有如下代碼:
function he(x,y)return x*y end則的C++中的調用過程是:
//..... lua_getgloabl(L,"he"); lua_pushnumber(L,5); lua_pushnumber(L,6); // run the lua program // lua_pcall(L,nargs,nresults,0) if(lua_pcall(L,2,1,0) != 0)printf("error pcall!: %s\n",lua_tostring(L,-1)); // if error then push errorinfo in the stack else push reuslts if(!lua_isnumber(L,-1))printf("error return!\n"); int re = (int)lua_tonumber(L,-1);函數參數、返回值壓棧是正序壓棧;如果有錯誤發生的話, lua_pcall 會捕獲它,然后把單一的值(錯誤信息)壓入堆棧,然后返回錯誤碼。lua_pcall 總是把函數本身和它的參數從棧上移除。
Lua中調用C++函數
- 要寫一個能讓Lua調用的C函數,就要符合lua_CFunction定義:typedef int (*lua_CFunction) (lua_State *L); //return 返回值的個數
- 當Lua調用C函數的時候,同樣使用棧來交互。C函數從棧中獲取她的參數,調用結束后將結果放到棧中,并返回放到棧中的結果個數。
- 這兒有一個重要的概念:用來交互的棧不是全局棧,每一個C函數都有他自己的私有棧。當Lua調用C函數的時候,第一個參數總是在這個私有棧的index=1的位置。
在main中可以使用lua_dostring(),lua_loadfile(),lua_pcall(L,0,0,0) 來執行lua代碼:
int main(int argc, char* argv[]) {lua_State *L = luaL_newstate();luaL_openlibs(L); // 加載Lua通用擴展庫// 將he函數注冊成lua的全局函數lua_register(L,"he",he);if(luaL_loadfile(L,"test.lua")/*||lua_pcall(L,0,0,0)*/)printf("error pcall!: %s\n",lua_tostring(L,-1));lua_close(L);return 0; }.lua文件文間之間的全局變量調用
比如有兩個文件
//a.lua a = 50 local b = 10//h.lua dofile("X:/.../a.lua") //或在同一個目錄下時:doflie("a.lua"),require會更好 print(a,b)lua中:
h.lua想要調用a.lua中的內容則要在a.lua中運行dofile("X:/.../a.lua")
C++中兩種方法:
- 如上面所示, 在h.lua中使用dofile(“a.lua”), 文件放同一個目錄;
- 或在C代碼加載時先用luaL_dofile(L,"a.lua"); 再luaL_dofile(L,"h.lua"); 順序不能變;
引入C模塊到 lua
- luaL_register
這個函數接收一些C函數及其名稱,并將這些函數注冊到一個與模塊同名的table中。假設創建一個模塊,其中包含了這個luaglue函數。首先,必須定義這個模塊函數:
然后,聲明一個數組,其中包含模塊中所有函數及名稱。這個數組元素的類型為luaL_Reg結構,該結構有兩個字段,一個字符串和一個函數指針:
static const struct luaL_Reg mylib[] = { {"dir",l_dir}, {NULL,NULL}//結尾 };最后,聲明一個主函數,其中用到了luaL_register:
int luaopen_mylib(lua_State *L) {luaL_register(L,"mylib",mylib);return 1; }其中luaL_register原型為:
void luaL_register (lua_State *L,const char *libname,const luaL_Reg *l);luaL_register根據給定的名稱(“mylib”)創建(或復用)一個table,并用數組mylib中的信息填充這個table。在luaL_Register返回時,會將這個table留在棧中。最后,luaopen_mylib函數返回1,表示將這個table返回給Lua。
打開一個庫,當libname為null時,該函數注冊所有在luaL_Reg上的函數,不為null時,該函數會創建一個table,根據libname注冊不與libname關聯的函數。
- 當寫完c模塊后,必須將其鏈接到解釋器。如果Lua解釋器支持動態鏈接的話,那么最簡便的方法是使用動態鏈接機制。在這種情況中,必須將c代碼編譯成動態鏈接庫,并將這個庫放入C路徑(LUA_CPATH)中。然后,便可以用require從Lua中加載這個模塊:
這個調用會將動態庫mylib鏈接到Lua,并會尋找luaopen_mylib函數,將其注冊為一個Lua函數,然后調用它以打開模塊。
如果解釋器不支持動態鏈接,那么就必須用新的模塊來重新編譯Lua。此外,還需要以某種方式來告訴解釋器,它應在打開一個新狀態的同時打開這個模塊。最簡單的做法是,將luaopen_mylib加到luaL_openlibs會打開的標準庫列表中,這個列表在文件linit.c中。
從C++程序員的觀點來看,Lua像一個“黑盒子”,為一些服務處理命令和調用。Lua通常作為最上層接口直接和程序使用者和游戲玩家打交道,在核心程序處理之前接受并響應輸入。
lua5.3 C++注冊函數或模塊到lua
- 上面的那個luaL_register函數在lua5.2以后就沒有用了,所以一直在找5.2以后版本的用法, 網上找了半天都沒有指出重點,最后在下面的網站上找到;
http://acamara.es/blog/2012/08/passing-variables-from-lua-5-2-to-c-and-vice-versa/
結合下面兩篇介紹后這里給出一些理解:
http://www.linuxidc.com/Linux/2014-05/102528p2.htm
http://blog.163.com/cqit_jsj/blog/static/65127220127251231881/
到這里,我們可以選擇去將庫導出為.dll來在lua中調用,這個網上好多資料,在lua中要用local mylib = require "mylib"來獲取.dll文件, 參考
http://blog.csdn.net/ljhjason/article/details/28860633
這里選擇不導出為.dll所以進行如下操作:
注冊C++類到lua
http://blog.csdn.net/siddontang/article/details/2316547
C++ struct對應到lua table
// 壓入表的鍵值對函數(沒有進行棧檢測)
inline void PushTableKV(lua_State* L, const char* k, int v)
{
lua_pushstring(L,k);
lua_pushnumber(L,v);
lua_settable(L,-3);
}
// 使用時候
{
lua_newtable(L)
PushTableKV(L,"v1",10);
....
}
總結
以上是生活随笔為你收集整理的Lua5.3 与C交互学习(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DESC查看表的结构
- 下一篇: js外链跳转_WordPress为any