当前位置: 首页 > news >正文

【C++/Lua联合开发】 (三) C++调用Lua

文章目录

  • C++调用Lua
    • 1. C++调用Lua全局变量(普通类型)
    • 2. C++给Lua传递全局变量
    • 3. C++调用Lua全局变量(表)
    • 4. C++给Lua传递全局变量表
    • 5. C++调用Lua函数
      • 5.1 基础调用
      • 5.2 调用Lua函数传递参数
      • 5.3 errfunc
      • 5.4 返回table

C++调用Lua

  • 全局变量访问(普通,表),函数调用(参数,返回值)

  • 注意栈空间清理,防止内存泄漏

1. C++调用Lua全局变量(普通类型)

lua_getglobal(L, "width");   //取出全局变量"width"并压栈
int width = lua_tointeger(L, -1);
lua_pop(L, 1);                    //栈顶出栈
cout << "width: " << width << endl;
width = 1920

2. C++给Lua传递全局变量

luaL_loadfile 调用前执行,设置全局变量cname

lua_pushstring(lua, "c name value");   //压栈
lua_setglobal(lua, "cname");   

lua_setglobal(L, "cname") 把栈顶的值弹出并设置为全局变量 cname(在 Lua中相当于 _G[“cname”] = value)

3. C++调用Lua全局变量(表)

-- main.lua
conf = {title = "My Title",height = 200
}
// main.cpp
lua_getglobal(L, "conf");  // [conf]
lua_getfield(L, -1, "title");  // [conf  "My Title"]
cout << "title: " << lua_tostring(L, -1) << endl;  
lua_pop(L, 1);            // [conf]lua_getfield(L, -1, "height");    [conf  200]
cout << "height: " << lua_tointeger(L, -1) << endl;
lua_pop(L, 1);     // [conf]

4. C++给Lua传递全局变量表

lua_newtable(L);      //[..., table]
lua_pushstring(L, "skan"); // [..., table, "skan"]
//把栈顶值作为value,弹出它并设置索引-2处表的字段name,等价于table["name"]=value
lua_setfield(L, -2, "name");  // [..., table]lua_pushinteger(L, 42);
lua_setfield(L, -2, "age");lua_setglobal(L, "person");
-- main.lua
print("person name: " .. person.name)
print("person age: " .. person.age)

5. C++调用Lua函数

注意点:

  1. 堆栈
  2. 多线程调用(dispatch的方式)

5.1 基础调用

function lua_event() print("Event triggered")
end
lua_getglobal(L, "lua_event");
if (!lua_isfunction(L, -1)) {// 不是函数:弹出并忽略lua_pop(L, 1); // 栈恢复
}
else {int ret = lua_pcall(L, 0, 0, 0); // 弹出函数并调用if (ret != LUA_OK) {const char* err = lua_tostring(L, -1); // 栈顶是错误信息printf("call event error: %s\n", err);lua_pop(L, 1); // 弹出错误信息}
}
  • lua_getglobal(L, "lua_event"):把全局变量 lua_event的值压入栈顶(不弹出任何东西)。

    • 调用前(假设栈为空):[]
    • 调用后:[ lua_event_value ](栈顶索引 -1)
  • lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)的行为:

    • 要求栈顶是一个可调用值(function)。lua_pcall会弹出该函数和传入的参数(此处 nargs=0),在保护模式下调用它。
    • 成功返回(ret == LUA_OK):根据 nresults=0,不会把函数的返回值压回栈,最终栈回到调用前的状态(即如果之前只有函数,则变为空栈)。
    • 调用前:[ function ] → 调用后(成功):[]
    • 失败返回(ret != LUA_OK):lua_pcall在栈顶压入错误信息(error message),并返回错误码。
      • 调用后(出错):[ error_msg ]
  • 如果 lua_event不是函数(例如 niltable),直接 lua_pcall会失败并在栈上留下错误信息("attempt to call a … "),应先用 lua_isfunctionlua_type检查

5.2 调用Lua函数传递参数

function lua_event(e1) print("Event triggered")print(e1)return "test lua_event"
end
lua_getglobal(L, "lua_event");
if (!lua_isfunction(L, -1)) {// 不是函数:弹出并忽略lua_pop(L, 1); // 栈恢复
}
else {lua_pushstring(L, "hello from C");  lua_newtable(L);lua_pushstring(L, "skan");lua_setfield(L, -2, "name");int ret = lua_pcall(L, 2, 1, errfunc_pos); // 弹出函数并调用if (ret != LUA_OK) {const char* err = lua_tostring(L, -1); // 栈顶是错误信息printf("call event error: %s\n", err);lua_pop(L, 1); // 弹出错误信息}else {printf("lua return: %s\n", lua_tostring(L, -1));lua_pop(L, 1);}
}

5.3 errfunc

-- main.lua
function my_error_handler(err)return "Custom error: " .. tostring(err)
endnd
// ...existing code...
int errfunc_pos = lua_gettop(L) + 1; 
lua_getglobal(L, "my_error_handler");  // 压入错误处理函数,假设索引为 1
// 栈: [..., my_error_handler]
lua_getglobal(L, "lua_event");  // 压入要调用的函数
lua_pushstring(L, "hello from C");  // 参数
// 栈: [..., my_error_handler, lua_event, "hello from C"]int ret = lua_pcall(L, 1, 1, errfunc_pos);
if (ret != LUA_OK) {const char* err = lua_tostring(L, -1);  // 栈顶是 errfunc 返回的字符串printf("Handled error: %s\n", err);lua_pop(L, 1);
} else {printf("Success: %s\n", lua_tostring(L, -1));lua_pop(L, 1);
}
lua_pop(L, 1); // errfunc出栈

5.4 返回table

lua_pushstring(L, "hello from C");  
lua_newtable(L);
lua_pushstring(L, "skan");
lua_setfield(L, -2, "name");
int ret = lua_pcall(L, 2, 1, errfunc_pos); // 弹出函数lua_event("hello from C", tab1)并调用
if (ret != LUA_OK) {const char* err = lua_tostring(L, -1); // 栈顶是错误信息printf("call event error: %s\n", err);lua_pop(L, 1); // 弹出错误信息
}
else {lua_getfield(L, -1, "result");if (lua_isstring(L, -1))cout << "result: " << lua_tostring(L, -1) << endl;else if (lua_isnumber(L, -1))cout << "result: " << lua_tonumber(L, -1) << endl;elsecout << "result: " << lua_typename(L, lua_type(L, -1)) << endl;lua_pop(L, 2);
}
function lua_event(e1, tb2) print("Event triggered")print(e1)print(tb2.name)return {result = "success"}
end
http://www.dtcms.com/a/499425.html

相关文章:

  • 网站开发与黑客做网站维护需要懂什么
  • C++动态规划——LIS(最长不下降子序列)
  • 计算 CIDR 块包含 C 类地址数量的方法
  • [创业之路-702]:“第三次”与“第四次工业革命”的范式跃迁
  • php 简单购物网站diy定制网站
  • 《vector.pdf 深度解读:vector 核心接口、扩容机制与迭代器失效解决方案》
  • Linux中slab缓存初始化kmem_cache_init函数和定时回收函数的实现
  • 南头专业的网站建设公司厦门网站建设公司怎么选
  • 郑州市做网站的公司西安有什么好玩的地方吗
  • Java 大视界 -- 金融市场情绪预测与动态决策的 Java 大数据实战(2024 券商落地版 425)
  • 运维干货:Nginx 常用配置与问题排查指南
  • 条款16:保证const成员函数的线程安全性
  • 网站开发需求现在网站怎么备案
  • 巧用LEF实现row aware track规划
  • 大话数据结构之 <栈> 和<队列>(C语言)
  • Windows 系统的 Delivery Optimization后台用了几GB流量,如何暂停?
  • 基于ads1256的ADC控制实现
  • 建站之星破解版手机正规建网站企业
  • 建一个电商网站要多少钱wordpress及时聊天
  • 云端思维导图软件,多设备同步无压力
  • Python Web 开发:从框架到实战案例
  • 做网站每天任务及实训过程公司关于网站建设的通知
  • 网站联系方式修改织梦网站建设是在商标哪个类别
  • 网站管理员密码在哪里找个人做网站的
  • C# 中,依赖注入(DI)的实现方式
  • java微服务驱动的社区平台:友猫社区的功能模块与实现逻辑
  • Flask入门教程——李辉 第三章 关键知识梳理
  • 产品更新与重构策略:创新与稳定的平衡之道
  • 【微服务】(1) Spring Cloud 概述
  • 做外贸球衣用什么网站嘉兴做微网站