<sub id="gqw76"><listing id="gqw76"></listing></sub>
      <sub id="gqw76"><listing id="gqw76"></listing></sub>

    1. <form id="gqw76"><legend id="gqw76"></legend></form>
    2. Lua C++交互 應用實例步驟(UserData使用)

      一.配置Lua C++交互環境

          1.下載Lua 包環境

        地址: https://www.lua.org/download.html ,我們這里用的是5.4.2版本。

        2.新建C++ 控制臺應用程序

        3.導入Lua 源碼

        1)導入Lua 源碼到同級目錄(這樣做為了Main函數所在類添加Lua 的C 類的時候直接可以include,不需要考慮目錄層級問題)

        

       

         打開的目錄里,將5.4.2 的lua包里的 src目錄里的文件全部拷到此目錄

        2)添加Lua 源碼

        

       

         選中剛剛導入的Lua文件

        3)編譯

        這時,點擊目錄生成,回發現報錯

       

       這是關鍵報錯信息,重復main頭文件,眾所周知,main函數是啟動函數;那就注釋調main.

      會發現,有兩處main ,lua.c 中 int main 和luac.c int main,分別都注釋了。(或者簡單粗暴,直接將luc.c和luac.c直接刪除也可以)

      再點生成,成功。這兩處main,其實就是如果你將此lua編碼打包成exe,就是啟動函數。但是我們這里不需要這邊的main,我們自己新建的C++ 應用程序,是有自己的Main。

      二.Hello.lua 運行

        新建Lua腳本,必須.lua 結尾。

       

        1.關鍵API

        1)lua與C++交互,必須要一個虛擬棧。可通過lua_State* L = luaL_newstate(); 對于棧的介紹可參考:https://blog.csdn.net/shun_fzll/article/details/39120965,這里就不對棧作描述了。

        2)加載Lua文件,可通過 luaL_dofile 返回一個 int類型,返回結果不為0,則表示異常

        3)Lua有異常,會把返回結果返回到棧頂,也就是說報異常了,可以通過lua_tostring(L,-1)得到報啥錯,再打印出來.

        4)lua_close 就是釋放這個棧。

        5)對于C++調用 C的頭文件,需要extern

       2.實例分析

       1 #include <iostream>
       2 #include <string.h>
       3 using namespace std;
       4 extern "C"
       5 {
       6 #include "lua.h"
       7 #include "lualib.h"
       8 #include "lauxlib.h"
       9 }
      10 int main()
      11 {
      12     std::cout << "Hello World!\n";
      13     lua_State* L = luaL_newstate();
      14     int Ret = luaL_dofile(L, "LuaHello.lua");
      15     if (Ret)
      16     {
      17         string strError = lua_tostring(L, -1);
      18         cout << strError.c_str() << endl;
      19         return -1;
      20     }
      21         
      22     lua_close(L);
      23     return 0;
      24 }

       

        1)運行上述代碼

       

         2)想一下,好像lua代碼是運行了,但是print怎么會nil,并報錯,提示的還挺智能,具體行號都報出來了。

      我們再試著修改Lua代碼中下移兩行試試:

       

        3)咦,那就證明Lua文件是肯定運行了,就是異常了。找不到print,print不是lua庫里的函數嘛,為啥拿不到了。

      因為C++環境中創建Lua_State這個棧,這個默認并沒有打開lua標準庫。所以查一下。

      在 上述Line:13 后面新增 luaL_openlibs(L);

        運行 得到 

       

        恭喜,C++ 與Lua通信成功。

      三.Lua UserData應用實例

        關于具體lua與C交互的一些常見操作,可參考:https://blog.csdn.net/shun_fzll/article/details/39120965

        

        問題:有時候,你會想,我在C++中聲明了一個struct,在lua中,也想聲明這個struct,怎么弄納?接下來這個案例就是教你如何使。

      我們的UserData就是解決這個問題的。

        Lua UserData分兩種,我們這說的是FullUserData,就是可以解決上述問題的UserData.

        直奔主題,看代碼分析。

        Lua5.1之前和之后的注冊函數差距很大,詳情可參考:https://blog.csdn.net/ljhjason/article/details/28860633

        Lua5.1之后可以使用 luaL_requiref 代替 Lua5.1之前的luaL_register ,可參考:https://blog.csdn.net/ljhjason/article/details/28860633

        

       1 #include <iostream>
       2 #include <string.h>
       3 using namespace std;
       4 extern "C"
       5 {
       6 #include "lua.h"
       7 #include "lualib.h"
       8 #include "lauxlib.h"
       9 }
      10 
      11 struct TestCStruct
      12 {
      13     char* Name;
      14     int Num = 1;
      15 };
      16 
      17 int NewTestCStruct(lua_State* L)
      18 {
      19     size_t iBytes = sizeof(struct TestCStruct);
      20     struct TestCStruct* pStruct = (struct TestCStruct*)lua_newuserdata(L, iBytes);
      21     return 1;
      22 }
      23 
      24 int SetNum(lua_State* L)
      25 {
      26     struct TestCStruct *pStruct = (struct TestCStruct*)lua_touserdata(L, 1);
      27     luaL_argcheck(L, pStruct != NULL, 1, "Error Param");
      28     int num = luaL_checkinteger(L, 2);
      29     luaL_argcheck(L, num > 0, 2,"Wrong Paramter");
      30     pStruct->Num = num;
      31     return 1;
      32 }
      33 
      34 int GetNum(lua_State* L)
      35 {
      36     struct TestCStruct *pStruct = (struct TestCStruct*)lua_touserdata(L, 1);
      37     luaL_argcheck(L, pStruct != NULL, 1, "ErrorStruct");
      38     lua_pushinteger(L, pStruct->Num);
      39     return 1;
      40 }
      41 
      42 struct luaL_Reg arrayFunc[] = {
      43 {"new",NewTestCStruct},
      44 {"SetNum",SetNum},
      45 {"SNum",GetNum},
      46 {NULL,NULL}
      47 };
      48 
      49 LUALIB_API int luaopen_mytest(lua_State* L)
      50 {
      51     luaL_newlib(L, arrayFunc);
      52     return 1;
      53 }
      54 
      55 int main()
      56 {
      57     std::cout << "Hello World!\n";
      58     lua_State* L = luaL_newstate();
      59     luaL_openlibs(L);
      60     luaL_requiref(L, "mytest", luaopen_mytest, 0);
      61     int Ret = luaL_dofile(L, "LuaHello.lua");
      62     if (Ret)
      63     {
      64         string strError = lua_tostring(L, -1);
      65         cout << strError.c_str() << endl;
      66         return -1;
      67     }
      68 
      69     lua_close(L);
      70     return 0;
      71 }

      Lua中源碼

      local t = require("mytest")
      print("t:" .. tostring(t))
      
      local y = t.new()
      print("y :" .. tostring(y))
      t.SetNum(y,100)
      print("Num:" ..t.SNum(y))
      local y2 = t.new()
      print("y2 :" .. tostring(y2))
      print("Hello lua and C++")

      運行結果

       綜上, 可以看到Full UserData 的使用,主要核心是Line:60 luaL_requiref的使用。

      https://files.cnblogs.com/files/u3ddjw/TestLuaAndC.rar

      posted @ 2021-03-01 17:01  不三周助  閱讀(169)  評論(2編輯  收藏
      最新chease0ldman老人|无码亚洲人妻下载|大香蕉在线看好吊妞视频这里有精品www|亚洲色情综合网

        <sub id="gqw76"><listing id="gqw76"></listing></sub>
        <sub id="gqw76"><listing id="gqw76"></listing></sub>

      1. <form id="gqw76"><legend id="gqw76"></legend></form>