目录
2.4、功能库代码
经过上一节的学习,大家应该也都清楚了怎么才能去添加一些驱动库。一般情况下2.3小节提供的驱动库也够用了。有时候我们不仅仅是驱动设备,还需要运行一些软件算法,比如sha1、md5这些信息摘要算法,还有一些图片的解码算法。json数据处理等等。
这些算法都是比较常见的,也经常会使用到。我们也在elua代码包中内置了一些纯软算法,具体见下图。
上面图片中的命名有的人可能不知道这些库有什么作用,这里做一下简要说明。
代码包 | 功能 |
---|---|
crypto | 加密/摘要功能(sha1、sha2、md5、base64、xxtea、aes) |
iconv | 字体编码转化(gb2312、ucs2、utf8、) |
json | 把JSON内容或JSON文件进行格式化解析 |
lpng | 图片解码 |
lzma | 压缩文件接口 |
pbc | 基于双线性对的密码学库 |
qr_encode | 二维码生成 |
zlib | 通用的压缩库 |
zziplib | 轻量级的用来从ZIP文件抽读取文件的C语言包 |
还是和上节一样,库太多了,这些库里面又有一大堆文件。本来准备选个高大上的库讲讲,就是那个啥----基于双线性对的密码学库。这时候没想到json这么积极,举手要求上台,那我就勉为其难的答应她好了。接下来我们讲讲json,举一反三都一样哈。
2.4.1、json注册
和硬件驱动一样,即使json是纯软运算库也没有什么特殊的地方,该有的东西都得有。
如果想json能在lua脚本中被调用,首先那就必须得在auxmods.h
中增加声明json模块的模块名和注册函数。
#ifndef AM_JSON_NOT_SUPPORT
#define AUXLIB_JSON "json"
LUALIB_API int ( luaopen_cjson)( lua_State *L );
#endif
声明之后需要在platform_conf.h
文件中完成将模块名和初始化函数注册到lua内核中。
_ROM( AUXLIB_JSON, luaopen_cjson, json_map )
紧接着就在模块初始化函数函数内进行模块函数注册。这一段json库的函数注册代码就要比adc库的函数注册代码要复杂得多。
/* Return cjson module table */
static int lua_cjson_new(lua_State *l)
{
luaL_Reg reg[] = {
{ "encode", json_encode },
{ "decode", json_decode },
{ "encode_sparse_array", json_cfg_encode_sparse_array },
{ "encode_max_depth", json_cfg_encode_max_depth },
{ "decode_max_depth", json_cfg_decode_max_depth },
{ "encode_number_precision", json_cfg_encode_number_precision },
{ "encode_keep_buffer", json_cfg_encode_keep_buffer },
{ "encode_invalid_numbers", json_cfg_encode_invalid_numbers },
{ "decode_invalid_numbers", json_cfg_decode_invalid_numbers },
{ "new", lua_cjson_new },
{ NULL, NULL }
};
/* Initialise number conversions */
fpconv_init();
/* cjson module table */
lua_newtable(l);
/* Register functions with config data as upvalue */
json_create_config(l);
luaL_setfuncs(l, reg, 1);
/* Set cjson.null */
lua_pushlightuserdata(l, NULL);
lua_setfield(l, -2, "null");
/* Set module name / version fields */
lua_pushliteral(l, CJSON_MODNAME);
lua_setfield(l, -2, "_NAME");
lua_pushliteral(l, CJSON_VERSION);
lua_setfield(l, -2, "_VERSION");
return 1;
}
int luaopen_cjson(lua_State *l)
{
lua_cjson_new(l);
#ifdef ENABLE_CJSON_GLOBAL
/* Register a global "cjson" table. */
lua_pushvalue(l, -1);
lua_setglobal(l, CJSON_MODNAME);
#endif
/* Return cjson table */
return 1;
}
2.4.2、json调用函数的实现
纯软模块和硬件驱动不同的地方现在开始体现出来了。像json这一类纯软模块不依赖外部环境,实现用的都是一些标准库。基本上就是拿来就能用,都不需要改的。如果json模块只是给elua用,不考虑提供给外界使用的话。那我们就可以直接在上述lua调用的实现中直接去调用json库中的函数。而无需去单独在抽象一层。
看这个adc模块中的adc_open函数实现,去掉一些必须得写的,实际上和adc有关的就一行。这一行platform开头的代码就是我们下一章节要讲的平台适配代码。它可以看作是elua开源项目的一个特殊的抽象层,负责和外界的环境进行交互,这里不做细讲,了解即可。
// adc.open(id)
static int adc_open(lua_State *L) {
int id = luaL_checkinteger(L, 1);
int ret;
MOD_CHECK_ID(adc, id);
ret = platform_adc_open(id,0);
lua_pushinteger(L, ret);
return 1;
}
再来看看json模块中的json_decode函数的实现,这就不一样了是吧,这么一大坨看着都晕。这还是我挑选的一个比较简单的,其他的那就更长了。
static int json_decode(lua_State *l)
{
json_parse_t json;
json_token_t token;
size_t json_len;
luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument");
json.cfg = json_fetch_config(l);
json.data = luaL_checklstring(l, 1, &json_len);
json.current_depth = 0;
json.ptr = json.data;
/* Detect Unicode other than UTF-8 (see RFC 4627, Sec 3)
*
* CJSON can support any simple data type, hence only the first
* character is guaranteed to be ASCII (at worst: '"'). This is
* still enough to detect whether the wrong encoding is in use. */
if (json_len >= 2 && (!json.data[0] || !json.data[1]))
luaL_error(l, "JSON parser does not support UTF-16 or UTF-32");
/* Ensure the temporary buffer can hold the entire string.
* This means we no longer need to do length checks since the decoded
* string must be smaller than the entire json string */
json.tmp = strbuf_new(json_len);
json_next_token(&json, &token);
json_process_value(l, &json, &token);
/* Ensure there is no more input left */
json_next_token(&json, &token);
if (token.type != T_END)
json_throw_parse_error(l, &json, "the end", &token);
strbuf_free(json.tmp);
return 1;
}
给大家20秒扫一眼,看看上面的代码有没有platform
开头的函数。
哎,好像没有是吧!这就说明这个json模块是给elua开源项目特供的,不需要给外界使用。也不需要把它拎到项目外面,再另外做一个抽象层与elua对接。