日期:2014.8.11
PartⅣ The C API
29 User-Defined Types in C
在之前的例子里,已经介绍过如果通过用C写函数来扩展Lua。在本章,将会介绍通过用C写新的类型来扩展Lua,将会使用到元方法等特性来实现这个功能。
以一个例子来介绍本章将要介绍的,例子实现的功能是实现了一个简单的类型:boolean arrays。实现这个功能主要是这种方法不需要太复杂的算法,因此可以将精力放在API的讨论上。当然我们可以在Lua中用一个table来实现,但是用一个C来实现,where we store each entry in one single bit(指的是用一个位数来表现boolean值?).,比用table来实现节省了3%的内存开销。
实现这个类型首先是需要做一些定义:
#include <limits.h>
#define BITS_PER_WORD (CHAR_BIT*sizeof(unsigned int))
#define I_WORD(i) ((unsigned int)(i) / BIT_PER_WORD)
#define I_BIT(i) (1 << ((unsigned int)(i) % BIT_PER_WORD))
BITS_PER_WORD 表示一个无符整型数中的位的数量。宏I_WORD 计算给定的数中位的数量,宏I_BIT 则计算了求一个数正数位的掩码。
以下面的struct代表我们定义的类型:
e.g.
typedef struct NumArray
{
int size;
unsigned int values[1];
} NumArray;
定义数组values的大小为1,实现一个占位符,因为C 89 不允许数组的大小为0.当我们allocate 这个数组的时候将会重新设定其实际大小。下面的表达式则计算了n个元素数组的实际大小:
e.g.
sizeof(NumArray) + I_WORD( n -1 ) * sizeof(unsigned int)
29.1 UserData
首先要考虑的是在Lua中用什么来代表NumArray这个数据结构。Lua提供了一个基础的类型:userdata。一个userdatum提供了一块内存区域,没有做任何预定义的操作,因此可以用这个类型存储任何东西。
函数lua_newuserdata 根据给定的大小分配了一块内存区域,将相应的userdatum推进栈中,然后返回这个内存块的地址:
void* lua_newuserdata(lua_State *L,size_t size);
而如果需要以其他用途来分配内存,使用给定大小的指针创建一个userdatum,然后用一个指针存储至实际的内存块上是非常容易的。在后面的章节会介绍这个。
结合使用lua_newuserdata ,那么创建一个新的boolean arrays 将会是这样实现的:
e.g.
static int newarray(lua_State *L)
{
int i;
size_t nbytes;
NumArray *a;
int n = luaL_checkint(L,1);
luaL_argcheck(L,n >= 1,1,"invalid siez");
nbytes = sizeof(NumArray) + I_WORD(n -1)*sizeof(unsign