Lua与C++交互(一)————堆栈

news2024/12/29 0:52:30

Lua与C++交互(一)————堆栈

Lua虚拟机

什么是Lua虚拟机

Lua本身是用C语言实现的,它是跨平台语言,得益于它本身的Lua虚拟机。

虚拟机相对于物理机,借助于操作系统对物理机器(CPU等硬件)的一种模拟、抽象,主要扮演CPU和内存的作用。

虚拟机的主要职责就是:执行字节码中的指令,管理全局状态(global_state)、数据栈(StackValue)和函数调用链状态(CallInfo)

可以理解成,lua虚拟机就是一个独立的空间,它会维护Lua的所有运行。

创建Lua虚拟机

使用C函数,luaL_newstate 来创建。

会创建一个lua_State的结构体,该结构体就代表了一个Lua虚拟机。

一个进程中可以创建多个Lua虚拟机,即多个lua_State结构。

Lua虚拟机中是单线程实现,所以,多个创建的Lua虚拟机之间是相互独立的。

cocos2dx中的创建Lua虚拟机的地方

AppDelegate中

bool AppDelegate::applicationDidFinishLaunching()
{
    ;;....
    // register lua module
    auto engine = LuaEngine::getInstance();
    ;;...
}

这里在调用单例LuaEngine的时候,会创建LuaStack

LuaEngine中

bool LuaEngine::init(void)
{
    _stack = LuaStack::create();
    _stack->retain();
    return true;
}

LuaStack中

bool LuaStack::init(void)
{
    _state = lua_open();
    luaL_openlibs(_state);
    toluafix_open(_state);

    // Register our version of the global "print" function
    const luaL_Reg global_functions [] = {
        {"print", lua_print},
        {"release_print",lua_release_print},
        {nullptr, nullptr}
    };
    ;;....
}

其中成员变量_state的类型就是lua_State结构体,也就是Lua虚拟机。lua_open是函数luaL_newstate的宏定义。

同时可以得知,这里Lua虚拟机只有一个,这也是为什么在cocos2dx中需要严格按照规则来进行C++和Lua调用的原因。

lua_State

lua虚拟机对象,本身是一个结构体。

它是一个lua线程的执行状态,所有的C api都是基于这个结构体的。

struct lua_State
{
	CommonHeader;//#define CommonHeader
	GCObject *next; 
	lu_byte tt; 
	lu_byte marked
	lu_byte status;//虚拟机的错误状态码
	StkId top;//栈顶元素所在位置的下一个位置,也就是栈上第一个空闲的位置
	StkId base;//栈上,当前函数的基址(注意不是函数所在位置)
	global_State* l_G;//全局表,环境章节再说
	CallInfo* ci;//当前函数调用信息
	const Instruction* savedpc;//当前函数的指令位置,指向待取指指令的地址
	StkId stack_last;//栈最后一个位置的下一个位置
	StkId stack;//寄存器数组的起始位置
	CallInfo* end_ci;//函数调用信息数组的最后一个位置的下一个位置
	CallInfo* base_ci;//函数调用信息数组首地址
	int stacksize;//栈的大小
	int size_ci;//函数调用信息数组大小
	unsigned short nCcalls;//内嵌C调用层数
	unsigned short baseCcalls;//唤醒协程时的内嵌C调用层数
	lu_byte hookmask;
	lu_byte allowhook;
	int basehookcount;
	int hookcount;
	lua_Hook hook;
	TValue l_gt;//Global表
	TValue env;//环境表的临时位置
	GCObject* openupval;//open状态的upvalues
	GCObject* gclist;
	struct lua_longjmp* errorJmp;//跳转信息单链表,实现try catch的功能,见函数章节
	ptrdiff_t errfunc;//当前错误处理函数在栈上的索引
};

关于lua_State这里不过多阐述,感兴趣的可以看《lua设计与实现》这本书。

或者看看云风的《lua源码赏析》

或者看看这个博客
https://blog.csdn.net/yuanlin2008/category_1307277.html

Lua全局表

global_State 全局状态机

如果说lua_State是面对外面表现的虚拟机对象,那么global_State才是背后真正的大佬,该结构体不对外开放,即无法用Lua公开的API获取到它的指针、句柄或引用。

它里面有对主线程(lua_State实例)的引用、有全局字符串表、有内存管理函数、有GC需要的相关信息以及一切Lua在工作时需要的工作内存等等

想要深入了解,同样可以查看《lua设计与实现》这本书。

Lua堆栈

Lua的堆栈是Lua和C++交互的基础,也就是说C++和Lua之间的数据类型交互都是通过这个虚拟栈进行完成的。

不管是C++需要获取Lua的数据还是需要传递数据给Lua,都需要先将这个数据压入栈中。

在这里插入图片描述

从索引来说,分为正向和逆向索引。其中-1永远表示栈顶,1永远表示栈底。

入栈操作

涉及到一些Lua入栈的函数(常用)。

函数原型说明
lua_pushnumbervoid lua_pushnumber (lua_State *L, lua_Number n)将数值类型n 压入栈中
lua_pushnilvoid lua_pushnil (lua_State *L)将nil压入栈中
lua_pushbooleanvoid lua_pushboolean (lua_State *L, int b);将布尔类型压入栈中
lua_pushfstringconst char *lua_pushfstring (lua_State *L, const char *fmt, …)把一个格式化过的字符串压入堆栈,然后返回这个字符串的指针
lua_pushintegervoid lua_pushinteger (lua_State *L, lua_Integer n)将一个整型数字n压入栈中
lua_pushlstringvoid lua_pushlstring (lua_State *L, const char *s, size_t len)把指针 s 指向的长度为 len 的字符串压栈
lua_pushstringvoid lua_pushstring (lua_State *L, const char *s)把指针 s 指向的以零结尾的字符串压栈
lua_pushthreadint lua_pushthread (lua_State *L)把 L 中提供的线程压栈。 如果这个线程是当前状态机的主线程的话返回 1
lua_pushvaluevoid lua_pushvalue (lua_State *L, int index)把堆栈上给定有效处索引处的元素作一个拷贝压栈
lua_pushlightuserdatavoid lua_pushlightuserdata (lua_State *L, void *p)把一个 light userdata 压栈。 userdata 在 Lua 中表示一个 C 值。light userdata 表示一个指针。它是一个像数字一样的值:你不需要专门创建它,它也没有独立的 metatable ,而且也不会被收集(因为从来不需要创建)。只要表示的 C 地址相同,两个 light userdata 就相等
lua_pushcfunctionvoid lua_pushcfunction (lua_State *L, lua_CFunction f)将一个 C 函数压入堆栈。 这个函数接收一个 C 函数指针,并将一个类型为 function 的 Lua 值 压入堆栈。当这个栈顶的值被调用时,将触发对应的 C 函数

具体可以查看

https://www.w3cschool.cn/doc_lua_5_1/lua_5_1-index.html#lua_pushnumber

取值和出栈

与之对应的取值为:

lua_to*(lua_State * L,栈中位置)取值

对应的出栈为:

lua_pop(lua_State * L,出栈个数)出栈

举例

myName = “beauty girl”

在这里插入图片描述

  1. C++想要获取myName的值,根据规则,它需要把myName压入栈中,这样lua就能看到;
  2. lua从堆栈中获取myName的值,此时栈顶为空;
  3. lua拿着myName去全局表中查找与之对应的字符串;
  4. 全局表找到,并返回"beauty girl";
  5. lua把"beauty girl"压入栈中;
  6. C++从栈中获取"beauty girl"

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java【手撕双指针】LeetCode 1089. “复写零“, 图文详解思路分析 + 代码

文章目录 前言一、复写零1, 题目2, 思路分析2.1, 从左往右 or 从右往左2.2, 找到最后一个保留的数 3, 代码展示 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: 📕 JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管…

SpringCloud Gateway服务网关的介绍与使用

目录 1、网关介绍2、SpringCloudGateway工作原理3、三大组件3.1 、Route(路由)3.2、断言 Predicate3.3、过滤器 filter 4、Gateway整合nacos的使用4.1 、引入依赖4.2、 编写基础类和启动类4.3、 编写基础配置和路由规则4.4 、测试结果 1、网关介绍 客户…

营销数字化|企业级 AIGC 工具的「iPhone 时刻」

2007 年,乔布斯发布了第一款 iPhone,从此彻底改变了手机行业的市场走向。iPhone 成功的背后,一个很重要的原因是:它让用户以更简单、更符合直觉的方式来使用手机。 如今,AIGC 工具也在等待它的「iPhone 时刻」&#xf…

C++信息学奥赛1119:矩阵交换行

解题思路&#xff1a;当输出时换行 解题程序&#xff1a; #include<iostream> using namespace std; int main() {int arr[5][5];// 输入矩阵元素for(int i0;i<5;i){for(int j0;j<5;j){cin>>arr[i][j];}} int n,m;cin>>n>>m;// 根据条件进行矩…

RT-Thread学习日记——点亮LED

最近开始接触RT-Thread&#xff0c;后面会单独建立专栏以此记录我的学习过程&#xff0c;如果能给你的学习提供参考&#xff0c;本人倍感荣幸。 学习工具&#xff1a;正点原子战舰开发板 一、、点亮LED 在RT-Thread的配置项里搜索LED可以看到和LED相关的很多内容&#xff0c…

AutoDev 1.1.3 登场,个性化 AI 辅助:私有化大模型、自主设计 prompt、定义独特规则...

在过去的半个月里&#xff0c;我们为开源辅助编程工具 AutoDev 添加了更强大的自定义能力&#xff0c;现在你可以&#xff1a; 使用自己部署的开源大模型自己配置 Intellij IDEA 中的行为自定义开发过程中的规范 当然了&#xff0c;如果您自身拥有开发能力的话&#xff0c;建议…

无涯教程-PHP - XML

简单的XML解析器解析 Name&#xff0c; attributes 和 textual content&#xff0c;简单的XML函数如下所示- simplexml_load_file() 此函数接受文件路径作为第一个参数&#xff0c;这是必需的。 simplexml_load_file(($fileName,$class,$options,$ns,$is_prefix) simplexml…

springMVC Unix 文件参数变更漏洞修复

错误信息如下&#xff1a; 解决方案&#xff1a; 原因&#xff1a;未对用户输入正确执行危险字符清理 未检查用户输入中是否包含“…”&#xff08;两个点&#xff09;字符串&#xff0c;比如 url 为 /login?action…/webapps/RTJEKSWTN26635&typerandomCode cookie为Coo…

飞天使-kubeadm安装一主一从集群

文章目录 安装前准备安装前准备配置yum源等安装前准备docker安装 安装kubeadm配置kubeadm验证集群 参考链接 安装前准备 cat >> /etc/hosts <<EOF 192.168.100.30 k8s-01 192.168.100.31 k8s-02 EOF hostnamectl set-hostname k8s-01 #所有机器按照要求修改 ho…

React笔记[tsx]-解决Property ‘frames‘ does not exist on type ‘Readonly<{}>‘

浏览器报错如下&#xff1a; 编辑器是这样的&#xff1a; 原因是React.Component<any>少了后面的any&#xff0c;改成这样即可&#xff1a; export class CustomFrame extends React.Component<any, any>{............ }

CH02_重构的原则(什么是重构、为什么重构、何时重构)

什么是重构 重构&#xff08;名词&#xff09;&#xff1a;对软件内部结构的一种调整&#xff0c;目的是在不改变软件可观察行为的前提下&#xff0c;提高其可理解性&#xff0c;降低其修改成本。 重构&#xff08;动词&#xff09;&#xff1a;使用一系列重构手法&#xff0…

Lnton羚通算法算力云平台在环境配置中当使用conda创建新的虚拟环境时为什么会遇到错误

当使用conda创建新的虚拟环境时遇到错误&#xff0c;可能是由于以下一些常见原因导致的&#xff1a; Conda环境未正确安装&#xff1a;请确保你已经正确安装了Conda&#xff0c;并且设置了正确的环境变量。你可以尝试在终端中运行conda --version来验证Conda是否已经成功安装并…

STM32设置为I2C从机模式(HAL库版本)

STM32设置为I2C从机模式&#xff08;HAL库版本&#xff09; 目录 STM32设置为I2C从机模式&#xff08;HAL库版本&#xff09;前言1 硬件连接2 软件编程2.1 步骤分解2.2 测试用例 3 运行测试3.1 I2C连续写入3.2 I2C连续读取3.3 I2C单次读写测试 4 总结 前言 我之前出过一篇关于…

ios小组件报错:Please adopt containerBackground API

iOS 17 小组件报错:Please adopt containerBackground API 使用下面的方法解决了: 代码: extension View {func widgetBackground(_ backgroundView: some View) -> some View {if #available(iOSApplicationExtension 17.0, *) {return containerBackground(for: .wi…

恒运资本:信创概念再度活跃,华是科技再创新高,南天信息等涨停

信创概念21日盘中再度活跃&#xff0c;截至发稿&#xff0c;华是科技涨超17%&#xff0c;盘中一度触及涨停再创新高&#xff0c;中亦科技涨超13%亦创出新高&#xff0c;久其软件、南天信息、新炬网络、英飞拓均涨停。 音讯面上&#xff0c;自8月3日以来&#xff0c;财政部官网连…

YOLOX在启智AI GPU/CPU平台部署笔记

文章目录 1. 概述2. 部署2.1 拉取YOLOX源码2.2 拉取模型文件yolox_s.pth2.3 安装依赖包2.4 安装yolox2.5 测试运行2.6 运行报错处理2.6.1 ImportError: libGL.so.1: cannot open shared object file: No such file or directory2.6.2 ImportError: libgthread-2.0.so.0: cannot…

推荐一款好用的开源视频播放器(免费无广告)

mpv是一个自由开源的媒体播放器&#xff0c;它支持多种音频和视频格式&#xff0c;并且具有高度可定制性。mpv的设计理念是简洁、高效和功能强大。 软件特点&#xff1a; 1. 开源、跨平台。可以在Windows\Linux\MacOS\BSD等系统上使用&#xff0c;完全免费无广告。Windows版解压…

Selenium环境+元素定位大法

selenium 与 webdriver Selenium 是一个用于 Web 测试的工具&#xff0c;测试运行在浏览器中&#xff0c;就像真正的用户在手工操作一样。支持所有主流浏览器 WebDriver 就是对浏览器提供的原生API进行封装&#xff0c;使其成为一套更加面向对象的Selenium WebDriver API。 使…

JSON简介及前端简单解析(一)

JSON现在常用来做前后端数据交互&#xff0c;两个蝴蝶飞只是简单的对JSON做一下讲解和简单使用。关于JSON,我还了解的远远不够。由于本人经验有限&#xff0c;嘴皮子不溜&#xff0c;所以学术性&#xff0c;概念性&#xff0c;底层性的知识点暂时不做介绍。文章中有错误之处&am…

QT中资源文件resourcefile的使用,使用API完成页面布局

QT中资源文件resourcefile的使用 之前添加图标的方法使用资源文件的方法创建资源文件资源文件添加前缀资源文件添加资源使用资源文件中的资源 使用API完成布局使用QHBoxLayout完成水平布局使用QVBoxLayout完成垂直布局使用QGridLayout完成网格布局 在Qt中引入资源文件好处在于他…