lua和C++交互的lua栈操作——以LuaTinker为例
一、
-- C++类注册函数(LuaTinker) 的lua栈操作:
-- lua栈内容(执行到pop语句) 栈地址 <--执行语句
space_name[name] = t1 -- (2b8) -- lua_rawset(L, -4);
-- t1[__gc] = destroyer<T> -- (2d8) -- lua_rawset(L, -3);
-- destroyer<T> -- (2f8) -- lua_pushcclosure(L, destroyer<T>, 0);
-- __gc -- (2e8) -- lua_pushstring(L, "__gc");
-- t1[__newindex] = meta_set -- (2d8) -- lua_rawset(L, -3);
-- meta_set -- (2f8) -- lua_pushcclosure(L, meta_set, 0);
-- __newindex -- (2e8) -- lua_pushstring(L, "__newindex");
-- t1[__index] = meta_get -- (2d8) -- lua_rawset(L, -3);
-- meta_get -- (2f8) -- lua_pushcclosure(L, meta_get, 0);
-- __index -- (2e8) -- lua_pushstring(L, "__index");
-- t1[__name] = name -- (2d8) -- lua_rawset(L, -3);
-- name -- (2f8) -- lua_pushstring(L, name);
-- __name -- (2e8) -- lua_pushstring(L, "__name");
-- setmetatable(t1, t2) -- (2d8) -- lua_setmetatable(L, -2);
-- t2[__index] = static_meta_get -- (2e8) -- lua_rawset(L, -3);
-- static_meta_get -- (308) -- lua_pushcclosure(L, static_meta_get, 0);
-- __index -- (2f8) -- lua_pushstring(L, "__index");
-- t2 -- (2e8) -- lua_newtable(L);
-- t1 -- (2d8) -- lua_newtable(L);
-- name -- (2c8) -- lua_pushstring(L, name);
-- space_name[name] -- (2b8) -- lua_rawget(L, -2);
-- name -- (2b8) -- lua_pushstring(L, name);
space_name -- (2a8) -- push_meta(L, space_name::name);
L -- (298) -- 初始状态
-- C++类注册函数(LuaTinker),支持注册到命名空间namespace
template<typename T>
void class_addEx(lua_State* L, const char* name)
{
push_meta(L, space_name::name());
if(lua_istable(L, -))
{
class_name<T>::name(name); lua_pushstring(L, name);
lua_rawget(L, -);
if (!lua_istable(L, -))
{
lua_pushstring(L, name);
lua_newtable(L); lua_newtable(L);
lua_pushstring(L, "__index");
lua_pushcclosure(L, static_meta_get, );
lua_rawset(L, -);
lua_setmetatable(L, -); lua_pushstring(L, "__name");
lua_pushstring(L, name);
lua_rawset(L, -); lua_pushstring(L, "__index");
lua_pushcclosure(L, meta_get, );
lua_rawset(L, -); lua_pushstring(L, "__newindex");
lua_pushcclosure(L, meta_set, );
lua_rawset(L, -); lua_pushstring(L, "__gc");
lua_pushcclosure(L, destroyer<T>, );
lua_rawset(L, -); lua_rawset(L, -);
}
}
lua_pop(L, );
}
二、
-- meta_get栈操作如下:
-- lua栈内容 栈地址 <--执行语句
t_meta[__index] -- (ed8) -- lua_rawget(L,-2); <-- 执行到此语句
-- __index -- (ed8) -- lua_pushvalue(L,2);
t_meta -- (ec8) -- lua_getmetatable(L,1);
__index -- (eb8) -- 初始 lua_pushstring(L, "__index");
t -- (ea8) -- 初始
L -- (e98) -- 初始状态
--// int lua_tinker::meta_get(lua_State *L)
int lua_tinker::meta_get(lua_State *L)
{
lua_getmetatable(L,); lua_pushvalue(L,);
lua_rawget(L,-); bool is_dispatcher = false;
const char* func_name = lua_tostring(L, ); if(lua_isuserdata(L,-))
{
user2type<var_base*>::invoke(L,-)->get(L);
lua_remove(L, -);
}
else if (lua_istable(L, -))
{
lua_remove(L, -);
is_dispatcher = true;
}
else if (lua_isnil(L, -))
{
lua_remove(L, -);
invoke_parent(L, func_name);
if (lua_isnil(L, -))
{
lua_remove(L, -);
invoke_child(L, func_name);
}
if (lua_istable(L, -))
{
lua_remove(L, -);
is_dispatcher = true;
}
} //函数分发
if (is_dispatcher)
{
push_currfuncname(L, func_name); push_dispatcher(L);
} lua_remove(L,-); return ;
}
三、
--> 假设:meta_get函数执行到上面语句(栈内容如上) ——> t_meta[__index] == nil ——> 进入invoke_parent(L, func_name);
-- lua栈内容 栈地址 <--执行语句
tt[funcname] -- (e18) -- lua_remove(L, -2);
-- tt[funcname] -- (e28) -- lua_rawget(L, -2); -->lua_istable(L, -1) || lua_isfunction(L, -1)
-- funcname -- (e28) -- lua_pushstring(L, funcname);
-- t_meta[__parent] = tt -- (e18) -- lua_rawget(L, -2); --> lua_istable(L,-1),重命名为tt
-- __parent -- (e18) -- lua_pushstring(L, "__parent");
-- -- (e08) -- lua_remove(L, -1);
-- t_meta[__index] -- (e18) -- lua_rawget(L,-2);
t_meta -- (d08) -- lua_getmetatable(L,1);
__index -- (cf8) -- 初始 lua_pushstring(L, "__index");
t -- (ce8) -- 初始
L -- (cd8) -- 初始状态(和上面的栈内容不匹配,因为是另一个过程,其满足t_meta[__index] == nil)
// static void invoke_parent(lua_State *L, const char* funcname) static void invoke_parent(lua_State *L, const char* funcname)
{
lua_pushstring(L, "__parent");
lua_rawget(L, -);
if(lua_istable(L,-))
{
lua_pushstring(L, funcname);
lua_rawget(L, -); if (lua_istable(L, -) || lua_isfunction(L, -))
{
lua_remove(L, -);
}
else
{
lua_remove(L, -);
invoke_parent(L, funcname);
lua_remove(L, -);
}
}
}
lua和C++交互的lua栈操作——以LuaTinker为例的更多相关文章
- Lua 和 C 交互中虚拟栈的操作
Lua 和 C 交互中虚拟栈的操作 /* int lua_pcall(lua_State *L, int nargs, int nresults, int msgh) * 以保护模式调用具有" ...
- Lua和C++交互 学习记录之二:栈操作
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- Lua的栈及基本栈操作
Lua的栈及基本栈操作 https://blog.csdn.net/mydriverc2/article/details/51134737 https://blog.csdn.net/mydriver ...
- Lua和C++交互详细总结
转自:http://cn.cocos2d-x.org/tutorial/show?id=1474 一.Lua堆栈 要理解Lua和C++交互,首先要理解Lua堆栈. 简单来说,Lua和C/C++语言通信 ...
- Lua与C++交互初探之Lua调用C++
Lua与C++交互初探之Lua调用C++ 上一篇我们已经成功将Lua的运行环境搭建了起来,也成功在C++里调用了Lua函数.今天我来讲解一下如何在Lua里调用C++函数. Lua作为一个轻量级脚本语言 ...
- 用好lua+unity,让性能飞起来——lua与c#交互篇
前言 在看了uwa之前发布的<Unity项目常见Lua解决方案性能比较>,决定动手写一篇关于lua+unity方案的性能优化文. 整合lua是目前最强大的unity热更新方案,毕竟这是唯一 ...
- lua与C交互 具体
什么样类型的函数可以被Lua调用 typedef int (*lua_CFunction) (lua_State *L); 符合类型的函数怎样处理后才可以被Lua调用 使用lua_register或者 ...
- Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 在 ...
- Lua和C++交互 学习记录之八:C++类注册为Lua模块
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
随机推荐
- AMQP学习 & RabbitMQ 与 ActiveMQ、ZeroMQ以及Kafka的比较
之前写了一篇文章关于Active以及消息队列推拉模式的文章,可以参考:link 关于 Active 与 RabbitMQ以及其他的比较,有如下记录: 这篇文章 link 提到: 基本介绍RabbitM ...
- 【C#】Config配置文件的读写,及无法写入/保存配置文件的问题
目的: 一些数据为了在项目打包好后也能方便的修改和调用,通常会把这些数据放到配置文件中,避免硬编码,修改配置文件内容更方便,而不用修改源代码. 使用: 在解决方案资源管理器中找到App.config文 ...
- Maven学习:项目之间的关系
Maven不仅可以定义一个项目中各个模块之间的关系,还可以更延伸一步定义项目与项目之间的关系. 定义父子项目的好处还是挺多的.
- [MMC]Linux MMC/SD/SDIO驱动分析
转自:http://www.cnblogs.com/cslunatic/p/3678045.html 一.SD/MMC/SDIO概念区分 SD(SecureDigital)与 MMC(Multimed ...
- 配置Apache与PHP的环境
http://www.cnblogs.com/zhcncn/archive/2013/05/09/3068318.html 1. 下载 Apache版本号为2.2.22. 最好下载msi安装文件.下载 ...
- parted创建LVM
parted创建LVM 把一块1T硬盘全部设为LVM #parted /dev/sdb >mklabel gpt 由于MBR分区表只支持2T硬盘,所以如果大于2T必须用GPT分区表 >pr ...
- Entity Framework实体拆分
一.概念 实体拆分:一个实体拆分成多个表,如Product实体,可以拆分成Product和ProductWebInfo两个表,Product表用于存储商品的字符类信息,ProductWebInfo用于 ...
- Oracle的sql语句中关键字冲突用双引号
select distinc user from instrument where created>"TO_DATE"('2015-02-05 12:00:00', 'yyy ...
- 对于表达式比较长的 for 语句和 if 语句
对于表达式比较长的 for 语句和 if 语句,为了紧凑起见可以适当地去 掉一些空格,如 for (i=0; i<10; i++)和 if ((a<=b) && (c< ...
- css -- 通俗理解inline、block、inline-block
display:inline; 内联元素,简单来说就是在同一行显示. display:block; 块级元素,简单来说就是就是有换行,会换到第二行. display:inline-block; 就是在 ...