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的更多相关文章

  1. Lua中使用table实现的其它5种数据结构

    Lua中使用table实现的其它5种数据结构 lua中的table不是一种简单的数据结构,它可以作为其他数据结构的基础,如:数组,记录,链表,队列等都可以用它来表示. 1.数组 在lua中,table ...

  2. 递归打印lua中的table

    在lua中,table是比较常用的数据形式,有时候为了打印出里面的内容,需要做一些特殊处理. 废话不多讲,直接粘代码: print = release_print -- 递归打印table local ...

  3. lua中遍历table的几种方式比较

    当我在工作中使用lua进行开发时,发现在lua中有4种方式遍历一个table,当然,从本质上来说其实都一样,只是形式不同,这四种方式分别是: for key, value in pairs(tbtes ...

  4. Lua中的table函数库

    table.concat(table, sep,  start, end) concat是concatenate(连锁, 连接)的缩写. table.concat()函数列出参数中指定table的数组 ...

  5. lua中求table长度

    关于lua table介绍,看以前的文章http://www.cnblogs.com/youxin/p/3672467.html. 官方文档是这么描述#的: 取长度操作符写作一元操作 #. 字符串的长 ...

  6. Lua中的table构造式(table constructor)

    最简单的构造式就是一个空构造式{},用于创建一个空table. 构造式还可以用于初始化数组.例如,以下语句:days = {"Sunday", "Monday" ...

  7. lua中求table长度--(转自有心故我在)

    关于lua table介绍,看以前的文章http://www.cnblogs.com/youxin/p/3672467.html. 官方文档是这么描述#的: 取长度操作符写作一元操作 #. 字符串的长 ...

  8. Lua中获取table长度

    -- table.getn(tableName) 得到一个table的大小,等同于操作符# -- 要注意的是:该table的key必须是有序的,索引是从1开始的. --例如有序的 local xian ...

  9. lua中使用table实现类和继承

    --因为只有当读写不存在的域时,才会触发__index和__newindex classA = {className = "classA",name="classAIns ...

随机推荐

  1. Python面试题 —— 计算列表中出现最多次的字符

    给你一个其中包含不同的英文字母和标点符号的文本,你要找到其中出现最多的字母,返回的字母必须是小写形式, 当检查最想要的字母时,不区分大小写,所以在你的搜索中 "A" == &quo ...

  2. 细数Javascript技术栈中的四种依赖注入

    作为面向对象编程中实现控制反转(Inversion of Control,下文称IoC)最常见的技术手段之一,依赖注入(Dependency Injection,下文称DI)可谓在OOP编程中大行其道 ...

  3. (十七)迭代器模式详解(foreach的精髓)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 各位好,很久没以LZ的身份和 ...

  4. 【转】赶集网mysql开发36军规

    原文链接:https://segmentfault.com/a/1190000004711147 写在前面的话:总是在灾难发生后,才想起容灾的重要性:总是在吃过亏后,才记得曾经有人提醒过. (一)核心 ...

  5. Python 练习册

    01:将你的 QQ 头像(或者微博头像)右上角加上红色的数字,类似于微信未读信息数量那种提示效果 [图像处理] 类似于图中效果: py 2.7代码: from PIL import Image, Im ...

  6. 基本数据类型-集合(set)_上周内容回顾(字符串_数字_列表_元组_字典_集合)

    上周内容回顾 1.字符串 2.数字 除了布尔类型外,int.long.float和complex都可以使用的运算为:加.减.乘.除.整除.幂运算和取余 3.列表和元组 列表的内容可变,可以包含任意对象 ...

  7. Node.js项目目录介绍

    新建的项目结构应该是这样 bin:项目的启动文件,也可以放其他脚本. node_modules:用来存放项目的依赖库. public:用来存放静态文件(css,js,img). routes:路由控制 ...

  8. 思维导图分享以及MindManager使用说明

    来源于: http://www.cnblogs.com/muhongxing/archive/2009/12/22/1628782.html http://www.cnblogs.com/muhong ...

  9. ps打造逼真印章效果

    新建500*500px--->路径工具 最后通过 通道扣取选取,填充白色,即可

  10. ITEM M6 自增(INCREMENT)、自减(DECREMENT)操作符前缀形式与后缀形式的区别

    前缀自增 UPInt & UPint::operator++() { *this+=1; return *this; } 后缀自增 const UPInt & UPint::opera ...