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. 死信的概念 先从概念解释上搞清楚这…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...
sshd代码修改banner
sshd服务连接之后会收到字符串: SSH-2.0-OpenSSH_9.5 容易被hacker识别此服务为sshd服务。 是否可以通过修改此banner达到让人无法识别此服务的目的呢? 不能。因为这是写的SSH的协议中的。 也就是协议规定了banner必须这么写。 SSH- 开头,…...
2025-05-08-deepseek本地化部署
title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek:小白也能轻松搞定! 如何给本地部署的 DeepSeek 投喂数据,让他更懂你 [实验目的]:理解系统架构与原…...
起重机起升机构的安全装置有哪些?
起重机起升机构的安全装置是保障吊装作业安全的关键部件,主要用于防止超载、失控、断绳等危险情况。以下是常见的安全装置及其功能和原理: 一、超载保护装置(核心安全装置) 1. 起重量限制器 功能:实时监测起升载荷&a…...
