lua中的table、stack和registery
ok,前面准备给一个dll写wrapper,写了篇日志,看似写的比较明白了,但是其实有很多米有弄明白的。比如PIL中使用的element,key,tname,field这些,还是比较容易混淆的。今天正好搞搞清楚。
1、stack
这个应该不用多讲了,C和lua中的交互就是基于一个stack的,而且每次lua调用一个c函数,都是给分配一个新的stack。它的原型:
typedef int (*lua_CFunction) (lua_State *L);
stack中的基本单元在PIL中多成为element。
2、table
我们可以在C中定义一个struct如下:
struct ColorTable {
char *name;
unsigned char red, green, blue;
} colortable[] = {
{"WHITE", MAX_COLOR, MAX_COLOR, MAX_COLOR},
{"RED", MAX_COLOR, , },
{"GREEN", , MAX_COLOR, },
{"BLUE", , , MAX_COLOR},
{"BLACK", , , },
...
{NULL, , , } /* sentinel */
};
在C中,我们事实上可以把如上的struct当做类似下面lua代码来用:
WHITE = {r=, g=, b=}
RED = {r=, g=, b=}
...
How?我们先定义一个自己的setfield,用来往在堆顶的table中添加member“name=value”:
#define MAX_COLOR 255 /* assume that table is at the top */
void setfield (const char *name, int value) {
lua_pushstring(L, name);
lua_pushnumber(L, (double)value/MAX_COLOR);
lua_settable(L, -);
}
然后,我们创建某个颜色的table:
void setcolor (struct ColorTable *ct) {
lua_newtable(L); /* creates a table */
setfield("r", ct->red); /* table.r = ct->r */
setfield("g", ct->green); /* table.g = ct->g */
setfield("b", ct->blue); /* table.b = ct->b */
lua_setglobal(L, ct->name); /* `name' = table */
}
利用上面的两段代码,我们在L中创建了一个某个颜色的table,比如setcolor(colortable[1]),事实上是往L中放了一个表格,WHITE = {r = 1, g = 1, b = 1}。把整个struct都放入,只需使用下面这个循环:
int i = ;
while (colortable[i].name != NULL)
setcolor(&colortable[i++]);
自此,我们上面struct中所有的颜色都有了一张自己的table。
所以,field只是某个table中的,一个“name=value”对,name通常是一个字符串。这里的name也就是通常说的index,使用任意的lua认可的值都可以用来做它的name。这样一个“name=value”对被称为一个field。
3、registery
registery和其它的lua的表没什么却别。我们可以通过一个伪index(pesudo-index)在L中找到它;这个伪index是由宏LUA_REGISTRYINDEX定义的。我们也可以把这个伪index当做是普通的index来使用,但是不同的是,需要知道,它的value也不是在L里面。它的value不在stack中这一点非常重要,它决定了那些对stack本身做操作的函数是不适用的,比如lua_remove和lua_insert。
我们可以用下面的语句取到在registery中的,关键词为“key”的注册项:
lua_pushstring(L, "Key");
lua_gettable(L, LUA_REGISTRYINDEX);
因为他和其它的表没有区别,那么,和操作其它表一样操作它就好了。不过,因为所有的C库使用同一张registery,所以,命名上面我们要下些功夫,以免发生命名冲突。PIL里面推荐了一种保险的做法,我们可以选择一个我们代码里的静态变量的地址作为key:链接器不会给不同的静态变量分配相同地址,所以就不用担心重复问题了。如果要这么做,你需要调用函数lua_pushlightuserdata。在lua中,userdata就是一个普通的C value,而lightuserdata则是指C指针。我们在这里调用它把某个指针放到堆顶。具体可以看下面代码:
/* 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, -); /* convert to number */
当然,你也可以使用字符串作为registery的key,去多长都可以,你认为达到目的了就行。后面的懒得翻译了囧RZ
For such keys, there is no bulletproof method of choosing names, but there are some good practices, such as avoiding common names and prefixing your names with the library name or something like it. Prefixes like lua or lualib are not good choices. Another option is to use a universal unique identifier (uuid), as most systems now have programs to generate such identifiers (e.g., uuidgen in Linux). An uuid is a -bit number (written in hexadecimal to form a string) that is generated by a combination of the host IP address, a time stamp, and a random component, so that it is assuredly different from any other uuid.
lua中的table、stack和registery的更多相关文章
- Lua中使用table实现的其它5种数据结构
Lua中使用table实现的其它5种数据结构 lua中的table不是一种简单的数据结构,它可以作为其他数据结构的基础,如:数组,记录,链表,队列等都可以用它来表示. 1.数组 在lua中,table ...
- 递归打印lua中的table
在lua中,table是比较常用的数据形式,有时候为了打印出里面的内容,需要做一些特殊处理. 废话不多讲,直接粘代码: print = release_print -- 递归打印table local ...
- lua中遍历table的几种方式比较
当我在工作中使用lua进行开发时,发现在lua中有4种方式遍历一个table,当然,从本质上来说其实都一样,只是形式不同,这四种方式分别是: for key, value in pairs(tbtes ...
- Lua中的table函数库
table.concat(table, sep, start, end) concat是concatenate(连锁, 连接)的缩写. table.concat()函数列出参数中指定table的数组 ...
- lua中求table长度
关于lua table介绍,看以前的文章http://www.cnblogs.com/youxin/p/3672467.html. 官方文档是这么描述#的: 取长度操作符写作一元操作 #. 字符串的长 ...
- Lua中的table构造式(table constructor)
最简单的构造式就是一个空构造式{},用于创建一个空table. 构造式还可以用于初始化数组.例如,以下语句:days = {"Sunday", "Monday" ...
- lua中求table长度--(转自有心故我在)
关于lua table介绍,看以前的文章http://www.cnblogs.com/youxin/p/3672467.html. 官方文档是这么描述#的: 取长度操作符写作一元操作 #. 字符串的长 ...
- Lua中获取table长度
-- table.getn(tableName) 得到一个table的大小,等同于操作符# -- 要注意的是:该table的key必须是有序的,索引是从1开始的. --例如有序的 local xian ...
- lua中使用table实现类和继承
--因为只有当读写不存在的域时,才会触发__index和__newindex classA = {className = "classA",name="classAIns ...
随机推荐
- C10K 问题引发的技术变革
C10K 问题引发的技术变革 http://rango.swoole.com/archives/381
- 永远不要修改arguments对象
案例复现 var obj = { plus: function(arg0, arg1) { return arg0 + arg1; } }; function callMethod(context, ...
- 丰富Easyui 的插件 - lookup
插件用途: 主要用于表单中,某字段的内容是用其他表里的记录ID.当然你可以使用combobox.combotree.combogrid等,但有时这些表现方式并不是很好,希望弹出个层,然后在去做一些查询 ...
- React Native开发技术周报1
(一).资讯 1.React Native 0.21版本发布,最新版本功能特点,修复的Bug可以看一下已翻译 重要:如果升级 Android 项目到这个版本一定要读! 我们简化了 Android 应用 ...
- 如何在batch脚本中嵌入python代码
老板叫我帮他测一个命令在windows下消耗的时间,因为没有装windows那个啥工具包,没有timeit那个命令,于是想自己写一个,原理很简单: REM timeit.bat echo %TIME% ...
- mongodb .net core 调用
MongoClient _client; IMongoDatabase _db; MongoCredential credential = MongoCredential.CreateMongoCRC ...
- Tyk API网关介绍及安装说明
Tyk API网关介绍及安装说明 Tyk是一个开源的轻量级API网关程序. 什么是API网关 API网关是一个各类不同API的前置服务器.API网关封装了系统内部架构,对外提供统一服务.此外还可以实现 ...
- SQL复杂查询和视图(2)
分组查询 SQL可以将检索到的元组按某一条件进行分组,分组是属性值相同的为一组 求每个学生的平均成绩 SELECT sn,AVG(score)FROM scGROUP BY sn 先按sn进行分组,即 ...
- alarm
AlarmManager的使用机制有的称呼为全局定时器,有的称呼为闹钟.通过对它的使用,它的作用和Timer有点相似.都有两种相似的用法:(1)在指定时长后执行某项操作 (2)周期性的执行某项操作 在 ...
- android 调用电话功能
今天用到了打电话的功能,这要如何实现呢? 很简单 1.创建对应对的xml展示页面喝java文件 2.在manifest中添加权限 下面上代码吧: 这是布局的一部分 <LinearLayout a ...