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 ...
随机推荐
- hadoop1.2.1伪分布模式配置
1.修改core-site.xml,配置hdfs <configuration> <property> <name>fs.default.name</name ...
- Putty颜色设置
默认的Putty颜色和字体太不好看了,得自己设置: 字体:毫无疑问Consolas, 10-point:看起来非常清新自然 颜色: * Default Foreground: 255/255/255 ...
- express:webpack dev-server中如何将对后端的http请求转到https的后端服务器中?
在上一篇文章(Webpack系列:在Webpack+Vue开发中如何调用tomcat的后端服务器的接口?)我们介绍了如何将对于webpack-dev-server的数据请求转发到后端服务器上,这在大部 ...
- 基于.NET Socket API 通信的综合应用
闲谈一下,最近和客户进行对接Scoket 本地的程序作为请求方以及接受方,对接Scoket 的难度实在比较大,因为涉及到响应方返回的报文的不一致性,对于返回的报文的格式我需要做反序列化的难度增大了不少 ...
- ASP.NET 系列:单元测试之StructureMap
ASP.NET使用StructureMap等依赖注入组件时最重要就是EntityFramework的DbContext对象要保证在每次HttpRequest只有一个DbContext实例,这里将使用第 ...
- 微软分布式云计算框架Orleans(1):Hello World
自从写了RabbitHub框架系列后的一段时间内一直在思索更加轻量简便,分布式高并发的框架(RabbitHub学习成本较高),无意间在网上级联看到了很多新框架:从helios到Akka.NET在到Or ...
- AutoMapperHelper
/// <summary> /// AutoMapper帮助类 /// </summary> public static class AutoMapperHelper { // ...
- matlab 绘制条形图
Matlab使用bar和barh函数来绘制二维条形图.分别是绘制二维垂直条形图和二维水平条形图. 转自:http://jingyan.baidu.com/article/64d05a02524e63d ...
- android服务之MP3播放(2)
该播放器将会直接从网络上获取资源进行播放,并提供进度条显示的功能 布局文件 布局文件中使用Seekbar组件来显示进度条 <?xml version="1.0" encodi ...
- java发送邮件
1.需要用到javax.mail怎么下载呢?百度javax.mail就会看见http://www.oracle.com/technetwork/java/index-138643.html实际上这个项 ...