zoukankan      html  css  js  c++  java
  • 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!
    ";
    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!
    ";
    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

    学以致用,不致用,何学?
  • 相关阅读:
    递归斐波那契数列时间复杂度
    动态规划 矩阵链乘法
    kmp算法
    贪心 单源最短路径
    贪心法 背包问题求解
    贪心法 货币支付问题或找零问题
    贪心算法简介
    排列问题的递归算法和非递归算法
    php __set() __get() __isset() __unset()四个方法的应用
    使用栈结构完毕四则运算
  • 原文地址:https://www.cnblogs.com/u3ddjw/p/14449605.html
Copyright © 2011-2022 走看看