lua程序设计第二版 读书笔记(27-28章)

来源:互联网 发布:closure php 编辑:程序博客网 时间:2024/06/05 06:25

书本下载地址                     http://download.csdn.net/detail/myy2012/5349646

本部分下载地址              http://download.csdn.net/detail/myy2012/5433541

 

ps:最近几个月在公司都没事做,然后最近几天一直想着要不要辞职。最后还是跟领导说了,领导说再呆阵子吧,上级的上级。

      瞬间我也不懂了,纠结了好久。哎,不管不管,不过也好几天没看这边书了。补上。快看完了。

 

 

lua程序设计第二版 读书笔记(1-4章)
第一章 开始
第二章 类型与值
第三章 表达式
第四章 语句
http://blog.csdn.net/myy2012/article/details/8900424

lua程序设计第二版 读书笔记(5-8章)
第五章 函数
第六章 深入函数
第七章 迭代器与泛型for
第八章 编译执行与错误
http://blog.csdn.net/myy2012/article/details/8906466

lua程序设计第二版 读书笔记(9-10章)
第九章 协同程序
第十章 完整的实例
http://blog.csdn.net/myy2012/article/details/8911206

lua程序设计第二版 读书笔记(11-14章)
第十一章 数据结构
第十二章 数据文件与持久性
第十三章 元表metatable与元方法meatmethod
第十四章 环境
http://blog.csdn.net/myy2012/article/details/8914457

lua程序设计第二版 读书笔记(15-17章)
第十五章 模块与包
第十六章  面向对象编程
第十七章 弱引用 table
http://blog.csdn.net/myy2012/article/details/8921632

lua程序设计第二版 读书笔记(18-21章)
第十八章 数学库
第十九章 table库
第二十章 字符串库
第二十一章 IO库
http://blog.csdn.net/myy2012/article/details/8925895

lua程序设计第二版 读书笔记(22-23章)
第二十二章 操作系统库
第二十三章 调试库
http://blog.csdn.net/myy2012/article/details/8930181

 

 

 

第二十七章  编写C函数的技术

 

27.1 数组操作

API为数组操作提供了两个函数:

void lua_rawgeti( lua_State *L,  int index,  int key);void lua_rawseti( lua_State* L,  int index,  int key);

其中:index表示table在栈中的位置,key表示元素在table中的位置。

假设t为正数,那么调用函数lua_rawgeti(L, t, key)等价于

  lua_pushnumber(L, key);  lua_rawget(L, t);

 调用函数lua_seti(L, t, key) 等价于

  lua_pushnumber(L, key);  lua_insert(L, -2);  lua_rawset(L, t);

 

27.2 字符串操作

当一个C函数从Lua收到一个字符串参数时,必须遵守两条规则:1.不要在访问字符串时从栈中弹出它;2.不要修改字符串。

LuaC API中主要提供了两个操作Lua字符串的函数,即:

void lua_pushlstring(lua_State *L, const char *s, size_t l); 
const char* lua_pushfstring(lua_State* L, const char* fmt, ...);

注:第一个API用于截取指定长度的子字符串,同时将其压入栈中。

第二个API类似于C库中的sprintf函数,将格式化后的字符串压入栈中。该函数只支持%%(表示字符%)%s(表示字符串)%d(表示整数)%f(表示Lua中的number)%c(表示字符)

27.3C函数中保存状态

对一个Lua函数来说,有3种地方可以存放非局部的数据(全局变量、函数环境、非局部变量)。而C API也提供了3种地方来保存这类数据(注册表、环境、upvalue)。

1. 注册表

  注册表是一个全局的table,它只能被C代码访问。通常用于保存多个模块间的共享数据。

注册表总是位于一个“伪索引”上,这个值由LUA_REGISTRYINDEX定义。例如:为了获取注册表中key为“Key”的值:lua_getfield( L, LUA_REGISTRYINDEX, “Key”);

在注册表中不应使用数字类型的key,因为这种类型的key是被“引用系统”所保留的。这个系统是由辅助库中的一系列繁琐组成的,它可以在向一个table 存储value时,忽略如何创建一个唯一的key

int  r = luaL_ref( L, LUA_REGISTRYINDEX);

Lua API中提供了专门的用来连接字符串的函数lua_concat。等价于Lua中的..操作符:自动将数字转换成字符串,如果有必要的时候还会自动调用metamethods。另外,她可以同时连接多个字符串。调用lua_concat(L,n)将连接(同时会出栈)栈顶的n个值,并将最终结果放到栈顶。

另一个有用的函数是lua_pushfstring

  const char *lua_pushfstring (lua_State *L,  const char *fmt, ...);

2. C函数的环境

Lua中注册的所有C函数都有自己的环境table,一个函数可以像访问注册表那样通过一个伪索引(LUA_ENVIRONINDEX)来访问它的环境table

通常,使用这些函数的方法与在Lua模块中使用环境的方法差不多。即先为模块创建一个新的table,然后使模块中的所有函数都共享这个table。也就是修改主程序的环境,然后所有新建的函数都会自动地套用这个新环境。附上C语言中设置环境的代码:

  int  luaopen_foo( lua_State* L)  {  lua_newtable(L);  lua_replace(L, LUA_ENVIRONINDEZX);  luaL_register( L, <库名>, <函数列表>);  }

3. upvalue

注册表提供了全局变量的存储,环境提供了模块变量的存储,而upvaue机制实现了一种类似于C语言中静态变量的机制,这种变量只在一个特定的函数可见。

每当在Lua中创建一个函数时,都可以将任意数量的upvalue与整个函数相关联,每个upvalue都可以保存一个Lua的值;以后,在调用这个函数时,就可以通过伪索引来访问这些upvalue

将这种C函数与upvalue的关联称为closure。一个C closure 类似于Lua closureclosure可以用同一个函数代码来创建多个closure,每个closure可以拥有不同的upvalue

 

第二十八章 用户自定义类型

28.1 userdata

这一部分结合书中给出的函数来分析。

第一步:定义一些宏

//无符号整型bit数量  CHAR_BIT == 8(limits.h 中有定义)#define BITS_PER_WORD (CHAR_BIT*sizeof(unsigned int))//根据给定的索引来计算对应的bit位所存放的word(字)#define I_WORD(i) ((unsigned int)(i)/BITS_PER_WORD )//计算出一个掩码,用于访问这个word的正确bit#define I_BIT(i) (i<<((unsigned int )(i)%BITS_PER_WORD))

Ps:不要把这些宏想的那么可怕那么复杂,其实在32位的机子上,第一个为16,第二个为i/1616的倍数取整的结果),第三个为i%16i左移 “对16求余的结果” 位)

第二步:定义结构体

typedef struct NumArray {int size;unsigned int value[1];} NumArray;

第三步:用于新建数组的函数newarray

static int newarray (lua_State *L) {unsigned int i;int n;size_t nbytes;NumArray* a;n = luaL_checkint(L, 1);luaL_argcheck(L, n>=1, 1, "invalid size");nbytes = sizeof(NumArray)+I_WORD(n-1)*sizeof(unsigned int);a = (NumArray*)lua_newuserdata(L,  nbytes);//a->size = n;for (i=0; i<=I_WORD(n-1); i++)a->value[i]=0;--数组中的value初始化为0return 1;}

函数说明:

第五、六行-- 检查传入的参数是否为整型,且数值是否大于1

错误的调用如下:

相应的报错如下:

第八行中--函数lua_newuserdata 会根据指定的大小分配一块内存,并将对应的userdata压入栈中,最后返回这个内存块的地址。(函数原型:void * lua_newuserdata( lua_State * L, size_t size);

lua_newuserdata函数按照指定的大小分配一块内存,将对应的userdatum放到栈内,并返回内存块的地址。

第四步:用于设置数组的函数setarray

为了存储元素,我们使用类似array.set(array, index, value)调用,后面我们将看到如何使用metatables来支持常规的写法array[index] = value

static int setarray (lua_State *L) {NumArray* a = (NumArray*)lua_touserdata(L, 1);int index = luaL_checkint(L,  2)-1;//在lua中的数组下标从1开始,符合lua的习惯。luaL_checkany(L, 3);luaL_argcheck(L, a!=NULL, 1, "'array' expected");luaL_argcheck(L, 0<=index && index<a->size, 2, "index out of range");if (lua_toboolean(L, 3)){a->value[I_WORD(index)] |= I_BIT(index);//设置bit}else{a->value[I_WORD(index)] &= ~I_BIT(index);//重置bit}return 0;}

函数说明:

第一行NumArraya = (NumArray*)lua_touserdata(L, 1); --保证第一个参数为NumArray类型;否则报错。例如:

luaL_checkany(L, 3); --检查第三个参数,有值即可,该值为结构体中value的值;否则报错。例如:

luaL_argcheck(La!=NULL, 1, "'array' expected");

luaL_argcheck(L, 0<=index && index<a->size, 2, "index out of range");

函数luaL_argcheck 用于检查传入的参数是否满足一定的条件;否则报错。例如:

设置bit和重置bit 涉及到部分汇编的东西,相信接触的人都知道。|=  和 &= ~  

(其中:&是按位与、|是按位或、~是按位非)

各操作的结果如下:

1&0=0, 0&1=0, 0&0=0, 1&1=1
1|0=1, 0|1=1, 0|0=0, 1|1=1
~1=0,~0=1

第五步 获取数组中value的函数

static int getarray (lua_State *L) {NumArray* a = (NumArray*)lua_touserdata(L, 1);int index = luaL_checkint(L, 2)-1;luaL_argcheck(L, a!=NULL, 1, "'array' expected");luaL_argcheck(L, 0<=index && index<a->size, 2, "index out of range");lua_pushboolean(L, a->value[I_WORD(index)] & I_BIT(index));return 1;} 

 

函数说明:

前面几行的函数在前面出现,语句 lua_pushboolean(L, a->value[I_WORD(index)] & I_BIT(index));  根据索引号返回相应value中的值。例如:

第六步 获取数组的大小

static int getsize (lua_State *L) {NumArray* a = (NumArray*)lua_touserdata(L, 1);luaL_argcheck(L, a!=NULL, 1, "'array' expected");lua_pushinteger(L, a->size);return 1;}

函数说明:

类似于getarray函数的分析。

第七步 初始化我们的库

static const struct luaL_reg arraylib [] = {{"new", newarray},{"set", setarray},{"get", getarray},{"size", getsize},{NULL, NULL}};

说明:

可以在文件lauxlib.h 中找到 luaL_reg 结构体如下:

给我们定义的函数取个来个相关联的名字。

最后一个{NULL, NULL} 则是提示库中函数定义的结束。

第八步 调用函数 luaL_register

int luaopen_array (lua_State *L) {  luaL_register(L, "array", arraylib);return 1;}

以上都在vs中编写好了。然后生成.dll文件(array.dll

lua文件放在同一个目录下即可。

应用 在lua文件中

附加 vs中完整的代码  整个文件已经在下载那边给出地址了

http://download.csdn.net/detail/myy2012/5433541

 

#ifdef __cplusplusextern "C"{#endif#include <stdio.h>#include <string.h>#include "lua.h"#include "lualib.h"#include "lauxlib.h"#pragma comment(lib, "lua51.lib")}#include <limits.h>//无符号整型bit数量CHAR_BIT == 8#define BITS_PER_WORD (CHAR_BIT*sizeof(unsigned int))//根据给定的索引来计算对应的bit位所存放的word(字)#define I_WORD(i) ((unsigned int)(i)/BITS_PER_WORD )//计算出一个掩码,用于访问这个word的正确bit#define I_BIT(i) (i<<((unsigned int )(i)%BITS_PER_WORD))typedef struct NumArray {int size;unsigned int value[1];} NumArray;//创建一个新的布尔数组static int newarray(lua_State* L){unsigned int i;int n;size_t nbytes;NumArray* a;n = luaL_checkint(L, 1);luaL_argcheck(L, n>=1, 1, "invalid size");nbytes = sizeof(NumArray)+I_WORD(n-1)*sizeof(unsigned int);a = (NumArray*)lua_newuserdata(L, nbytes);//a->size = n;for (i=0; i<=I_WORD(n-1); i++){a->value[i]=0;}return 1;}//static int setarray(lua_State* L){NumArray* a = (NumArray*)lua_touserdata(L, 1);int index = luaL_checkint(L, 2)-1;luaL_checkany(L, 3);luaL_argcheck(L, a!=NULL, 1, "'array' expected");luaL_argcheck(L, 0<=index && index<a->size, 2, "index out of range");if (lua_toboolean(L, 3)){a->value[I_WORD(index)] |= I_BIT(index);//设置bit}else{a->value[I_WORD(index)] &= ~I_BIT(index);//重置bit}return 0;}//检索元素static int getarray(lua_State* L){NumArray* a = (NumArray*)lua_touserdata(L, 1);int index = luaL_checkint(L, 2)-1;luaL_argcheck(L, a!=NULL, 1, "'array' expected");luaL_argcheck(L, 0<=index && index<a->size, 2, "index out of range");lua_pushboolean(L, a->value[I_WORD(index)] & I_BIT(index));return 1;}//检索数组的大小static int getsize(lua_State* L){NumArray* a = (NumArray*)lua_touserdata(L, 1);luaL_argcheck(L, a!=NULL, 1, "'array' expected");lua_pushinteger(L, a->size);return 1;}//初始化这个库static const struct luaL_Reg arraylib[]= {{"new", newarray},{"set", setarray},{"get", getarray},{"size", getsize},{NULL, NULL}};//extern "C" __declspec(dllexport)int luaopen_array(lua_State* L){luaL_register(L, "array", arraylib);return 1;
}

28.2  元表

一种辨别不同类型的userdata 的方法是:为每种类型创建一个唯一的元表。每当创建一个userdata后,就用相应的元表来标记它。而每当得到一个userdata后,就检查它是否拥有正确的元表。(由于Lua代码不能改变userdata的元表,因此也就无法欺骗代码了。)

另外还需要有个地方来存储这个行的元表,然后才能用它来创建新的userdata,并检查给定的userdata是否具有正确的类型。

Lua中,通常习惯是将所有新的C类型注册到注册表中,以一个类型名作为key,元表作为value。(由于注册表中还有其他的内容,所有必须小心地选择类型名,以避免与key冲突。

下面来看具体的实现(接着上一步userdata的内容):

第一步 增加一个检查参数的宏

#define checkarray(L)  (NumArray*)luaL_checkudata(L, 1,  "LuaBook.array")

说明:

函数 luaL_checkudata作用:

可以检查栈中指定位置上是否为一个userdata,并且是否具有与给定名称相匹配的元表。(返回这个userdata地址,否则引发一个错误。)

函数原型: void *luaL_checkudata (lua_State *L, int index, const char *tname);

于是在之前的基础上就可以在getsize函数中修改为:

//检索数组的大小

static int getsize(lua_State* L){NumArray* a = checkarray(L);lua_pushinteger(L, a->size);return 1;}
第二步 增加一个索引参数是否合法的函数 
static unsigned int * getindex(lua_State* L, unsigned int *mask){NumArray* a = checkarray(L);int index = luaL_checkint(L, 2)-1;luaL_argcheck(L, 0<=index && index< a->size, 2, "index out of range");//返回元素地址*mask = I_BIT(index);return &a->value[I_WORD(index)];}

函数说明:

整合了之前函数setarraygetarray中一段相同代码来检查第二个索引参数。

详见上一部分userdata中的相关函数说明。

在之前的基础上修改setarray函数和getarray函数:

static int setarray(lua_State* L){unsigned int mask;unsigned int* entry = getindex(L, &mask);luaL_checkany(L, 3);if (lua_toboolean(L, 3)){*entry |= mask;//设置bit}else{*entry &= ~mask;//重置bit}return 0;}//检索元素static int getarray(lua_State* L){unsigned int mask;unsigned int* entry = getindex(L, &mask);lua_pushboolean(L, *entry & mask);return 1;}

//检索元素

static int getarray(lua_State* L){unsigned int mask;unsigned int* entry = getindex(L, &mask);lua_pushboolean(L, *entry & mask);return 1;}

第三步 在newarray函数分钟添加2行luaL_getmetatable(L, "LuaBook.array");lua_setmetatable(L, -2);

函数说明:

使其能为所有新建的数组设置这个元表,在注册表中检索与他那么关联的元表。

函数原型:void lua_getmetatable( lua_State * L, const char * tname);

第四步 修改打开库的函数

//打开库的函数int luaopen_array (lua_State *L) {luaL_newmetatable(L, "LuaBook.array");//为数组创建一个元表luaL_register(L, "array", arraylib);return 1;}

函数说明:

创建一个新的table用作元表,并将其压入栈顶,然后将这个table与注册表中的指定名称关联起来。

函数原型:int luaL_newmetatable(lua_State*L, const char * tname);

应用 在lua文件中与前一部分相同。具体调用:

不过此时试图这样调用 array.get(io.stdin, 10),就会得到一个错误的消息:

而在之前的userdata中则 编译通过。

这样的结果就使内存找到破坏(如果幸运的话,可能会得到一个索引超出范围的错误)。

但对于有些Lua库来说,这种行为是不可接受的。问题的原因不在于如何使用一个C程序库,而在与程序库不应破坏C数据或在Lua中导致核心转储(Core Dump)。

附加 vs中完整的代码 在下载地址中有

http://download.csdn.net/detail/myy2012/5433541

#ifdef __cplusplusextern "C"{#endif#include <stdio.h>#include <string.h>#include "lua.h"#include "lualib.h"#include "lauxlib.h"#pragma comment(lib, "lua51.lib")}#include <limits.h>//无符号整型bit数量CHAR_BIT == 8#define BITS_PER_WORD (CHAR_BIT*sizeof(unsigned int))//根据给定的索引来计算对应的bit位所存放的word(字)#define I_WORD(i) ((unsigned int)(i)/BITS_PER_WORD )//计算出一个掩码,用于访问这个word的正确bit#define I_BIT(i) (i<<((unsigned int )(i)%BITS_PER_WORD))//检查参数是否合法#define checkarray(L) (NumArray*)luaL_checkudata(L, 1, "LuaBook.array")typedef struct NumArray {int size;unsigned int value[1];} NumArray;//检查索引的参数是否合法static unsigned int * getindex(lua_State* L, unsigned int *mask){NumArray* a = checkarray(L);int index = luaL_checkint(L, 2)-1;luaL_argcheck(L, 0<=index && index< a->size, 2, "index out of range");//返回元素地址*mask = I_BIT(index);return &a->value[I_WORD(index)];}static int newarray (lua_State *L) {unsigned int i;int n;size_t nbytes;NumArray* a;n = luaL_checkint(L, 1);luaL_argcheck(L, n>=1, 1, "invalid size");nbytes = sizeof(NumArray)+I_WORD(n-1)*sizeof(unsigned int);a = (NumArray*)lua_newuserdata(L, nbytes);for (i=0; i<=I_WORD(n-1); i++){a->value[i]=0;}luaL_getmetatable(L, "LuaBook.array");lua_setmetatable(L, -2);a->size = n;return 1;//新的userdata已在栈中}//static int setarray(lua_State* L){unsigned int mask;unsigned int* entry = getindex(L, &mask);luaL_checkany(L, 3);if (lua_toboolean(L, 3)){*entry |= mask;//设置bit}else{*entry &= ~mask;//重置bit}return 0;}//检索元素static int getarray(lua_State* L){unsigned int mask;unsigned int* entry = getindex(L, &mask);lua_pushboolean(L, *entry & mask);return 1;}//检索数组的大小static int getsize(lua_State* L){NumArray* a = checkarray(L);lua_pushinteger(L, a->size);return 1;}//初始化这个库static const struct luaL_Reg arraylib[]= {{"new", newarray},{"set", setarray},{"get", getarray},{"size", getsize},{NULL, NULL}};//extern "C" __declspec(dllexport)//打开库的函数int luaopen_array (lua_State *L) {luaL_newmetatable(L, "LuaBook.array");//为数组创建一个元表luaL_register(L, "array", arraylib);return 1;}

28.3面向对象的访问

郁闷的是我按照书上的例子写了2

static const struct luaL_Reg arraylib_f[]= {{"new", newarray},{NULL, NULL}};static const luaL_Reg arraylib_m[]={{"set", setarray},{"get", getarray},{"size", getsize},{"__tostring", array2string},{NULL, NULL}};

来替换之前的那个 

static const struct luaL_Reg arraylib[]= {{"new", newarray},{"set", setarray},{"get", getarray},{"size", getsize},{NULL, NULL}};

竟然在lua文件中运行出错。

然后我在想为什么我在lua文件中运行的new那一行不会报错呢?

于是我改了

static const struct luaL_Reg arraylib_f[]= {{"set", setarray},{"get", getarray},{"size", getsize},{"__tostring", array2string},{"new", newarray},{NULL, NULL}};

把初始化库中的函数对于的东西跟new放到一起了。

结果在lua中编译类似面向对象的语句竟然可以编译通过。我也不知道为什么,谁知道的说一声啊。

2文件放在同一个目录下运行:

跟前面一节中相比较除了刚刚说的对库的初始化不同外,还有在函数 

//打开库的函数

int luaopen_array (lua_State *L) {luaL_newmetatable(L, "LuaBook.array");//为数组创建一个元表//元表.__index = 元表lua_pushvalue(L, -1);lua_setfield(L, -2, "__index");luaL_register(L, NULL, arraylib_m);luaL_register(L, "array", arraylib_f);return 1;}

按照我之前那个“逻辑”,连luaL_register(L, NULL, arraylib_m); 这个语句都可以不要了,arraylib_m 也 不要定义了。

附加这部分的代码 在给出的下载地址中有

http://download.csdn.net/detail/myy2012/5433541

#ifdef __cplusplusextern "C"{#endif#include <stdio.h>#include <string.h>#include "lua.h"#include "lualib.h"#include "lauxlib.h"#pragma comment(lib, "lua51.lib")}#include <limits.h>//无符号整型bit数量CHAR_BIT == 8#define BITS_PER_WORD (CHAR_BIT*sizeof(unsigned int))//根据给定的索引来计算对应的bit位所存放的word(字)#define I_WORD(i) ((unsigned int)(i)/BITS_PER_WORD )//计算出一个掩码,用于访问这个word的正确bit#define I_BIT(i) (i<<((unsigned int )(i)%BITS_PER_WORD))//检查参数是否合法#define checkarray(L) (NumArray*)luaL_checkudata(L, 1, "LuaBook.array")typedef struct NumArray {int size;unsigned int value[1];} NumArray;//函数声明int array2string (lua_State *L);//检查索引的参数是否合法static unsigned int * getindex(lua_State* L, unsigned int *mask){NumArray* a = checkarray(L);int index = luaL_checkint(L, 2)-1;luaL_argcheck(L, 0<=index && index< a->size, 2, "index out of range");//返回元素地址*mask = I_BIT(index);return &a->value[I_WORD(index)];}static int newarray (lua_State *L) {unsigned int i;int n;size_t nbytes;NumArray* a;n = luaL_checkint(L, 1);luaL_argcheck(L, n>=1, 1, "invalid size");nbytes = sizeof(NumArray)+I_WORD(n-1)*sizeof(unsigned int);a = (NumArray*)lua_newuserdata(L, nbytes);a->size = n;for (i=0; i<=I_WORD(n-1); i++){a->value[i]=0;}luaL_getmetatable(L, "LuaBook.array");lua_setmetatable(L, -2);return 1;//新的userdata已在栈中}//static int setarray(lua_State* L){unsigned int mask;unsigned int* entry = getindex(L, &mask);luaL_checkany(L, 3);if (lua_toboolean(L, 3)){*entry |= mask;//设置bit}else{*entry &= ~mask;//重置bit}return 0;}//检索元素static int getarray(lua_State* L){unsigned int mask;unsigned int* entry = getindex(L, &mask);lua_pushboolean(L, *entry & mask);return 1;}//检索数组的大小static int getsize(lua_State* L){NumArray* a = checkarray(L);lua_pushinteger(L, a->size);return 1;}//初始化这个库static const struct luaL_Reg arraylib[]= {//{"new", newarray},//{"set", setarray},//{"get", getarray},//{"size", getsize},{NULL, NULL}};//static const struct luaL_Reg arraylib_f[]= {{"set", setarray},{"get", getarray},{"size", getsize},{"__tostring", array2string},{"new", newarray},{NULL, NULL}};//static const luaL_Reg arraylib_m[]={//{"set", setarray},//{"get", getarray},//{"size", getsize},//{"__tostring", array2string},{NULL, NULL}};//int array2string (lua_State *L) {NumArray *a = checkarray(L);lua_pushfstring(L, "array(%d)", a->size);return 1;}//extern "C" __declspec(dllexport)//打开库的函数int luaopen_array (lua_State *L) {luaL_newmetatable(L, "LuaBook.array");//为数组创建一个元表//元表.__index = 元表lua_pushvalue(L, -1);lua_setfield(L, -2, "__index");//luaI_openlib(L, NULL, arraylib_m, 0);//luaI_openlib(L, "array", arraylib_f, 0);//luaL_register(L, NULL, arraylib_m);luaL_register(L, "array", arraylib_f);return 1;}

28.4 数组访问

另一种面向对象写法是使用常规数组访问的写法。

相当于写a:get(i),可以简单地写成a[i]

实例如下:

说明:直接沿用上一节的array.dll 文件,即这2个在同一目录下即可。

运行结果:

 

28.5 轻量级userdata light userdata

  之前介绍的是full userdataLua还提供了另一种轻量级userdata(light userdata)。事实上,轻量级userdata仅仅表示的是C指针的值,即(void*)。由于它只是一个值,所以不用创建。如果需要将一个轻量级userdata放入栈中,调用lua_pushlightuserdata即可。full userdatalight userdata之间最大的区别来自于相等性判断,对于一个full userdata,它只是与自身相等,而light userdata则表示为一个C指针,因此,它与所有表示同一指针的light userdata相等。再有就是light userdata不会受到垃圾收集器的管理,使用时就像一个普通的整型数字一样

 

原创粉丝点击