lua程序设计第二版 读书笔记(24-26章)
2013-05-16 16:52
405 查看
书本下载地址 http://download.csdn.net/detail/myy2012/5349646
本部分下载地址 http://download.csdn.net/detail/myy2012/5390585
lua程序设计第二版 读书笔记(1-4章)
第一章 开始
第二章 类型与值
第三章 表达式
第四章 语句
/article/7932654.html
lua程序设计第二版 读书笔记(5-8章)
第五章 函数
第六章 深入函数
第七章 迭代器与泛型for
第八章 编译执行与错误
/article/7932655.html
lua程序设计第二版 读书笔记(9-10章)
第九章 协同程序
第十章 完整的实例
/article/7932656.html
lua程序设计第二版 读书笔记(11-14章)
第十一章 数据结构
第十二章 数据文件与持久性
第十三章 元表metatable与元方法meatmethod
第十四章 环境
/article/7932657.html
lua程序设计第二版 读书笔记(15-17章)
第十五章 模块与包
第十六章 面向对象编程
第十七章 弱引用 table
/article/7932658.html
lua程序设计第二版 读书笔记(18-21章)
第十八章 数学库
第十九章 table库
第二十章 字符串库
第二十一章 IO库
/article/7932659.html
lua程序设计第二版 读书笔记(22-23章)
第二十二章 操作系统库
第二十三章 调试库
/article/7932660.html
首先在vs中设置lua环境
工具--->选项
24.1 第一个示例
头文件Lua.h中定义了Lua提供的基础函数:包括创建Lua环境,调用Lua函数(如lua_pcall)、读写Lua环境中的全局变量、注册供Lua调用的新函数。
注:lua.h中定义所有内容都有一个lua_前缀。
头文件lauxlib.h定义了辅助库(auxiliary library, auxlib)提供的函数。辅助库并没有直接访问Lua的内部,它都是用官方的基础API来完成所有工作的。
注:lauxlib.h中定义所有内容都有一个luaL_前缀。
头文件lualib.h中定义了打开这些库的函数,而辅助库函数luaL_openlibs则可以打开所有的标准库。
Lua库中没有定义任何全局变量,它将所有的状态都保存在动态结构lua_State中,所有的C API都要求传入一个指向该结构的指针。这种实现使得Lua可以重入(reenter),稍加修改即可用于多线程的代码中。
程序调用luaL_loadbuffer来编译用户输入的每行内容。如果没有错误,返回0,并向栈中压入编译后的程序块。然后,程序调用lua_pcall(将程序块从栈中弹出),并在保护模式中运行它。注:若发生错误,就会向栈中压入一条错误消息,用lua_tostring可以获取这条消息,打印后可以用lua_pop把它从栈中删除。
24.2 栈
Lua API 中使用了一个抽象的栈,在Lua和C语言之间交换数据。几乎所有的API函数都会用到这个栈。
Lua严格地按LIFO(Last in , First out 先进后出)规范来操作这个栈。当调用Lua时,Lua只会改变栈的顶部,不过C代码有更大的自由度,它可以检索栈中间的元素,甚至在栈的任意位置插入或者删除元素。
在头文件lua.h文件中有如下的定义:
向栈中压入一个元素时,应该确保栈中具有足够的空间(当Lua启动时,或者Lua调用C语言时,栈中至少会有20个空闲的槽)。一般这些空间对于普通的应用是足够了,所有无须顾及空间上的问题。当然也有例外,这时候可以调用lua_checkstack函数来检查栈中是否有足够的空间:
int lua_checkstack( lua_State *L, int sz);
API 使用“索引”来引用栈中的元素:第一个压入栈中的元素索引为1,第二个为2,依次类推知道栈顶。此外,最后压入的元素(栈顶)索引为-1,栈顶下面的元素为-2,依次类推。
为了检查一个元素是否为特定的类型,API提供了一系列的函数lua_is*
在头文件lua.h文件中有如下的定义:
若要检查一个元素是否为真正的字符串或者数字(无须转换的),也可以用以下函数
在头文件lua.h文件中有如下的定义:
除了在C语言和栈之间交换数据的函数外,API还提供了以下这些用于普通栈操作的函数:
说明:
1.lua_gettop函数返回栈中元素的个数(栈顶元素的索引)
2.lua_settop函数将栈顶设置为一个指定的位置(修改栈中元素的数量----多着弃,少则用nil补)。注:lua_settop(L, 0); //清空栈
另外API根据这个函数还提供了一个宏:
3.lua_pushvalue函数会将指定索引上值的副本压入栈。
4.lua_remove函数删除指定索引上的元素,并将该位置之上的所有元素下移以填补空缺
5.lua_insert函数会上移所有元素以开辟一个槽的空间,然后将栈顶元素移到该位置。
6.lua_replace弹出栈顶的值,并将该值设置到指定的索引上,但它不会移动任何东西。
24.3 C API中的错误处理
Lua中所有的结构都是动态的,它们会根据需要来增长或者缩小。在Lua中有许多地方可能会发生内存分配错误,在发生错误时,使用异常来标记这些错误。因此,几乎所有的API函数都会抛出错误(即调用longjmp),而不是返回错误。
当Lua发现了例如“内存不足”这类错误时,它基本不会进行太多的处理,而是调用一个“紧急”函数(Panic Function),当这个函数返回后,Lua就好结束应用程序。(用户通过函数lua_atpanic来设置自己的“紧急”函数)
不是所有的API函数都会抛出异常,像函数luaL_newstate、lua_load、lua_pcall和lua_close都是安全的。
如果发生内存分配错误,其他大多数函数都会抛出异常。例如:luaL_loadfile无法为文件名字符串分配到足够的内存。
函数lua_cpcall类似于lua_pcall,但它接受一个C函数作为参数,然后调用这个C函数(将一个函数)。
第二十五章 扩展应用程序
lua的一项重要用途就是作为一种配置语言(configuration language)
25.1 基础
假设已经创建了一个Lua状态,这个函数调用luaL_loadfile从文件fname加载程序块,然后调用lua_pcall运行编译好的程序块。
25.2 table操作
我们可以在C语言的代码中操作Lua中的table数据,这是一个非常方便且非常实用的功能。这样不仅可以使Lua代码的结构更加清晰,也可以在C语言代码中定义等同的结构体与之对应,从而大大提高代码的可读性。
使用table来表示颜色:background={ r=0.30, g=0.10, b=0}
25.3 调用Lua函数
Lua允许在一个配置文件中定义函数,并且还允许应用程序调用这些函数。
调用函数的API协议很简单:首先,将待调用函数压入栈,并压入函数的参数;然后使用lua_pcall进行实际的调用;最后将调用结果从栈中弹出。
25.4 一个通用的调用函数
call_va 会处理所有的API函数。
函数:call_va ( “f”, “dd>d”, x, y, &z);
说明:“dd>d”表示两个双精度类型的参数和一个双精度类型的参数(d---双精度、i---整数、s---字符串);> 表示参数和结果的分隔符(如果函数没有结果,>是可选的)。
调用函数实例:
第二十六章 从lua调用C
当Lua调用C函数时,也使用了一个与C语言调用Lua时相同的栈。C函数从栈中获取函数参数,并将结果压入栈中。为了在栈中将函数结果和其他值区分开,C函数还应返回其压入栈的结果数量。
当Lua调用一个C函数时,第一个参数总是这个局部栈的索引1。
26.1 C函数
所有注册到Lua中的函数都具有相同的原型,该原型就是定义在lua.h中的lua_CFunction: typedef int ( *lua_CFunction ) ( lua_State *L )
说明:从C语言的观点来看,这个C函数仅有一个参数(Lua的状态)。它返回一个整数,表示其压入栈中的返回值数量(因此,这个函数无须在压入结果前清空栈, 在它返回后,Lua会自动删除栈中结果之下的内容)。
在注册(函数lua_pushcfunction)完后,C函数就具有与其他Lua函数一样的行为。
26.2 C模块
Lua模块是一个程序块(chunk),其中定义了一些Lua函数,这些函数通常存储为table的条目。
一旦C函数被注册之后,Lua调用这个函数并不依赖于函数名,包的位置,或者调用函数的可见规则。通常C库都有一个外部(public/extern)的用来打开库的函数。其他的函数可能都是私有的,在C中被声明为static。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
附加:Lua调用C函数实例
代码部分参考于文章 /article/4700373.html
1.首先配置vs为生成dll文件的格式 如下
2.加上代码 生成dll文件
3.运行后,可以看到debug文件下有test3.dll 文件
拷贝出来和lua文件(这边是26.lua)放在同一个目录下:
4.修改test3.dll文件名为 mytestlib.dll
如下:
5.lua文件中的内容和运行结果如下:
本实例参代码部分考于文章
/article/4700373.html
本部分下载地址 http://download.csdn.net/detail/myy2012/5390585
lua程序设计第二版 读书笔记(1-4章)
第一章 开始
第二章 类型与值
第三章 表达式
第四章 语句
/article/7932654.html
lua程序设计第二版 读书笔记(5-8章)
第五章 函数
第六章 深入函数
第七章 迭代器与泛型for
第八章 编译执行与错误
/article/7932655.html
lua程序设计第二版 读书笔记(9-10章)
第九章 协同程序
第十章 完整的实例
/article/7932656.html
lua程序设计第二版 读书笔记(11-14章)
第十一章 数据结构
第十二章 数据文件与持久性
第十三章 元表metatable与元方法meatmethod
第十四章 环境
/article/7932657.html
lua程序设计第二版 读书笔记(15-17章)
第十五章 模块与包
第十六章 面向对象编程
第十七章 弱引用 table
/article/7932658.html
lua程序设计第二版 读书笔记(18-21章)
第十八章 数学库
第十九章 table库
第二十章 字符串库
第二十一章 IO库
/article/7932659.html
lua程序设计第二版 读书笔记(22-23章)
第二十二章 操作系统库
第二十三章 调试库
/article/7932660.html
第二十四章 C API概述
要想在C函数中调用Lua代码:首先在vs中设置lua环境
工具--->选项
24.1 第一个示例
头文件Lua.h中定义了Lua提供的基础函数:包括创建Lua环境,调用Lua函数(如lua_pcall)、读写Lua环境中的全局变量、注册供Lua调用的新函数。
注:lua.h中定义所有内容都有一个lua_前缀。
头文件lauxlib.h定义了辅助库(auxiliary library, auxlib)提供的函数。辅助库并没有直接访问Lua的内部,它都是用官方的基础API来完成所有工作的。
注:lauxlib.h中定义所有内容都有一个luaL_前缀。
头文件lualib.h中定义了打开这些库的函数,而辅助库函数luaL_openlibs则可以打开所有的标准库。
Lua库中没有定义任何全局变量,它将所有的状态都保存在动态结构lua_State中,所有的C API都要求传入一个指向该结构的指针。这种实现使得Lua可以重入(reenter),稍加修改即可用于多线程的代码中。
程序调用luaL_loadbuffer来编译用户输入的每行内容。如果没有错误,返回0,并向栈中压入编译后的程序块。然后,程序调用lua_pcall(将程序块从栈中弹出),并在保护模式中运行它。注:若发生错误,就会向栈中压入一条错误消息,用lua_tostring可以获取这条消息,打印后可以用lua_pop把它从栈中删除。
#ifdef __cplusplus extern "C" { #endif #include <stdio.h> #include <string.h> #include "lua.h" #include "lualib.h" #include "lauxlib.h" #pragma comment(lib, "lua51.lib") } int main(void) { char buff[256]; int error; lua_State *L=luaL_newstate();//打开Lua luaL_openlibs(L);//打开标准库 while (NULL!=fgets(buff, sizeof(buff), stdin)) { error=luaL_loadbuffer(L, buff, strlen(buff), "line")|| lua_pcall(L, 0, 0, 0); if (error) { fprintf(stderr, "%s", lua_tostring(L, -1)); //从栈中弹出错误消息 lua_pop(L, 1); } } lua_close(L); return 0; }
24.2 栈
Lua API 中使用了一个抽象的栈,在Lua和C语言之间交换数据。几乎所有的API函数都会用到这个栈。
Lua严格地按LIFO(Last in , First out 先进后出)规范来操作这个栈。当调用Lua时,Lua只会改变栈的顶部,不过C代码有更大的自由度,它可以检索栈中间的元素,甚至在栈的任意位置插入或者删除元素。
在头文件lua.h文件中有如下的定义:
向栈中压入一个元素时,应该确保栈中具有足够的空间(当Lua启动时,或者Lua调用C语言时,栈中至少会有20个空闲的槽)。一般这些空间对于普通的应用是足够了,所有无须顾及空间上的问题。当然也有例外,这时候可以调用lua_checkstack函数来检查栈中是否有足够的空间:
int lua_checkstack( lua_State *L, int sz);
API 使用“索引”来引用栈中的元素:第一个压入栈中的元素索引为1,第二个为2,依次类推知道栈顶。此外,最后压入的元素(栈顶)索引为-1,栈顶下面的元素为-2,依次类推。
为了检查一个元素是否为特定的类型,API提供了一系列的函数lua_is*
在头文件lua.h文件中有如下的定义:
若要检查一个元素是否为真正的字符串或者数字(无须转换的),也可以用以下函数
在头文件lua.h文件中有如下的定义:
除了在C语言和栈之间交换数据的函数外,API还提供了以下这些用于普通栈操作的函数:
说明:
1.lua_gettop函数返回栈中元素的个数(栈顶元素的索引)
2.lua_settop函数将栈顶设置为一个指定的位置(修改栈中元素的数量----多着弃,少则用nil补)。注:lua_settop(L, 0); //清空栈
另外API根据这个函数还提供了一个宏:
3.lua_pushvalue函数会将指定索引上值的副本压入栈。
4.lua_remove函数删除指定索引上的元素,并将该位置之上的所有元素下移以填补空缺
5.lua_insert函数会上移所有元素以开辟一个槽的空间,然后将栈顶元素移到该位置。
6.lua_replace弹出栈顶的值,并将该值设置到指定的索引上,但它不会移动任何东西。
void testStack(lua_State* L) { lua_pushboolean(L, 1);//索引为1 lua_pushnumber(L, 10);//索引为2 lua_pushnil(L);//索引为3 lua_pushstring(L, "hello");//索引为4 stackDump(L); lua_pushvalue(L, 2);//将指定索引()上值的副本压入栈 stackDump(L); lua_replace(L, 3);//弹出栈顶的值,并将该值设置到指定的索引()上 stackDump(L); lua_settop(L, 6);//将栈顶设置为一个指定的位置 stackDump(L); lua_remove(L, -3);//删除指定索引上的元素,并将该位置之上的所有元素下移以填补空缺 stackDump(L); lua_settop(L, -5);// stackDump(L); }
24.3 C API中的错误处理
Lua中所有的结构都是动态的,它们会根据需要来增长或者缩小。在Lua中有许多地方可能会发生内存分配错误,在发生错误时,使用异常来标记这些错误。因此,几乎所有的API函数都会抛出错误(即调用longjmp),而不是返回错误。
当Lua发现了例如“内存不足”这类错误时,它基本不会进行太多的处理,而是调用一个“紧急”函数(Panic Function),当这个函数返回后,Lua就好结束应用程序。(用户通过函数lua_atpanic来设置自己的“紧急”函数)
不是所有的API函数都会抛出异常,像函数luaL_newstate、lua_load、lua_pcall和lua_close都是安全的。
如果发生内存分配错误,其他大多数函数都会抛出异常。例如:luaL_loadfile无法为文件名字符串分配到足够的内存。
函数lua_cpcall类似于lua_pcall,但它接受一个C函数作为参数,然后调用这个C函数(将一个函数)。
第二十五章 扩展应用程序
lua的一项重要用途就是作为一种配置语言(configuration language)
25.1 基础
假设已经创建了一个Lua状态,这个函数调用luaL_loadfile从文件fname加载程序块,然后调用lua_pcall运行编译好的程序块。
void load(lua_State* L, const char* fname, int* w, int* h) { if (luaL_loadfile(L, fname) || lua_pcall(L, 0, 0, 0)) { printf("Error Msg is %s.\n",lua_tostring(L,-1)); return; } lua_getglobal(L, "width"); lua_getglobal(L, "height"); if (!lua_isnumber(L, -2)) { printf("'width' should be a number\n" ); return; } if (!lua_isnumber(L, -1)) { printf("'height' should be a number\n" ); return; } *w = lua_tointeger(L, -2); *h = lua_tointeger(L, -1); }
25.2 table操作
我们可以在C语言的代码中操作Lua中的table数据,这是一个非常方便且非常实用的功能。这样不仅可以使Lua代码的结构更加清晰,也可以在C语言代码中定义等同的结构体与之对应,从而大大提高代码的可读性。
使用table来表示颜色:background={ r=0.30, g=0.10, b=0}
void load2(lua_State* L) { if (luaL_loadstring(L, "background = { r = 0.30, g = 0.10, b = 0 }") || lua_pcall(L, 0, 0, 0)) { printf("Error Msg is %s.\n", lua_tostring(L,-1)); return; } //************* lua_getglobal(L, "background"); if (!lua_istable(L, -1)) { printf("'background' is not a table.\n" ); return; } //************* lua_getfield(L, -1, "r"); if (!lua_isnumber(L, -1)) { printf("Invalid component in background color.\n"); return; } int r = (int)(lua_tonumber(L, -1) * 255); lua_pop(L, 1); //************* lua_getfield(L, -1, "g"); if (!lua_isnumber(L, -1)) { printf("Invalid component in background color.\n"); return; } int g = (int)(lua_tonumber(L,-1) * 255); lua_pop(L,1); //************* lua_pushnumber(L, 0.4); lua_setfield(L, -2, "b"); lua_getfield(L,-1,"b"); if (!lua_isnumber(L,-1)) { printf("Invalid component in background color.\n"); return; } int b = (int)(lua_tonumber(L,-1) * 255); //************* printf("r = %d, g = %d, b = %d\n", r, g, b); lua_pop(L, 1); lua_pop(L, 1); return; }
25.3 调用Lua函数
Lua允许在一个配置文件中定义函数,并且还允许应用程序调用这些函数。
调用函数的API协议很简单:首先,将待调用函数压入栈,并压入函数的参数;然后使用lua_pcall进行实际的调用;最后将调用结果从栈中弹出。
void testCallLua(lua_State* L) { if (luaL_loadfile(L, filepath)) { printf("Failed to run lua code.\n"); return; } double x = 3.0, y = 4.0; lua_getglobal(L,"foo"); lua_pushnumber(L, x); lua_pushnumber(L, y); if (lua_pcall(L, 2, 1, 0)) { printf("error is %s.\n",lua_tostring(L,-1)); return; } if (!lua_isnumber(L,-1)) { printf("function 'foo' must return a number.\n"); return; } double ret = lua_tonumber(L, -1); lua_pop(L, -1); printf("The result of call function is %f.\n", ret); }
25.4 一个通用的调用函数
call_va 会处理所有的API函数。
函数:call_va ( “f”, “dd>d”, x, y, &z);
说明:“dd>d”表示两个双精度类型的参数和一个双精度类型的参数(d---双精度、i---整数、s---字符串);> 表示参数和结果的分隔符(如果函数没有结果,>是可选的)。
void call_va(lua_State* L, const char* func, const char* sig, ...) { va_list vl; int narg=0, nres=0;//参数和结果的数量 va_start(vl, sig); lua_getglobal(L, func);//压入函数 //压入参数 for (narg=0; *sig; narg++) { //检查栈中空间 luaL_checkstack(L, 1, "too many argument"); switch (*sig++) { case 'd'://double参数 lua_pushnumber(L, va_arg(vl, double)); break; case 'i'://int参数 lua_pushinteger(L, va_arg(vl, int)); break; case 's'://字符串参数 lua_pushstring(L, va_arg(vl, char*)); break; case '>'://参数结束 break; default: printf("invalid option(%c)", *(sig-1)); } } nres=strlen(sig); if (0 != lua_pcall(L, narg, nres, 0))//完成调用 { printf("error calling %s:%s", func, lua_tostring(L, -1)); } //<检索结果> nres=-nres;//第一个结果的栈索引 while (*sig) { switch (*sig) { case 'd'://double结果 { if (!lua_isnumber(L, nres)) printf("wrong result type"); *va_arg(vl, double *) = lua_tonumber(L, nres); } break; case 'i': { if (!lua_isnumber(L, nres)) printf("wrong result type"); *va_arg(vl, int *) = (int)lua_tonumber(L, nres); } break; case 's': { if (!lua_isstring(L, nres)) printf("wrong result type"); *va_arg(vl, const char **) = lua_tostring(L, nres); } break; default: printf("invalid option (%c)", *(sig - 1)); } nres++; *sig++; } va_end(vl); }
调用函数实例:
int x=5, y=8, z=0; call_va(L, "add", "ii>i", x, y, &z); printf("x+y=%d \n", z); double xx=10.0, yy=15.0, zz=0.0; call_va(L, "add", "dd>d", xx, yy, &zz); printf("xx+yy=%f \n", zz);
第二十六章 从lua调用C
当Lua调用C函数时,也使用了一个与C语言调用Lua时相同的栈。C函数从栈中获取函数参数,并将结果压入栈中。为了在栈中将函数结果和其他值区分开,C函数还应返回其压入栈的结果数量。
当Lua调用一个C函数时,第一个参数总是这个局部栈的索引1。
26.1 C函数
所有注册到Lua中的函数都具有相同的原型,该原型就是定义在lua.h中的lua_CFunction: typedef int ( *lua_CFunction ) ( lua_State *L )
说明:从C语言的观点来看,这个C函数仅有一个参数(Lua的状态)。它返回一个整数,表示其压入栈中的返回值数量(因此,这个函数无须在压入结果前清空栈, 在它返回后,Lua会自动删除栈中结果之下的内容)。
在注册(函数lua_pushcfunction)完后,C函数就具有与其他Lua函数一样的行为。
26.2 C模块
Lua模块是一个程序块(chunk),其中定义了一些Lua函数,这些函数通常存储为table的条目。
一旦C函数被注册之后,Lua调用这个函数并不依赖于函数名,包的位置,或者调用函数的可见规则。通常C库都有一个外部(public/extern)的用来打开库的函数。其他的函数可能都是私有的,在C中被声明为static。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
附加:Lua调用C函数实例
代码部分参考于文章 /article/4700373.html
1.首先配置vs为生成dll文件的格式 如下
2.加上代码 生成dll文件
#ifdef __cplusplus extern "C" { #endif #include <stdio.h> #include <string.h> #include "lua.h" #include "lualib.h" #include "lauxlib.h" #pragma comment(lib, "lua51.lib") } //extern "C":函数必须以C的形式被导出 extern "C" int add(lua_State* L) { double op1 = luaL_checknumber(L,1); double op2 = luaL_checknumber(L,2); lua_pushnumber(L,op1 + op2); return 1; } extern "C" int sub(lua_State* L) { double op1 = luaL_checknumber(L, 1); double op2 = luaL_checknumber(L, 2); lua_pushnumber(L,op1 - op2); return 1; } //luaL_Reg结构体中{字符串,函数名} //最后一个元素的两个字段均为NULL,用于提示Lua注册函数已经到达数组的末尾。 static luaL_Reg mylibs[] = { {"add", add}, {"sub", sub}, {NULL, NULL} }; //该C库的唯一入口函数。见如下几点说明: //1. 我们可以将该函数简单的理解为模块的工厂函数。 //2. 其函数名必须为luaopen_xxx,其中xxx表示library名称。Lua代码require "xxx"需要与之对应。 //3. 在luaL_register的调用中,其第一个字符串参数为模块名"xxx",第二个参数为待注册函数的数组。 //4. 需要强调的是,所有需要用到"xxx"的代码,不论C还是Lua,都必须保持一致,这是Lua的约定, // 否则将无法调用。 extern "C" __declspec(dllexport) int luaopen_mytestlib(lua_State* L) { const char* libName = "mytestlib"; luaL_register(L, libName, mylibs); return 1; }
3.运行后,可以看到debug文件下有test3.dll 文件
拷贝出来和lua文件(这边是26.lua)放在同一个目录下:
4.修改test3.dll文件名为 mytestlib.dll
如下:
5.lua文件中的内容和运行结果如下:
require "mytestlib" --指定包名称 --在调用时,必须是package.function print(mytestlib.add(1.0,2.0)) print(mytestlib.sub(20.1,19))
本实例参代码部分考于文章
/article/4700373.html
相关文章推荐
- Spring In Action(中文第二版)读书笔记(1-1)
- 《人工智能(智能系统指南,第二版)》读书笔记——9、第八章
- 读书笔记之:鸟哥的Linux私房菜——基础学习篇(第三版) (18-26章)
- 代码大全第二版读书笔记 第二部分-创建高质量的代码 七、高质量的子程序
- C#2008与.NET 3.5 高级程序设计读书笔记(24)-- LINQ API编程
- ISM 信息存储与管理第二版 and 大话存储2 读书笔记 (1): Host, Connectivity, Disk Drive
- sams emacs 24 hour 读书笔记5
- Effctive C#第二版 读书笔记2
- 《javascript高级程序设计》第二版 读书笔记
- Effective Java 英文 第二版 读书笔记 Item 2:Consider a builder when faced with many constructor parameters.
- Effective Java 英文 第二版 读书笔记 Item 4:Attempting to enforce noninstantiability by making a class abstract does not work.
- 《lua程序设计》读书笔记 第三章:表达式
- lua程序设计第二版 读书笔记(5-8章)
- 《设计模式解析》第二版读书笔记之Facade模型
- iOS之《Effective Objective-C 2.0》读书笔记(24)
- lua元表和元方法 《lua程序设计》 13章 读书笔记
- 读书笔记------代码大全(第二版)
- 《鸟哥的Linux私房菜 基础学习篇(第二版)》 读书笔记 第07章 Linux文件和目录管理
- Effective Java 英文 第二版 读书笔记 Item 8:Obey the general contract when overriding equals
- 《WF in 24 Hours》读书笔记 - Hour 1 - Understanding Windows Workflow Foundation