Lua 与C 交互之LUA_REGISTRYINDEX(3)
通常来说,C函数需要保留一些非局部的数据,也就是指那些超过他们作用范围的数据。C语言中我们使用全局变量或者static变量来满足这种需要。然而当你为Lua设计一个程序库的时候,全局变量和static变量不是一个好的方法。首先,不能将所有的Lua值保存到一个C变量中。第二,使用这种变量的库不能在多个Lua状态的情况下使用。
一个替代的解决方案是将这些值保存到一个Lua全局变两种,这种方法解决了前面的两个问题。Lua全局变量可以存放任何类型的Lua值,并且每一个独立的状态都有他自己独立的全局变量集。然而,并不是在所有情况下,这种方法都是令人满意地解决方案,因为Lua代码可能会修改这些全局变量,危及C数据的完整性。为了避免这个问题,Lua提供了一个独立的被称为registry的表,C代码可以自由使用,但Lua代码不能访问他。
假索引
LUA_REGISTRYINDEX、LUA_ENVIRONINDEX、 LUA_GLOBALSINDEX是一个假索引(pseudo-indices),一个假索引除了他对应的值不在栈中之外,其他都类似于栈中的索引。 Lua API 中大部分接受索引作为参数的函数,其实可以理解为一张普通表格,你可以使用任何非nil的Lua值来访问她的元素。
The Registry
Lua 提供一个独立的被称为 registry 的表, C 可以自由使用,但 Lua 代码不能访问他。索引:LUA_REGISTRYINDEX,官方解释:
Lua provides a registry, a pre-defined table that can be used by any C code to store whatever Lua value it needs to store. This table is always located at pseudo-index LUA_REGISTRYINDEX. Any C library can store data into this table, but it should take care to choose keys different from those used by other libraries, to avoid collisions. Typically, you should use as key a string containing your library name or a light userdata with the address of a C object in your code
注意的地方:Key值,你可以使用字符串或者C函数的指针以light userdata作为键值。
/* variable with an unique address */
static const char Key = 'k';
/* store a number */
lua_pushlightuserdata(L, (void *)&Key); /* push address */
lua_pushnumber(L, myNumber); /* push value */
/* registry[&Key] = myNumber */
lua_settable(L, LUA_REGISTRYINDEX);
/* retrieve a number */
lua_pushlightuserdata(L, (void *)&Key); /* push address */
lua_gettable(L, LUA_REGISTRYINDEX); /* retrieve value */
myNumber = lua_tonumber(L, -1); /* convert to number */
References
为了解决Key唯一的问题,引入 References:Reference 系统是由辅助库中的一对函数组成,这对函数用来不需要担心名称冲突的将值保存到 registry 中去。
int luaL_ref (lua_State *L, int t);
lua_rawgeti(L, LUA_REGISTRYINDEX, r);
void luaL_unref (lua_State *L, int t, int ref);
luaL_ref Creates and returns a reference, in the table at index t, for the object at the top of the stack (and pops the object). A reference is a unique integer key. As long as you do not manually add integer keys into table t, luaL_ref ensures the uniqueness of the key it returns. You can retrieve an object referred by reference r by calling lua_rawgeti(L, t, r).
If the object at the top of the stack is nil, luaL_ref returns the constant LUA_REFNIL. The constant LUA_NOREF is guaranteed to be different from any reference returned by luaL_ref.
luaL_unref frees a reference and its associated object.
一些相关的优化技巧:
http://blog.codingnow.com/2006/11/lua_c.html “Lua 中写 C 扩展库时用到的一些技巧”
http://blog.codingnow.com/2006/01/_lua.html “Lua中字符串使用优化”
一些问题(待补充)
为什么lua要提供这个区间?有这些变量保存在C或者宿主语言中不是也挺好的吗?
可以理解的是:
- 分散在宿主语言不同部分的Lua交互代码可以很方面的获取全局信息
- 上面提到的,ref速度问题。
但是看了几个实现交互库,都是这样来处理的,其根本的原因是什么呢?
Lua 与C 交互之LUA_REGISTRYINDEX(3)的更多相关文章
- Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 在 ...
- Lua和C++交互 学习记录之二:栈操作
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- 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 和 C 交互中虚拟栈的操作
Lua 和 C 交互中虚拟栈的操作 /* int lua_pcall(lua_State *L, int nargs, int nresults, int msgh) * 以保护模式调用具有" ...
- 用好lua+unity,让性能飞起来——lua与c#交互篇
前言 在看了uwa之前发布的<Unity项目常见Lua解决方案性能比较>,决定动手写一篇关于lua+unity方案的性能优化文. 整合lua是目前最强大的unity热更新方案,毕竟这是唯一 ...
- Lua和C++交互 学习记录之八:C++类注册为Lua模块
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- Lua和C++交互 学习记录之七:C++全局函数注册为Lua模块
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- Lua和C++交互 学习记录之六:全局函数交互
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
随机推荐
- docker 安全
由于容器运行在主机上,且与主机共用一套内核,因此在容器的安全使用上会涉及到容器本身以及主机的安全加固,如针对系统调用,系统资源,远程访问等都需要进行安全方面的考量. docker官网给出了简单的一些建 ...
- 解决Response.AddHeader("Content-Disposition", "attachment; filename=" + file.Name) 中文显示乱码
如果file.Name为中文则乱码.解决办法是方法1:response.setHeader("Content-Disposition", "attachment; fil ...
- nginx介绍 - 部署到linux中
前言: tomcat理论并发处理能力, 大概500左右吧, 即使通过一些优化, 能提升一点, 但是, 并不能达到质变, 最多涨几百. 对于非互联网项目, 确实够用了. 在企业中, 如果要达到500并发 ...
- MYSQL中的COLLATE是什么?
本文由horstxu发表 在mysql中执行show create table <tablename>指令,可以看到一张表的建表语句,example如下: CREATE TABLE `ta ...
- 【PyTorch深度学习60分钟快速入门 】Part5:数据并行化
在本节中,我们将学习如何利用DataParallel使用多个GPU. 在PyTorch中使用多个GPU非常容易,你可以使用下面代码将模型放在GPU上: model.gpu() 然后,你可以将所有张 ...
- U3D GameObject 解读
GameObject本身没有功能,是Unity场景里所有组件的基类,但很多时候我们需要在脚本中操作GameObject.先讲一下GameObject类包含哪些内容,其中常用的用红色标出了 Variab ...
- FFmpeg封装格式处理4-转封装例程
本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10506662.html FFmpeg封装格式处理相关内容分为如下几篇文章: [1]. F ...
- 手撕coreML之yolov2 object detection物体检测(含源代码)
一些闲话: 前面我有篇博客 https://www.cnblogs.com/riddick/p/10434339.html ,大致说了下如何将pytorch训练的.pth模型转换为mlmodel,部署 ...
- USB 驱动(监测鼠标左键的动作)
(基于 Linux 3.4.2 内核) 可分为以下几个步骤来完成这个驱动: 1. 分配设置一个 usb_driver 结构体 2. 注册这个 usb_driver (如果设备的 id_table 与驱 ...
- python的类变量与实例变量以及__dict__属性
关于Python的实例变量与类变量,先来看一段可能颠覆世界观的例子 #!/usr/bin/env python # -*- coding: utf_8 -*- # Date: 2016年10月10日 ...