Lua与C++交互

文章目录

  • 1、Lua和C++交互
  • 2、基础练习
    • 2.1、加载Lua脚本并传递参数
    • 2.2、加载脚本到stable(包)
    • 2.3、Lua调用c语言接口
    • 2.4、Lua实现面向对象
    • 2.5、向脚本中注册c++的类

1、Lua和C++交互

1、lua和c++交互机制是基于一个虚拟栈,C++和lua之间的所有数据交互都通过这个虚拟栈来完成,无论何时C++想从lua中调用一个值,被请求的值将会被压入栈,C++想要传递一个值给Lua,首选将整个值压栈,然后就可以在Lua中调用。
2、lua中提供正向和反向索引,区别在于证书永远是栈底,负数永远是栈顶。

在这里插入图片描述

2、基础练习

编译指令:g++ test.cpp -o test -llua -ldl

#include <iostream>  
#include <string.h>  
using namespace std;extern "C"
{
#include "lua.h"  
#include "lauxlib.h"  
#include "lualib.h"  
}// g++ test.cpp -o test  -llua -ldl
int main()
{//1.创建一个state  // luaL_newstate返回一个指向堆栈的指针lua_State *L = luaL_newstate();//2.入栈操作  lua_pushstring(L, "hello world");lua_pushnumber(L, 200);//3.取值操作  if (lua_isstring(L, 1)) {             //判断是否可以转为string  cout << lua_tostring(L, 1) << endl;  //转为string并返回  }if (lua_isnumber(L, 2)) {cout << lua_tonumber(L, 2) << endl;}//4.关闭state  lua_close(L);return 0;
}

在这里插入图片描述

2.1、加载Lua脚本并传递参数

编译指令:g++ test.cpp -o test -llua -ldl

函数说明:1、函数用于将Lua脚本加载到Lua虚拟机中并进行编译
luaL_loadbuffer(L,s,sz,n)lua_State *L:Lua状态对象,表示Lua虚拟机的运行实例。const char *buff:指向Lua脚本内容的字符串。size_t sz:Lua脚本内容的长度。const char *name:可选参数,用于给脚本设置一个名称,便于调试和错误消息的输出。返回值:不为0表示有错误2、函数用于调用Lua函数并处理其执行过程中可能发生的错误
lua_pcall(L,n,r,f)lua_State *L:Lua状态对象,表示Lua虚拟机的运行实例。int nargs:传递给Lua函数的参数数量。int nresults:期望的返回值数量。int errfunc:错误处理函数在调用栈中的索引。返回值:不为0表示有错误3、函数用于从全局环境中获取一个全局变量,并将其值压入Lua栈顶
int lua_getglobal(lua_State *L, const char *name)lua_State *L:Lua状态对象,表示Lua虚拟机的运行实例。const char *name:要获取的全局变量的名称。4、函数用于将一个数字(lua_Number类型)压入Lua栈顶
void lua_pushnumber(lua_State *L, lua_Number n)lua_State *L:Lua状态对象,表示Lua虚拟机的运行实例。lua_Number n:要压入栈的数字。

执行流程:
1、加载script脚本加载到lua虚拟机中
2、将脚本中的my_pow函数,压入到栈顶
3、压入my_pow需要的两个参数
4、执行脚本
5、获取脚本中的返回值

#include <cstdio>
#include <cstring>
#include <cmath>
#include <new>
extern "C" {#include <lua.h>#include <lualib.h>#include <lauxlib.h>
}char const *script = R"(
function hello()print('hello world')
endfunction my_pow(x,y)return x^y
end
)";char const *script_1 = R"(pkg.hello()
)";int main()
{/*加载脚本并传递参数*/// 创建lua虚拟机,创建虚拟栈lua_State *state = luaL_newstate();// 打开lua标准库,以便正常使用lua apiluaL_openlibs(state);{// 将lua脚本加载到虚拟机中,并编译auto rst = luaL_loadbuffer(state,script,strlen(script),"hello");// 判断是否加载成功if(rst !=0 ){if(lua_isstring(state,-1)){auto msg = lua_tostring(state,-1);printf("load script faile:%s\n",msg);lua_pop(state,-1);}return -1;}// 执行加载并编译的Lua脚本if(lua_pcall(state,0,0,0)){if(lua_isstring(state,-1)){auto msg = lua_tostring(state,-1);printf("load script faile:%s",msg);lua_pop(state,-1);}}// 从全局环境中获取一个my_pow函数压入到栈顶lua_getglobal(state,"my_pow");// 判断栈顶是不是一个函数,要是不是表示没有找到if(!lua_isfunction(state,-1)){printf("function  named my_pow not function\n");return -1;}// 将数字参数压入Lua栈中lua_pushnumber(state,2);lua_pushnumber(state,8);rst = lua_pcall(state,2,1,0);if(rst !=0 ){if(lua_isstring(state,-1)){auto msg = lua_tostring(state,-1);printf("load script faile:%s\n",msg);lua_pop(state,-1);}return -1;}if(lua_isnumber(state,-1)){lua_Number val = lua_tonumber(state,-1);printf("%lf\n",val);}}lua_close(state);return 0;
}

2.2、加载脚本到stable(包)

编译命令: g++ main.cpp -o main -llua -ldl

#include <cstdio>
#include <cstring>
#include <cmath>
#include <new>
extern "C" {#include <lua.h>#include <lualib.h>#include <lauxlib.h>
}
char const *script = R"(
function hello()print('hello world')
endfunction my_pow(x,y)return x^y
end
)";/*   _G = {"helloworld" = function print("hello world")}_G = {"pkg" = {"helloworld" = function print("hello world")}}pkg.helloworld()
*/char const *script_1 = R"(pkg.hello()
)";int main()
{/*加载脚本到stable(包)1、生成chunk push到栈顶2、创建table,设置给_G表,_G["pkg"] = {}3、给这个table设置元表,元表继承_G的访问域(__index)4、执行code chunk*/lua_State *state = luaL_newstate();luaL_openlibs(state);{auto rst = luaL_loadbuffer(state,script,strlen(script),"helloworld");if(rst != 0){if(lua_isstring(state,-1)){auto msg = lua_tostring(state,-1);printf("load script faile:%s\n",msg);lua_pop(state,1);}return -1;}// 取出_G表lua_getglobal(state,"_G");if(lua_istable(state,-1)){  // chunk _Glua_newtable(state);    // 创建表 chunk _G new_stablelua_pushstring(state,"pkg"); // chunk _G new_stable pkglua_pushvalue(state,-2); // chunk _G new_stable pkg new_stablelua_rawset(state,-4);   // chunk _G new_stablechar const *upvalueName = lua_setupvalue(state,-3,1); // chunk _Glua_newtable(state);    // chunk _G metastablelua_pushstring(state,"__index");    // chunk _G metastable "__index"lua_pushvalue(state,-3); // chunk _G metastable "__index" _Glua_rawset(state,-3);   // chunk _G metastablelua_pushstring(state,"pkg");lua_rawget(state,-3);   // chunk _G metastable "pkg"(table)lua_pushvalue(state,-2);    // chunk _G metastable pkg(table) metastablelua_setmetatable(state,-2); // chunk _G metastable pkg(stable)lua_pop(state,3);   // chunk}// 执行chunkif(lua_pcall(state,0,0,0)){if(lua_isstring(state,-1)){auto msg = lua_tostring(state,-1);printf("call function chunk failed:%s\n",msg);lua_pop(state,1);}}// 加载script_1rst = luaL_loadbuffer(state,script_1,strlen(script_1),"script_1");if(rst != 0){if(lua_isstring(state,-1)){auto msg = lua_tostring(state,-1);printf("load script failed:%s\n",msg);lua_pop(state,1);}return -1;}if(lua_pcall(state,0,0,0)){if(lua_isstring(state,-1)){auto msg = lua_tostring(state,-1);printf("call function chunk failed:%s\n",msg);lua_pop(state,1);}}lua_close(state);}return 0;
}

2.3、Lua调用c语言接口

#include <cstdio>
#include <cstring>
#include <cmath>
#include <new>
extern "C" {#include <lua.h>#include <lualib.h>#include <lauxlib.h>
}int pow_from_c(lua_State *L)
{int param_count = lua_gettop(L);if(param_count != 2)return 0;if(lua_isinteger(L,1) && lua_isinteger(L,2)){auto x = lua_tointeger(L,1);auto y = lua_tointeger(L,2);int rst = (int)pow(x,y);lua_pushinteger(L,rst);return 1;}return 0;
}char const *script_2 = R"(local val = pow_from_c(2,3)print(val)
)";
int main()
{// lua调用c语言接口lua_State *state = luaL_newstate();luaL_openlibs(state);{/*"_G" = {"pow_from_c" = pow_from_c}*/lua_getglobal(state,"_G");lua_pushstring(state,"pow_from_c");lua_pushcclosure(state,pow_from_c,0);    // _G "pow_from_c"; closurelua_rawset(state,-3);   // _Glua_pop(state,1);   // _G}auto rst = luaL_loadbuffer(state,script_2,strlen(script_2),"script_2");if(rst != 0){if(lua_isstring(state,-1)){auto msg = lua_tostring(state,-1);printf("load script faile:%s\n",msg);lua_pop(state,1);}return -1;}if(lua_pcall(state,0,0,0)){if(lua_isstring(state,-1)){auto msg = lua_tostring(state,-1);printf("call function chunk failed:%s\n",msg);lua_pop(state,1);}}lua_close(state);return 0;
}

2.4、Lua实现面向对象

local anial_matestable = {__index = {walk = function (self)print(self,"我是walk")end,eat = function (self)print(self,"eat.")end,},__newindex = function (object,key,value)print("assigned "..value.."named "..key.."but not really")end,
}function newobject()local objs = {name = "xxxx"}setmetatable(objs,anial_matestable)return objs
endlocal obj = newobject()
obj.eat()
obj.walk()
obj.name = "abc"
obj.id = 0

2.5、向脚本中注册c++的类

#include <cstdio>
#include <cstring>
#include <cmath>
#include <new>
extern "C" {#include <lua.h>#include <lualib.h>#include <lauxlib.h>
}
char const *script_3 = R"(local obj_1 = create_game_object(1);local obj_2 = create_game_object(1);local obj_3 = create_game_object(2);local rst1 = obj_1:equal(obj_2)local rst2 = obj_1:equal(obj_3)print(rst1,";",rst2)print(""..obj_1:id())
)";class GameObject{
private:u_int32_t _id;
public:static size_t registy_value;
public:GameObject(u_int32_t id):_id(id){}u_int32_t id()const{return _id;}bool equal(GameObject *obj){return _id == obj->id();}
};
size_t GameObject::registy_value = 0;int GameObject_equal(lua_State *state){int arg_count = lua_gettop(state);if(arg_count!=2){return 0;}if(lua_isuserdata(state,1) && lua_isuserdata(state,2)){void *userdata_self = lua_touserdata(state,1);void *userdata_that = lua_touserdata(state,2);GameObject *obj1 = (GameObject*)userdata_self;GameObject *obj2 = (GameObject*)userdata_that;auto rst = obj1->equal(obj2);lua_pushboolean(state,rst);return 1;}return 0;
}int GameObject_id(lua_State* state){GameObject *this_obj = (GameObject*)lua_touserdata(state,1);auto rst = this_obj->id();lua_pushinteger(state,rst);return 1;
}int create_game_object(lua_State* state){auto id = lua_tointeger(state,1);void *p = lua_newuserdata(state,sizeof(GameObject));GameObject *obj = new(p)GameObject(id);lua_rawgetp(state,LUA_REGISTRYINDEX,&GameObject::registy_value);lua_setmetatable(state,-2);return 1;
}int main()
{// 怎么向脚本中注册c++的类// 使用userdata/*userdata:{metadata:{__index = {equal = function(){},id = function(){},}}}*/lua_State *state = luaL_newstate();luaL_openlibs(state);{lua_getglobal(state,"_G");lua_pushstring(state,"create_game_object");lua_pushcclosure(state,create_game_object,0);lua_rawset(state,-3);lua_pop(state,1);lua_newtable(state);lua_pushstring(state,"__index");lua_newtable(state);lua_pushstring(state,"equal");lua_pushcclosure(state,GameObject_equal,0);lua_rawset(state,-3);lua_pushstring(state,"id");lua_pushcclosure(state,GameObject_id,0);lua_rawset(state,-3);lua_rawset(state,-3);lua_rawsetp(state,LUA_REGISTRYINDEX,&GameObject::registy_value);auto rst = luaL_loadbuffer(state,script_3,strlen(script_3),"oop");if(rst != 0){if(lua_isstring(state,-1)){auto msg = lua_tostring(state,-1);printf("load script failed:%s\n",msg);lua_pop(state,1);}return -1;}// 执行if(lua_pcall(state,0,0,0)){if(lua_isstring(state,-1)){auto msg = lua_tostring(state,-1);printf("load script failed:%s\n",msg);lua_pop(state,1);}}}lua_close(state);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/170105.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SYS/BIOS 开发教程: 创建自定义平台

目录 SYS/BIOS 开发教程: 创建自定义平台创建自定义平台新建工程并指定自定义平台修改现有工程使用自定义平台 参考: TI SYS/BIOS v6.35 Real-time Operating System User’s Guide 6.2节 本示例基于 EVMC6678L 开发板, 创建自定义平台, 并将代码段的位置指定到C6678器件内部的…

安卓主板,人脸识别主板考勤门禁智能门锁安卓主板开发方案

人脸识别主板是一种广泛应用于多个领域的技术&#xff0c;包括人脸支付系统、人脸识别监控系统、写字楼办公楼门禁闸机、校园、地铁、住宅门禁、考勤机、智能门锁、广告机、售卖机以及其他行业应用设计等。这些主板基于联发科MTK方案&#xff0c;由行业PCBA和MTK的核心板组成。…

搭建zlmediakit和wvp_pro

zlmediakit使用zlmediakit/zlmediakit:master镜像 wvp_pro使用648540858/wvp_pro&#xff0c;可参照https://github.com/648540858/wvp-GB28181-pro wvp_pro官方https://doc.wvp-pro.cn/#/ 刚开始我找了个docker镜像运行&#xff0c;后来播放页面一直加载&#xff0c;最后就用了…

Windows下Eclipse C/C++开发环境配置教程

1.下载安装Eclipse 官网下载eclipse-installer&#xff08;eclipse下载器&#xff09;&#xff0c;或者官方下载对应版本zip。 本文示例&#xff1a; Eclipse IDE for C/C Developers Eclipse Packages | The Eclipse Foundation - home to a global community, the Eclipse ID…

自动化测试07Selenium01

目录 什么是自动化测试 Selenium介绍 Selenium是什么 Selenium特点 工作原理 SeleniumJava环境搭建 Selenium常用的API使用 定位元素findElement CSS选择语法 id选择器&#xff1a;#id 类选择 .class 标签选择器 标签名 后代选择器 父级选择器 自己选择器 xpath …

TeeChart for .NET 2023.10.19 Crack

TeeChart.NET 的 TeeChart 图表控件提供了一个出色的通用组件套件&#xff0c;可满足无数的图表需求&#xff0c;也针对重要的垂直领域&#xff0c;例如金融、科学和统计领域。 数据可视化 数十种完全可定制的交互式图表类型、地图和仪表指示器&#xff0c;以及完整的功能集&am…

debian、ubuntu打包deb包工具,图形界面deb打包工具mkdeb

debian、ubuntu打包deb包工具&#xff0c;图形界面deb打包工具mkdeb&#xff0c;目前版本1.0 下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1QX6jXNMYRybI9Cx-1N_1xw?pwd8888 md5&#xff1a; b6c6658408226a8d1a92a7cf93834e66 mkdeb_1.0-1_all.deb

听GPT 讲Rust源代码--library/std(2)

File: rust/library/std/src/sys_common/wtf8.rs 在Rust源代码中&#xff0c;rust/library/std/src/sys_common/wtf8.rs这个文件的作用是实现了UTF-8编码和宽字符编码之间的转换&#xff0c;以及提供了一些处理和操作UTF-8编码的工具函数。 下面对这几个结构体进行一一介绍&…

【学习笔记】Git开发流程

Git开发大致流程图&#xff1a; 具体流程&#xff1a; 首先一个从仓库的main分支&#xff0c;然后从main分支中拉一个功能分支feature/xxx&#xff0c;在多人开发这个功能的时候拉去自己的个人分支比如&#xff1a;xxx/xxx 。然后每天开发完个人分支后压缩commit&#xff0c;…

vue2.x封装svg组件并使用

第一步&#xff1a;安装svg-sprite-loader插件 <!-- svg-sprite-loader svg雪碧图 转换工具 --> <!-- <symbol> 元素中的 path 就是绘制图标的路径&#xff0c;这种一大串的东西我们肯定没办法手动的去处理&#xff0c; 那么就需要用到插件 svg-sprite-loader …

护眼灯有效果吗?五款好用热门的护眼台灯推荐

可以肯定的是&#xff0c;护眼灯一般可以达到护眼的效果。看书和写字时&#xff0c;光线应适度&#xff0c;不宜过强或过暗&#xff0c;护眼灯光线较柔和&#xff0c;通常并不刺眼&#xff0c;眼球容易适应&#xff0c;可以防止光线过强或过暗导致的用眼疲劳。如果平时生活中需…

12、Python -- if 分支 的讲解和使用

目录 程序结构顺序结构分支结构分支结构注意点不要忘记冒号 if条件的类型if条件的逻辑错误if表达式pass语句 程序流程 分支结构 分支结构的注意点 if条件的类型 if语句的逻辑错误 if表达式 程序结构 Python同样提供了现代编程语言都支持的三种流程 顺序结构 分支结构 循环结构…

django建站过程(3)定义模型与管理页

定义模型与管理页 定义模型[models.py]迁移模型向管理注册模型[admin.py]注册模型使用Admin.site.register(模型名)修改Django后台管理的名称定义管理列表页面应用名称修改管理列表添加查询功能 django shell交互式shell会话 认证和授权 定义模型[models.py] 模仿博客形式&…

Mysql如何理解Sql语句?MySql分析器

1. 什么是 MySQL 分析器? MySQL 分析器是 MySQL 数据库系统中的一个关键组件&#xff0c;它负责解析 SQL 查询语句&#xff0c;确定如何执行这些查询&#xff0c;并生成查询执行计划。分析器将 SQL 语句转换为内部数据结构&#xff0c;以便 MySQL 可以理解和执行查询请求。 …

全是干货!2023年双十一买什么最划算、双十一值得买的好物推荐

在双十一前选购到好物&#xff0c;打败99.99%的人&#xff01;看了下日历马上就要到一年一度的购物节了&#xff0c;双十一都想好买什么了吗朋友们&#xff1f;双十一购物狂欢即将来临&#xff0c;你是否已经开始准备购买自己心仪的商品&#xff1f;在这个购物狂欢节中&#xf…

【算法小课堂】深入理解前缀和算法

前缀和是指某序列的前n项和&#xff0c;可以把它理解为数学上的数列的前n项和&#xff0c;而差分可以看成前缀和的逆运算。合理的使用前缀和与差分&#xff0c;可以将某些复杂的问题简单化。 我们通过一个例子来理解前缀和算法的优势&#xff1a; 一维前缀和&#xff1a; ww…

Unity Spine 指定导入新Spine动画的默认材质

指定导入新Spine动画的默认材质 找到Spine的Editor导入配置如何修改方法一: 你可以通过脚本 去修改Assets/Editor/SpineSettings.asset文件方法二&#xff1a;通过面板手动设置 找到Spine的Editor导入配置 通常在 Assets/Editor/SpineSettings.asset 配置文件对应着 Edit/Prefe…

2018年亚太杯APMCM数学建模大赛B题人才与城市发展求解全过程文档及程序

2018年亚太杯APMCM数学建模大赛 B题 人才与城市发展 原题再现 招贤纳士是过去几年来许多城市的亮点之一。北京、上海、武汉、成都、西安、深圳&#xff0c;实际上都在用各种吸引人的政策来争夺人才。人才代表着城市创新发展的动力&#xff0c;因为他们能够在更短的时间内学习…

Zip密码忘记了,如何破解密码?

Zip压缩包设置了密码&#xff0c;解压的时候就需要输入正确对密码才能顺利解压出文件&#xff0c;正常当我们解压文件或者删除密码的时候&#xff0c;虽然方法多&#xff0c;但是都需要输入正确的密码才能完成。忘记密码就无法进行操作。 那么&#xff0c;忘记了zip压缩包的密…

Linux部署Redis哨兵集群 一主两从三哨兵(这里使用Redis6,其它版本类似)

目录 一、哨兵集群架构介绍二、下载安装Redis2.1、选择需要安装的Redis版本2.2、下载并解压Redis2.3、编译安装Redis 三、搭建Redis一主两从集群3.1、准备配置文件3.1.1、准备主节点6379配置文件3.1.2、准备从节点6380配置文件3.1.3、准备从节点6381配置文件 3.2、启动Redis主从…