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 ...
随机推荐
- pdo_mysql安装
如果编译时没有编译pdo模块,可以cd 到php编译时的目录,重新编译 1.切换到pdo_mysql目录,如php-5.5.10/ext/pdo_mysql/ 2.生成configure文件,在pdo ...
- Java并发编程()阻塞队列和生产者-消费者模式
阻塞队列提供了可阻塞的put和take方法,以及支持定时的offer和poll方法.如果队列已经满了,那么put方法将阻塞直到有空间可用:如果队列为空,那么take方法将会阻塞直到有元素可用.队列可以 ...
- C语言 · 淘淘的名单
算法提高 淘淘的名单 时间限制:100ms 内存限制:8.0MB 问题描述 by ZBY... :) 淘淘拿到了一份名单,他想对上面的名字进行处理,挑出一些特殊的名字,他请你来帮忙. ...
- MyBatis批量操作报错:Parameter 'xxxList' not found. Available parameters are [list]
问题背景: 在Dao中使用MyBatis进行查询操作,参数是传的一个List:studentNameList,但是在执行查询的时候报错,具体日志如下: com.chenzhou.base.mybati ...
- contiki rpl
Linking target: udp-client-temperature.stk3700arm-none-eabi-gcc -Xlinker -Map=udp-client-temperature ...
- ad9 的快捷方式
TAB:选中元件后,可以显示该元件的属性: PAGEUP:以鼠标所在点为中心,放大视图: PAGEDOWN:以鼠标所在点为中心,缩小视图: HOME:居中,可以从原来光标下的图纸位置,移位到工作区中心 ...
- 六步破解win2008R2登录密码
防火墙没有开启,win2008R被当成矿机,只好重新破解密码进去解决问题,试了好多方法,下列方法绝对实用简单. 破解2008登录密码的方法: 1.进入PE2.找到文件:windows\system32 ...
- redis调优
1.先把持久化数据备份一份,然后使用rdb分析工具分析一下大的键值2.然后DBA删除一部分不用的3.然后再配置最大内存 千万不要没清理数据就直接把内存限制较小 那样会触发redis对内存达到限制的处理 ...
- WCF客户端获取服务器返回数据报错
错误信息:An error occurred while receiving the HTTP response to http://127.0.0.1/SIHIS/Infection/PubExec ...
- JavaScript 关键字快速匹配
来源: http://www.cnblogs.com/index-html/archive/2013/04/17/js_keyword_match.html http://www.etherdream ...