C++訪問LUA中的函數

來源:互聯網
上載者:User

最近一個COCOS2DX項目有了較大的變化,整個項目的資料層都從C++層移到了LUA層。這下問題就來了,如何在C++層訪問LUA的資料層呢?而我作為一個LUA的新人,那就糾結了,那尼馬還不得啃好幾本書?如果我告訴上司,我需要一周的時間,那估計要被炒掉了。但沒法,任務分配了,開始幹吧。

 

關於在c++代碼中訪問LUA函數的教程,可以說遍布網路的每個角落,大家會去教你如何使用lua_pcall,  lua_getglobal,  lua_pushnumber等。基本要求如下:

1、普通全域函數的訪問(這個容易,如果只有一兩個參數,一兩個返回值,都能應付)

2、表內函數的訪問(這個尼馬,又和表扯到一起了,冒似LUA裡的包也和表是同一概念,尼馬難度提高了)

3、參數和返回值的類型支援INT,STRING,TABLE,參數和返回值的數量支援任意數量。(數量都不是問題,按順序PUSH就完了,如何PUSH一個table呢????這個難度就有點高了,估計親你得回去和度娘好好親熱一番。如果這個table嵌套了TABLE呢???是不是開始蛋疼了?肯定會有某種需求,要向LUA函數傳遞一個二維,甚至三維數組,你敢說這種需求不會出現?)

 

作為程式員的第一感覺,我需要做一個類來管理這所有的事情。於是我設計了一個類LuaAction用來類比整個函數的調用過程。 

LuaAction已經上傳了,下載頁面:http://download.csdn.net/detail/sunshine7858/6357979

 

基本思路如下: 

LuaAction lua;                             //建立一個LuaAction對象  lua.setModule(module);                     //設定包名,如果函數沒有包名,那就跳過這行  lua.setFunction(func);                     //設定要訪問的函數名,  lua.addStringParam(argString);             //添加第一個string參數,如果沒有就跳過  lua.addIntParam(argInt);                   //添加第二個int參數,如果沒有就跳過  lua.addTableParam(argTable);               //添加第三個table參數,如果沒有就跳過  .......                                    //添加更多的參數   lua.executeFunction(resultnum);            //核心函數,要傳入返回值的數量,然後找到要執行的函數,壓入參數,讀取返回值。     string retuslt0 = lua.getStringResult(0);  //擷取第1個SRING返回值  int result1 = lua.getIntResult(1);         //擷取第2個INT返回值  table result2 = lua.getTableResult(2);     //擷取第3個table返回值
....


 

而其中最難的地方,則是如何通過遞迴載入整個table表。而詳細的實現細節比較複雜,就不在這裡贅述了。基本上有了這個類,可以訪問LUA中的所有公用函數,就像你在LUA層一樣。由於LuaAction已經實現了多層表的嵌套,你既可以傳入一個多層的TABLE,也可以返回一個多層的TABLE。這樣就大大方便了LUA和C++的互動。

但LuaAction在使用前,必須調用一次他的初始化函數:

void  LuaAction::initState(LuaState* state);


剩餘的事情就和上面的流程一樣了。

 

有了這個類,可以說一勞永逸,我再也不用去管什麼lua_gettop(),什麼lua_pushstring()等。都見鬼去吧,哥再也不和你們玩了!

但時間長了後,問題又出現了,發現大家經常會訪問一些簡單的函數,可能只有一個參數,或沒有參數,或只是想返回一個值。但在調用時,我還是要瞭解LuaAction的全部對外介面。而且很可能只是一個簡單的string getName()函數我確要寫近5行的代碼,實在不划算啊,看著也累啊。好吧,為了提高代碼的重用性,我將這些常用的函數都封裝了起來。建立了一個LuaAactionFactory類,用來訪問那些常用的函數。如:

 static void void_func_void(const char* module, const char* func); static void void_func_int(const char* module, const char* func, int arg1); static int int_func_void(const char* module, const char* func); static int int_func_int(const char* module, const char* func, int arg1); ........


 

舉個例子:Lua中有一個函數如下

function getName(index)    return tNames[index]end


LuaAction的存取碼:

 LuaAction lua; lua.setModule(module); lua.setFunction(func); lua.addIntParam(arg1); lua.executeFunction(1); return lua.getStringResult(0);


LuaActionFactory存取碼:

int ret = LuaActionFactory::int_func_int(NULL, "getName", 1)

 

最後對2維數組的傳遞和擷取做一下簡單的示範:

 

有LUA函數如下:function func(t)t[1] = 1return tendLuaAction的返問代碼://建立一個要傳遞給函數的table參數LuaParamTable* table = new LuaParamTable();//以下設定各種屬性table->setInt("key1", 11);table->setString("key2", "value1");table->setInt(5, 22);table->setString(6, "value2");//建立子表LuaParamTable* subtable = new LuaParamTable();subtable->setInt("key3", 5556);subtable->setString("key4", "value1");subtable->setInt(3, 444);subtable->setString(4, "value3");//將子表掛到主表中table->setTable("table", subtable);LuaAction lua;                                //啟動LuaAction調用函數lua.setFunction("func");lua.addTableParam(table);                     //壓入表參數lua.executeFunction(1);                       //執行函數LuaParamTable tResult;lua.getTableResultAndClear(&tResult, 0);      //擷取表對象int a = tResult.getIntByIndex(1);             //檢查在LUA中的賦值//將返回值與之前的賦值情況進行對比int value1 = tResult.getIntByKey("key1");string value2 = tResult.getStringByKey("key2");int value3 = tResult.getIntByIndex(5);string value4 = tResult.getStringByIndex(6);LuaParamTable tSubResult;tResult.swapTableByKey("table", &tSubResult);int value5 = tSubResult.getIntByKey("key3");string value6 = tSubResult.getStringByKey("key4");int value7 = tSubResult.getIntByIndex(3);string value8 = tSubResult.getStringByIndex(4);切記:作為表參數時,LuaParamTable是new出來的,因為他的生命週期要交給LuaAction去管理。作為返回值時,LuaParamTable是直接在棧上建立的,因為他自己要管理自己的生命週期。


相信有了以上的工具,基本上大部分的LUA函數都能訪問了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.