我爱代码 - 专业游戏安全与逆向论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 78|回复: 0

lua 和 c++ 交互 Demo

[复制链接]

2388

主题

53

回帖

9187

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
9187
QQ
发表于 6 天前 | 显示全部楼层 |阅读模式

想要查看内容赶紧注册登陆吧!

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. #include <lua.hpp>
  2. #include <iostream>

  3. using namespace std;

  4. int simple_test(lua_State *L) {
  5.     cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  into simple_test" << endl;
  6.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  7.     // 获取lua脚本传过来的参数
  8.     const char *name = lua_tostring(L, -2);
  9. //    size_t len;
  10. //    const char *name = lua_tolstring(L, -2, &len);
  11.     lua_Integer age = lua_tointeger(L, -1);
  12.     lua_pop(L, 2);

  13.     cout << "name:" << name << "  age:" << age << endl;

  14.     // lua脚本调用函数的返回值
  15.     lua_pushinteger(L, 99);

  16.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  17.     return 1;
  18. }

  19. int array_test(lua_State *L) {
  20.     cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  into array_test" << endl;
  21.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  22.     luaL_checktype(L, 1, LUA_TTABLE);

  23.     // 方法 1
  24.     {
  25.         // 因为lua_next 的第1步会先从栈顶弹出一个key, 如果没值会出错,所以这里压个nil,让其不出错
  26.         lua_pushnil(L);

  27.         // lua_next(L, 1) =>   1 是 table在栈中的位置
  28.         // 1. 先从栈顶弹出一个key (因为是数组,所以这个key就是序号了)
  29.         // 2. 从栈指定位置的table中取一对 key-value, 先将key入栈,再将value入栈
  30.         // 3. 如果第2步成功则返回非0值, 否则返回0, 且不向栈中压入任何值
  31.         while (lua_next(L, 1) != 0) {
  32.             cout << "key: " << lua_tonumber(L, -2) << "  value: " << lua_tostring(L, -1) << endl;

  33.             // lua_next会把key弹掉, 所以这里只要弹掉value即可恢复栈
  34.             lua_pop(L, 1);
  35.         }
  36.         lua_pop(L, 1);  // 弹出table
  37.     }

  38.     // 方法 2
  39.     {
  40. //        size_t n = lua_objlen(L, -1);
  41. //        for (int i = 1; i <= n; ++i) {
  42. //            // 索引号压栈
  43. //            lua_pushnumber(L, i);
  44. //
  45. //            //  1. 上一步的num出栈(pop number) , 这里 num = i
  46. //            //  2. 通过这个num,获取索引号对应的值table[num]
  47. //            //  3. 把这个值table[num] 压栈 (push table[num] )
  48. //            lua_gettable(L, 1);
  49. //
  50. //            //  获取这个值table[num]
  51. //            cout << lua_tostring(L, -1) << endl;
  52. //
  53. //            // 出栈, 1 是出栈的数量
  54. //            lua_pop(L, 1);
  55. //        }
  56. //        lua_pop(L, 1);  // 弹出table
  57.     }

  58.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  59.     return 0;
  60. }

  61. int map_test(lua_State *L) {
  62.     cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  into map_test" << endl;
  63.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  64.     luaL_checktype(L, 1, LUA_TTABLE);

  65.     // 方法 1
  66.     {
  67.         // 因为lua_next 的第1步会先从栈顶弹出一个key, 如果没值会出错,所以这里压个nil,让其不出错
  68.         lua_pushnil(L);

  69.         // lua_next(L, 1) =>   1 是 table在栈中的位置
  70.         // 1. 先从栈顶弹出一个key
  71.         // 2. 从栈指定位置的table中取一对 key-value, 先将key入栈,再将value入栈
  72.         // 3. 如果第2步成功则返回非0值, 否则返回0, 且不向栈中压入任何值
  73.         while (lua_next(L, 1) != 0) {
  74.             cout << "key: " << lua_tostring(L, -2) << "  value: " << lua_tostring(L, -1) << endl;

  75.             // lua_next会把key弹掉, 所以这里只要弹掉value即可恢复栈
  76.             lua_pop(L, 1);
  77.         }
  78.         lua_pop(L, 1); // 弹出table
  79.     }

  80.     // 方法 2 (根据key 获取 value)
  81. //    {
  82. //        lua_getfield(L, 1, "a");        // 获取到 table["a"] 的值, 压入栈顶
  83. //        cout << "a => " << lua_tostring(L, -1) << endl;
  84. //
  85. //        lua_getfield(L, 1, "b");
  86. //        cout << "b => " << lua_tostring(L, -1) << endl;
  87. //
  88. //        lua_getfield(L, 1, "c");
  89. //        cout << "c => " << lua_tostring(L, -1) << endl;
  90. //
  91. //        lua_getfield(L, 1, "d");
  92. //        cout << "d => " << lua_tostring(L, -1) << endl;
  93. //
  94. //        lua_pop(L, 5);  // 全部弹出
  95. //    }

  96.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  97.     return 0;
  98. }

  99. int checkType_test(lua_State *L) {
  100.     cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  into checkType_test" << endl;
  101.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  102.     // luaL_checktype , 一旦类型不符合, 代码不会继续执行
  103.     luaL_checktype(L, -1, LUA_TBOOLEAN);
  104.     cout << "第1个参数类型检查通过" << endl;

  105.     // lua_type , 就算类型不符合, 代码也会继续执行
  106.     int nType = lua_type(L, -2);
  107.     if (nType != LUA_TNUMBER) {
  108.         cout << "第2个参数类型不符合" << endl;
  109. //        luaL_argerror(L, -2, "参数类型不符合");
  110.     }

  111.     lua_pop(L, 2);

  112.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  113.     return 0;
  114. }

  115. int ret_test(lua_State *L) {
  116.     cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  into ret_test" << endl;
  117.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  118.     lua_pushstring(L, "张三");
  119.     lua_pushnumber(L, 12);

  120.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  121.     return 2;
  122. }

  123. int ret_table_test(lua_State *L) {
  124.     cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  into ret_table_test" << endl;
  125.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  126.     // 创建表,压栈
  127.     lua_newtable(L);

  128.     // 一对key  value 入栈
  129.     // 压入key
  130.     lua_pushstring(L, "name");
  131.     // 压入value
  132.     lua_pushstring(L, "张三");

  133.     // 此时,表在栈底
  134.     // 弹出 key  value 设置到表.  此时,表在栈顶了
  135.     lua_settable(L, 1);

  136.     //-------------------------------
  137.     // 一对key  value 入栈
  138.     // 压入key
  139.     lua_pushstring(L, "age");
  140.     // 压入value
  141.     lua_pushinteger(L, 22);

  142.     // 此时,表在栈底
  143.     // 弹出 key  value 设置到表.  此时,表在栈顶了
  144.     lua_settable(L, 1);


  145.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  146.     return 1;
  147. }

  148. int getLuaVar_test(lua_State *L) {
  149.     cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  into getLuaVar_test" << endl;
  150.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  151.     lua_getglobal(L, "g_var1");
  152.     lua_Number num = lua_tonumber(L, -1);
  153.     cout << "g_var1 = " << num << endl;
  154.     lua_pop(L, 1);

  155.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  156.     return 0;
  157. }

  158. int set2LuaVar_test(lua_State *L) {
  159.     cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  into set2LuaVar_test" << endl;
  160.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  161.     lua_pushstring(L, "赵六");

  162.     // 将栈顶位置设置为全局变量,并出栈
  163.     lua_setglobal(L, "g_name");

  164.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  165.     return 0;
  166. }


  167. int getLuaVar_table_test(lua_State *L) {
  168.     cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  into getLuaVar_table_test" << endl;
  169.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  170.     // 一层map
  171.     {
  172.         cout << "----------- 一层map ----------" << endl;

  173.         lua_getglobal(L, "g_t1");
  174.         {
  175.             lua_getfield(L, -1, "name");  // name的值入栈
  176.             const char *name = lua_tostring(L, -1);
  177.             cout << "name = " << name << endl;
  178.             lua_pop(L, 1);  // 弹掉 name

  179.             lua_getfield(L, -1, "age");  // age的值入栈
  180.             lua_Number age = lua_tonumber(L, -1);
  181.             cout << "age = " << age << endl;
  182.             lua_pop(L, 1);  // 弹掉 age
  183.         }
  184.         lua_pop(L, 1);  //  弹掉 g_t1

  185.         cout << "当前栈上数量 = " << lua_gettop(L) << endl;
  186.     }

  187.     // 嵌套的map
  188.     {
  189.         cout << "----------- 嵌套的map ---------" << endl;

  190.         lua_getglobal(L, "g_t2");
  191.         {
  192.             // 因为lua_next 的第1步会先从栈顶弹出一个key, 如果没值会出错,所以这里压个nil,让其不出错
  193.             lua_pushnil(L);

  194.             // lua_next(L, 1) =>   1 是 table在栈中的位置
  195.             // 1. 先从栈顶弹出一个key
  196.             // 2. 从栈指定位置的table中取一对 key-value, 先将key入栈,再将value入栈
  197.             // 3. 如果第2步成功则返回非0值, 否则返回0, 且不向栈中压入任何值
  198.             while (lua_next(L, 1) != 0) {
  199.                 lua_Number key = lua_tonumber(L, -2);
  200.                 cout << "key: " << key << endl;

  201.                 // 取value的值, 这里的value就是子table, 在栈顶
  202.                 {
  203.                     lua_getfield(L, -1, "name");  // 子table中name的值入栈
  204.                     cout << "value: " << lua_tostring(L, -1) << endl;
  205.                     lua_pop(L, 1);  // 弹掉 name

  206.                     lua_getfield(L, -1, "age");   // 子table中age的值入栈
  207.                     cout << "age: " << lua_tonumber(L, -1) << endl;
  208.                     lua_pop(L, 1); // 弹掉 age
  209.                 }

  210.                 // lua_next会把key弹掉, 所以这里只要弹掉value(子table)即可恢复栈
  211.                 lua_pop(L, 1);
  212.                 cout << "**********" << endl;
  213.             }
  214.         }
  215.         lua_pop(L, 1); // 弹掉 g_t2
  216.         cout << "当前栈上数量 = " << lua_gettop(L) << endl;
  217.     }

  218.     return 0;
  219. }

  220. int setLuaVar_table_test(lua_State *L) {
  221.     cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  into setLuaVar_table_test" << endl;
  222.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  223.     // 创建表,压栈
  224.     lua_newtable(L);

  225.     // 一对key  value 入栈
  226.     // 压入key
  227.     lua_pushstring(L, "name");
  228.     // 压入value
  229.     lua_pushstring(L, "张三");

  230.     // 此时,表在栈底
  231.     // 弹出 key  value 设置到表.  此时,表在栈顶了
  232.     lua_settable(L, 1);

  233.     //-------------------------------
  234.     // 一对key  value 入栈
  235.     // 压入key
  236.     lua_pushstring(L, "age");
  237.     // 压入value
  238.     lua_pushinteger(L, 22);

  239.     // 此时,表在栈底
  240.     // 弹出 key  value 设置到表.  此时,表在栈顶了
  241.     lua_settable(L, 1);

  242.     // 将此表设置为全局变量
  243.     lua_setglobal(L, "g_varTable");

  244.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  245.     return 0;
  246. }

  247. void callLuaFunc_simple(lua_State *L) {
  248.     cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  into callLuaFunc_simple" << endl;
  249.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  250.     const string luaFuncName = "luaSimpleFunc";
  251.     lua_getglobal(L, luaFuncName.c_str());  // 获取lua函数
  252.     if (lua_pcall(L, 0, 0, 0) != 0)   // 调用失败
  253.     {
  254.         // 失败会产生错误,这个错误会压栈。 这里把它出栈,以免内存泄露
  255.         cout << "call " << luaFuncName << " failed ! error = " << lua_tostring(L, -1) << endl;
  256.         lua_pop(L, 1);
  257.     }

  258.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;
  259. }

  260. void callLuaFunc_params_ret(lua_State *L) {
  261.     cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  into callLuaFunc_params_ret" << endl;
  262.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;

  263.     const char* luaErrorFuncName = "fError";
  264.     lua_getglobal(L, luaErrorFuncName);   // 获取lua错误处理函数

  265.     const char* luaFuncName = "luaParamsAndRetFunc";
  266.     lua_getglobal(L, luaFuncName);  // 获取lua函数

  267.     lua_pushstring(L, "张三");   // 参数1
  268.     lua_pushinteger(L, 23);     // 参数2

  269.     lua_newtable(L);               // 参数3
  270.     // 表在栈中的位置
  271.     int tIdx =  lua_gettop(L);
  272.     // 压入key
  273.     lua_pushstring(L, "score");
  274.     // 压入value
  275.     lua_pushnumber(L, 91.5);
  276.     // 弹出 key  value 设置到表.  此时,表在栈顶了
  277.     lua_settable(L, tIdx);

  278.     // 别忘了设置: 参数个数 、 返回值个数 、 错误处理函数在栈的位置
  279.     if (lua_pcall(L, 3, 2, -5) != 0)   // 调用失败
  280.     {
  281.         cout << "call " << luaFuncName << " failed ! error = " << lua_tostring(L, -2) << endl;
  282.         // 失败会产生错误,这个错误会压栈。 这里把它出栈,以免内存泄露
  283.         lua_pop(L, 1);
  284.     } else {
  285.         // 获取返回值1
  286.         cout << "ret1 = " << lua_tostring(L, -2) << endl;

  287.         // 获取返回值2 (table)
  288.         // 这里演示直接获取字段值。 如要全表遍历,参考之前的代码
  289.         lua_getfield(L, -1, "name");
  290.         cout << "name = " << lua_tostring(L, -1) << endl;
  291.         lua_pop(L, 1);
  292.         lua_getfield(L, -1, "age");
  293.         cout << "age = " << lua_tointeger(L, -1) << endl;
  294.         lua_pop(L, 1);

  295.         // 这里把它出栈,以免内存泄露
  296.         lua_pop(L, 2);    //  有2个返回值
  297.     }

  298.     // 弹出错误处理函数,以免内存泄露
  299.     lua_pop(L, 1);

  300.     cout << "当前栈上数量 = " << lua_gettop(L) << endl;
  301. }

  302. int main() {
  303.     cout << " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> start <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << endl;

  304.     // 创建状态机
  305.     lua_State *L = luaL_newstate();

  306.     // 打开基本库
  307.     luaL_openlibs(L);

  308.     // 获取lua传递过来的普通参数测试 (给lua写的函数)
  309.     lua_register(L, "simple_test", simple_test);

  310.     // 获取lua传递过来的array参数测试 (给lua写的函数)
  311.     lua_register(L, "array_test", array_test);

  312.     // 获取lua传递过来的map参数测试 (给lua写的函数)
  313.     lua_register(L, "map_test", map_test);

  314.     // lua传递过来的参数类型检查测试 (给lua写的函数)
  315.     lua_register(L, "checkType_test", checkType_test);

  316.     // lua调用C++函数的返回值测试 (给lua写的函数)
  317.     lua_register(L, "ret_test", ret_test);

  318.     // lua调用C++函数的返回值(table)测试 (给lua写的函数)
  319.     lua_register(L, "ret_table_test", ret_table_test);

  320.     // 给lua传递c++全局变量值 (lua可用的C++全局变量)
  321.     set2LuaVar_test(L);

  322.     // 给lua传递c++全局变量值(table) (lua可用的C++全局变量)
  323.     setLuaVar_table_test(L);

  324.     // -------- 调用脚本前 ---------

  325.     luaL_dofile(L, "test1.lua");

  326.     // -------- 调用脚本后 ---------

  327.     // c++获取lua的全局变量值 (C++可用的lua全局变量)
  328.     getLuaVar_test(L);

  329.     // c++获取lua的全局变量值(table) (C++可用的lua全局变量)
  330.     getLuaVar_table_test(L);

  331.     // c++调用lua函数
  332.     callLuaFunc_simple(L);

  333.     // c++调用lua函数(带参数和返回值)
  334.     callLuaFunc_params_ret(L);

  335.     // 关闭
  336.     lua_close(L);

  337.     cout << " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> end <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<";

  338.     return 0;
  339. }
复制代码
  1. --- test1.lua ---
  2. --- Generated by EmmyLua(https://github.com/EmmyLua)
  3. --- Created by saber.
  4. --- DateTime: 2022/7/6 17:38
  5. ---

  6. ------------ array_test ---------------
  7. local t1 = { "张三", "李四", "abc", "1234" }
  8. array_test(t1)
  9. -------------- map_test -------------
  10. local t2 = { a = "张三", b = "李四", c = "abc", d = "1234" }
  11. map_test(t2)

  12. --------------- checkType_test ------------
  13. checkType_test("abc", true)

  14. ------------- simple_test --------------
  15. local score = simple_test("张三", 12)
  16. print("score = ", score)
  17. score = nil

  18. ------------- ret_test --------------
  19. local ret1, ret2 = ret_test()
  20. print("ret1 = ", ret1, "  ret2 = ", ret2)
  21. ret1 = nil
  22. ret2 = nil

  23. ------------- ret_table_test --------------
  24. local t3 = ret_table_test()
  25. print("t3 = ", t3)
  26. for i, v in pairs(t3) do
  27.     print(i .. " => " .. v)
  28. end

  29. t3 = nil

  30. ------------- getLuaVar_test --------------
  31. g_var1 = 13.4

  32. ----------- getLuaVar_table_test -------------
  33. g_t1 = {
  34.     name = "王五", age = 22,
  35. }

  36. g_t2 = {
  37.     { name = "张三", age = 21 },
  38.     { name = "王五", age = 22 },
  39.     { name = "李明", age = 12 },
  40. }

  41. ---------- set2LuaVar_test -------------
  42. print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  lua get c++ global var")
  43. print("c++ g_name = " .. g_name)

  44. ----------- setLuaVar_table_test ------------
  45. print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  lua get c++ global table var")
  46. print("g_varTable ==> ", g_varTable)
  47. print("g_varTable name ==> " .. g_varTable["name"])

  48. ----------- callLuaFunc_simple -------------

  49. function luaSimpleFunc1()
  50.     -- 测试错误用
  51.     --function luaSimpleFunc()
  52.     print("c++ call lua func simple")
  53. end

  54. ---------------- callLuaFunc_params_ret -------------------
  55. --function luaParamsAndRetFunc1(name, age, t)  -- 测试错误用
  56. function luaParamsAndRetFunc(name, age, t)
  57.     --function luaSimpleFunc()
  58.     print("c++ call lua params and ret func")
  59.     print("name = ", name, "  age = ", age, "  t = ", t, "  t.score = ", t.score)
  60.     local retTable = { name = "saber", age = 20 }
  61.     return "this is a lua params_return func return", retTable
  62. end

  63. function fError(e)
  64.     print("原始Error = ", e)
  65.     return "这是自定义错误处理函数返回的错误,将覆盖原始返回的错误"
  66. end
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|我爱代码 - 专业游戏安全与逆向论坛 ( 陇ICP备17000105号-1 )

GMT+8, 2025-11-3 12:26 , Processed in 0.045463 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表