无聊写的谷歌拼音颜文字扩展
谷歌输入法的颜文字扩展已经有好多了,反正也不差我再写一个吧 o(* ̄▽ ̄*)o ,表情比较多(300+)
源码和扩展文件都放在 Github 上了:https://github.com/tisyang/kaos
示例1:
示例2:
用 C 扩展写 Lua closure
这个是《programming in lua》中的有的一个例子,通过 closure(闭包)来实现一个 tuple(元组)。
元组是一种具有匿名字段的常量记录。可以用一个数字索引来检索某个字段,或者一次性检索所有字段。
这里的实现将元组表示为函数,元组的值存放在函数绑定的 upvalue 中。大概的 Lua 代码示意如下:
local tuple = {} function tuple.new(...) local t = {...} return function(index) if index then if type(index) ~= "number" then error("invalid index type") end if index < 0 then error("index is out of range") end return t[index] else return unpack(t) end end end
闭包工厂 tuple.new 中的 table t 就是用于存放元组内容的 upvalue,这个 tuple 的使用如下:
local x = tuple.new(10, "hi", {}, 4) print(x(1)) print(x(2)) print(x())
当用一个数字参数来调用此函数时,它会返回指定的字段。当不用参数来调用此函数时,则返回所有的字段。输出为:
#include <lua.h> #include <lualib.h> #include <lauxlib.h> static int t_tuple(lua_State *L) { int op = luaL_optint(L, 1, 0); if (op == 0) { /* 无参数? */ int i; /* 将所有合法 upvalue 压入栈中 */ for (i = 1; !lua_isnone(L, lua_upvalueindex(i)); i++) lua_pushvalue(L, lua_upvalueindex(i)); return i - 1; /* 栈中值的数量 */ } else { /* 获取 'op' 字段 */ luaL_argcheck(L, 0 < op, 1, "index out of range"); if (lua_isnone(L, lua_upvalueindex(op))) { /* 无此字段 */ lua_pushnil(L); /* 返回 nil 表明不存在 */ return 1; } lua_pushvalue(L, lua_upvalueindex(op)); return 1; } } static int t_new(lua_State *L) { lua_pushcclosure(L, t_tuple, lua_gettop(L)); return 1; } static const struct luaL_Reg tuplelib[] = { {"new", t_new}, {NULL, NULL} }; int luaopen_tuple(lua_State *L) { luaL_register(L, "tuple", tuplelib); return 1; }
编译成“tuple.dll”(windows 下)然后仍然用上面的 tuple 使用代码测试,不过要先“require 'tuple'”来加载这个扩展。DLL 中的需要导出 lutopen_tuple 这个函数符号。
t_new 是创建元组的工厂函数。将需要作为 upvalue 的参数实现压入栈中,然后调用 lua_pushcclosure 来创建一个基于 t_tuple 的 closure 。lua_gettop 返回栈的大小,在这里也就等于已经压入栈中作为 upvalue 的数量。lua_upvalueindex 是一个用来索引 upvalue 的宏,当索引一个不存在的 upvalue ,结果会是一个类型为 LUA_TNONE 的伪值(pseudo-value),当索引超出当前栈范围时候,也会得到这样的 LUA_TNONE 的伪值。不能以负数来调用 lua_upvalueindex ,所以做了范围检查,luaL_argcheck(L, 0 < op, 1, "index out of range") 第二个参数是个条件表达式,第三个是检查的参数数量,最后一个是检查失败传递的消息。
用于检测可选参数的函数是 luaL_optint ,它允许参数不存在,如果不存在,则返回一个指定的默认值,也就是最后一个参数。
给 lua 写 C 模块示例
主要内容出在《programming in lua》第二版 26章
本例是在 VS2008下,配合 lua on windows 包内的 lua 库使用。
1. 配置好 VS 的lua 环境,主要是引用的头文件目录,库目录,然后将 dll 加入 path 环境。
2. 新建一个 Win32 DLL 空项目(例如 "l_lib",这也是本例所提供的模块名),配置项目 链接器》输入》附加依赖库:lua5.1.lib
3. 添加一个 C 源文件:
#include <math.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
static int l_sin(lua_State *L)
{
double d = luaL_checknumber(L, 1);
lua_pushnumber(L, sin(d));
return 1;
}
static const struct luaL_Reg l_lib[] = {
{"l_sin", l_sin},
{NULL, NULL}
};
int luaopen_l_lib(lua_State *L)
{
luaL_register(L, "l_lib", l_lib);
return 1;
}
4. 给项目添加一个模块定义文件(.def),用于导出dll 符号:
require 'l_lib'
print(l_lib.l_sin(1))
所有注册到 Lua 中的函数都具有相同的原型,该原型就是定义在 lua.h 中的 lua_CFunction:typedef int (*lua_CFunction)(lua_State *L);从 C 语言的观点来看,这个 C 函数仅有一个参数,即 Lua 的状态。它返回一个整数,表示其压入栈中的返回值数量。因此,这个函数无须在压入结果前清空栈。在它返回后,Lua 会自动删除栈中结果之下的内容。
lua 之爱
《programming in lua》第二版的中文版这本书快看完了,中间夹杂着英文版的看,因为翻译并非完美,而且英文版的也很容易看懂。
这里是我的读书笔记:http://book.douban.com/people/tisyang/annotation/3076942/ 但并非每个要点都会有笔记。
lua 是一个值得学习的语言而且也不会需要过多时间,这本书是学 lua 一定要看的,云风 大神也这样推荐。
愈学愈爱