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;
}
相关文章:
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之间的所有数据交互都通…...
Ubuntu安装pyenv,配置虚拟环境
文章目录 安装pyenvpyenv创建虚拟环境一般情况下创建虚拟环境的方法 安装pyenv 摘自:文章 pyenv可以管理不同的python版本 1、安装pyenv的依赖库 # 执行以下命令安装依赖库 # 更新源 sudo apt-get update # 更新软件 sudo apt-get upgradesudo apt-get install ma…...
【分布式技术专题】「分布式技术架构」MySQL数据同步到Elasticsearch之N种方案解析,实现高效数据同步
MySQL数据同步到Elasticsearch之N种方案解析,实现高效数据同步 前提介绍MySQL和ElasticSearch的同步双写优点缺点针对于缺点补充优化方案 MySQL和ElasticSearch的异步双写优点缺点 定时延时写入ElasticSearch数据库机制优点缺点 开源和成熟的数据迁移工具选型Logsta…...
什么是React中的高阶组件(Higher Order Component,HOC)?它的作用是什么?
聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...
NEFU离散数学实验3-递推方程
相关概念 递推方程是指一种递归定义,它将问题拆分成更小的子问题,并使用这些子问题的解来计算原问题的解。离散数学中,递推方程通常用于描述数列、组合问题等。 以下是一些递推方程相关的概念和公式: 1. 递推公式:递推…...
如何为你的地图数据设置地图样式?
地图样式设置是GIS系统中非常重要的功能模块,水经微图Web版本最近对符号样式功能模块进行了升级。 你可以通过以下网址直接打开访问: https://map.wemapgis.com 现在我们为大家分享一下水经微图Web版中,如何为你标注的地图数据设置地图样式…...
解决visual studio Just-In-Time Debugger调试
解决visual studio Just-In-Time Debugger调试 网上流行很多方法,最后一直不行,其实有最简单的方法比较实用 方法一:把 C:\WINDOWS\system32\vsjitdebugger.exe,删除了,若怕出问题,可以把它改名或者做个rar文件暂时保留…...
Uservue 中 keep-alive 组件的作用
目录 前言 用法 代码 理解 keep-alive 是 Vue.js 中一个内置的组件,它能够将不活动的组件实例保存在内存中,防止其被销毁,以便在后续需要时能够快速重新渲染。这个功能在一些需要频繁切换但不希望每次都重新渲染的场景中非常有用…...
gitlab查看、修改用户和邮箱,gitlab生成密钥
查看用户、邮箱 git config user.name git config user.email 修改用户、邮箱 git config --global user.name “xxx” git config --global user.email “xxxxxx.com” 生成ssh密钥 ssh-keygen -t rsa -C “xxxxxx.com” 查看SSH秘钥 cat ~/.ssh/id_rsa.pub 将秘钥复制&…...
python操作MySQL、SQL注入问题、视图、触发器、事务、存储过程、函数、流程控制、索引(重点)
python操作MySQL(重要) SQL的由来: MySQL本身就是一款C/S架构,有服务端、有客户端,自身带了有客户端:mysql.exe python这门语言成为了MySQL的客户端(对于一个服务端来说,客户端可以有很多) 操作步骤: …...
这一年的资源
#线性代数 https://textbooks.math.gatech.edu/ila/one-to-one-onto.html行业规范https://xlinux.nist.gov/dads/https://www.dhs.gov/publications产业群链基金会 https://www.cncf.io/谷歌 https://opensource.google/projects网飞 高德纳 https://www.gartne…...
从【臀部监控】到【电脑监控软件】,企业如何在隐私权与管理权博弈中找到平衡
【臀部监控】 依稀记得在2021年初某个高科技产品的爆火,惹得各大媒体网站争相报道。 起因是一位杭州网友在论坛上发帖,不久前公司给员工发放了一批高科技坐垫。 这个坐垫能自动感应心跳、呼吸在内的诸多人体数据,还能提醒人保持正确坐姿以及…...
数据库简介和sqlite3安装
数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作。 严格意义上来说,"数据库"不能被称之为"数据库",而…...
颈肩肌筋膜炎做什么检查
颈肩肌筋膜炎症状 颈肩背部广泛疼痛酸胀沉重感、麻木感,僵硬、活动受限,可向后头部及上臂放散。疼痛呈持续性,可因感染、疲劳、受凉、受潮等因素而加重。查体见颈部肌紧张,压痛点常在棘突及棘突旁斜方肌、菱形肌等,压…...
django建站过程(3)定义模型与管理页
定义模型与管理页 定义模型[models.py]迁移模型向管理注册模型[admin.py]注册模型使用Admin.site.register(模型名)修改Django后台管理的名称定义管理列表页面应用名称修改管理列表添加查询功能 django shell交互式shell会话 认证和授权 定义模型[models.py] 模仿博客形式&…...
node开发微信群聊机器人第⑤章
▍PART 序 看本文时,请确保前4章都已经看过,不然本章你看着看着思维容易跳脱!再一个机器人教程只在公众号:“程序员野区”首发。csdn会跟着发一份,未经博主同意,请勿转载!欢迎分享到自己的微信…...
如何助力企业出海?未来发展趋势是什么?尽在「云通信」Tech专场
2023杭州云栖大会 倒计时4天! 阿里云云通信 2大并行Session 6场话题演讲 今日「云通信」Tech 议程内容抢先知晓 01 「云通信」Tech • 国内企业出海,如何更高地提升市场营销的ROI,提升客户的转化率? • 面对海外存量客户&a…...
安装虚拟机(VMware)保姆级教程及配置虚拟网络编辑器和安装WindowsServer以及本地访问虚拟机和配置服务器环境
目录 一、操作系统 1.1.什么是操作系统 1.2.常见操作系统 1.3.个人版本和服务器版本的区别 1.4.Linux的各个版本 二、VMware Wworkstation Pro虚拟机的安装 1.下载与安装 注意:VMWare虚拟网卡 2.配置虚拟网络编辑器 三、安装配置 WindowsServer 1.创建虚拟…...
使用Typecho搭建个人博客网站,并内网穿透实现公网访问
使用Typecho搭建个人博客网站,并内网穿透实现公网访问 文章目录 使用Typecho搭建个人博客网站,并内网穿透实现公网访问前言1. 安装环境2. 下载Typecho3. 创建站点4. 访问Typecho5. 安装cpolar6. 远程访问Typecho7. 固定远程访问地址8. 配置typecho 前言 …...
RabbitMQ (4)
RabbitMQ (4) 文章目录 1. 死信的概念2. 死信的来源3. 死信代码案例3.1 TTL 过期时间3.2 超过队列最大长度3.3 拒绝消息 前言 上文我们已经学习完 交换机 ,知道了几个交换机的使用 ,下面我们来学习一下 死信队列 1. 死信的概念 先从概念解释上搞清楚这…...
马斯克多项目进展与诉讼案引关注
本月 1 号 SpaceX 提交 IPO 申请,预计最早 6 月 IPO。同时,特斯拉多项目遇阻,Cybercab 人员流失、自动驾驶事故多,还有马斯克诉阿尔特曼案即将开庭,情况复杂。SpaceX IPO 预测原以为马斯克会在 20 号秘密提交 SpaceX 的…...
Youtu-Parsing快速部署指南:一键启动Web服务,5分钟开始解析文档
Youtu-Parsing快速部署指南:一键启动Web服务,5分钟开始解析文档 1. 引言:为什么选择Youtu-Parsing 在日常工作中,我们经常需要处理各种文档——合同、报告、表格、发票等。传统的手动录入方式不仅效率低下,还容易出错…...
Chocolatey 安装 Python 3 时那些你可能不知道的隐藏依赖(附详细日志分析)
Chocolatey 安装 Python 3 时那些你可能不知道的隐藏依赖(附详细日志分析) 当你在 Windows 系统上使用 Chocolatey 安装 Python 3 时,表面上看只是一条简单的命令,但背后却隐藏着一系列复杂的依赖处理过程。这些自动安装的组件往往…...
如何解决Cats类型推导难题:SI-2712修复与部分统一完整指南
如何解决Cats类型推导难题:SI-2712修复与部分统一完整指南 【免费下载链接】cats Lightweight, modular, and extensible library for functional programming. 项目地址: https://gitcode.com/gh_mirrors/ca/cats Cats是一个轻量级、模块化且可扩展的函数式…...
linux sed/awk命令检索区间日志的问题
开发时如果需要检索一段时间内或者某个批量执行期间的所有日志,也就是区间日志时,手动检索会有一些问题:如要查询一段时间前的日志(比如归档日志),需要一页一页翻,费时且费眼睛使用grep筛选日志…...
Ostrakon-VL终端教程:终端日志记录与扫描任务审计追踪
Ostrakon-VL终端教程:终端日志记录与扫描任务审计追踪 1. 像素特工终端简介 Ostrakon-VL终端是一款专为零售与餐饮行业设计的智能扫描工具,它将复杂的图像识别任务转化为直观有趣的"数据扫描任务"。与传统工业级UI不同,这款终端采…...
MySQL 中 count(*)、count(1) 和 count(字段名) 有什么区别?
一、快速结论(先看结论再看分析)方式作用效率一句话总结count(*)统计所有行数⭐⭐⭐⭐ 最高我是专业的!我为统计而生count(1)统计所有行数⭐⭐⭐⭐ 同样高效我是 count(*) 的马甲兄弟count(列名)统计该列非 NULL 的行数⭐⭐⭐ 较慢我挑剔&…...
OpenClaw新手入门:千问3.5-9B镜像一键部署与初体验
OpenClaw新手入门:千问3.5-9B镜像一键部署与初体验 1. 为什么选择这个组合? 去年冬天,我第一次在本地尝试用OpenClaw自动整理电脑上的照片。当时对接的是GPT-3.5,每次识别图片内容都要消耗大量token,一个月下来账单让…...
在Linux中编写shell脚本监听指定端口的实现方式
在Linux中,你可以编写一个shell脚本来监听指定端口。以下是几种实现方式:方法1:使用nc(netcat)的简单监听脚本1234567891011121314151617181920212223#!/bin/bash# 文件名:port_listener.sh# 检查参数if [ …...
Arduino模拟输入校准库:软件定义ADC精度提升方案
1. AnalogInput 库概述AnalogInput 是一个专为 Arduino 平台设计的轻量级模拟输入信号处理库,其核心工程目标是在资源受限的微控制器上实现高鲁棒性的自动校准与稳定采样。不同于 Arduino 原生analogRead()的裸调用方式,该库通过软件层面的系统性补偿机制…...
