Lua内置库的实现(一)_math模块(一)_从math模块看Lua的模块注册机制
2017-04-05 20:38
447 查看
内置库的实现_从math模块看Lua的模块注册机制
Lua5.2自带了几个库,实现了一般应用最基本的需求。这些库的实现仅仅使用了Lua官方手册中提到的API,对Lua核心部分的代码几乎没有依赖,所以最易于阅读。阅读这些库的实现,也可以加深对Lua API的印象,方便我们自己扩展Lua。
注意:在看这个之前要先了解Lua和C之间的交换数据的机制,因为Lua和C之间交互有2个问题:1.动态和静态类型系统的不匹配,2.自动和手动内存管理的不一致。(Lua
与C调用点击连接)
数学库是最简单的一个。它导入了若干数学函数,和两个常量pi与huge。下面代码是如何把一组API以及常量导入Lua的。
API 有一系列压栈的函数,它将每种可以用 C 来描述的Lua 类型压栈:
空值(nil) 用 lua_pushnil
数值型(double)用 lua_pushnumber
布尔型(在 C 中用整数表示)用 lua_pushboolean
任意的字符串(char*类型,允许包含'\0'字符)用 lua_pushlstring
C语言风格(以'\0'结束)的字符串(const char*)用 lua_pushstring
luaL_newlib是定义在lauxlib.h里的一个宏,在源代码3中可以看到,它仅仅是创建了一个table,然后把数组里的函数放进去而已。这个API在Lua的公开手册里有明确定义。
Lua5.2 简化了C扩展模块的定义方式,不再要求模块创建全局表。对于C模块,以luaopen为前缀导出API,通常是返回一张存有模块内涵数的表。这可以精简设计,Lua中require 的行为仅仅只是用来加载一个预定义的模块,并阻止重复加载而已;而不用关心载入的模块内的函数放在哪里。
luaL_setfuncs在源代码4里列出了实现,它把数组l中的所有函数注册入栈顶的table,并给所有函数绑上nup个upvalue。
/*源代码4*/
LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup){
luaL_checkversion(L);
luaL_checkstack(L, nup, "too_many_upvalue");
for(; l->name != NULL; i++){/* fill the table with given functions*/
int i;
for(i = 0; i < nup; i++)/*copy upvalues to the top*/
lua_pushvalue(L, -nup);
lua_pushclosure(L, l->func, nup);/*closure with those upvalues*/
lua_setfield(L, -(nup + 2), l->name);
}
lua_pop(L, nup);/*remove upvalues*/
}
Lua5.2自带了几个库,实现了一般应用最基本的需求。这些库的实现仅仅使用了Lua官方手册中提到的API,对Lua核心部分的代码几乎没有依赖,所以最易于阅读。阅读这些库的实现,也可以加深对Lua API的印象,方便我们自己扩展Lua。
注意:在看这个之前要先了解Lua和C之间的交换数据的机制,因为Lua和C之间交互有2个问题:1.动态和静态类型系统的不匹配,2.自动和手动内存管理的不一致。(Lua
与C调用点击连接)
数学库是最简单的一个。它导入了若干数学函数,和两个常量pi与huge。下面代码是如何把一组API以及常量导入Lua的。
/*源代码1*/ static const luaL_Reg mathlib [] = { {"abs", math_abs}, {"acos", math_acos}, {"asin", math_asin}, {"atan2", math_atan2}, {"atan", math_atan}, {"ceil", math_ceil}, {"cosh", math_cosh}, {"cos", math_cos}, {"deg", math_deg}, {"exp", math_exp}, {"floor", math_floor}, }没有列完这段代码,后面雷同。Lua使用一个结构luaL_Reg数组来描述需要注入的函数和名字。结构体前缀是luaL而不是lua,是因为这并非Lua的核心API部分。利用luaL_newlib可以把这组函数注入一个table。代码如下:
/*源代码2*/ LUAMOD_API int luaopen_math (lua_State *L){ luaL_newlib(L, mathlib); lua_pushnumber(L, PI); lua_setfield(L, -2, "pi"); lua_pushnumber(L, HUGE_VAL); lua_setfield(L, -2, "huge"); return 1; }
API 有一系列压栈的函数,它将每种可以用 C 来描述的Lua 类型压栈:
空值(nil) 用 lua_pushnil
数值型(double)用 lua_pushnumber
布尔型(在 C 中用整数表示)用 lua_pushboolean
任意的字符串(char*类型,允许包含'\0'字符)用 lua_pushlstring
C语言风格(以'\0'结束)的字符串(const char*)用 lua_pushstring
luaL_newlib是定义在lauxlib.h里的一个宏,在源代码3中可以看到,它仅仅是创建了一个table,然后把数组里的函数放进去而已。这个API在Lua的公开手册里有明确定义。
/*源代码3*/ #define luaL_newlibtable(L, l) lua_createtble(L, 0, sizeof(l)/sizeof((l)[0]) - 1) #define luaL_newlib(L, l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))注入这些函数使用的是Lua 5.2新加的API luaL_setfuncs, 引入这个API是因为Lua5.2 取消了环境(点击环境介绍)。那么,为了让C函数可以有附加一些额外的信息,就需要利用upvalue(给函数绑上upvalue取代之前给C函数使用的环境表,是Lua作者推荐的做法。不过要留意:lua5.2引入轻量C函数的概念,没有upvalue的C函数将是一个和lightuserdata一样轻量级的值。不给不必要的C函数绑上upvalue可以使Lua程序得到一定的优化。为了把需求不同的C函数区别对待,可以通过多次调用luaL_setfuncs来实现)。
Lua5.2 简化了C扩展模块的定义方式,不再要求模块创建全局表。对于C模块,以luaopen为前缀导出API,通常是返回一张存有模块内涵数的表。这可以精简设计,Lua中require 的行为仅仅只是用来加载一个预定义的模块,并阻止重复加载而已;而不用关心载入的模块内的函数放在哪里。
luaL_setfuncs在源代码4里列出了实现,它把数组l中的所有函数注册入栈顶的table,并给所有函数绑上nup个upvalue。
/*源代码4*/
LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup){
luaL_checkversion(L);
luaL_checkstack(L, nup, "too_many_upvalue");
for(; l->name != NULL; i++){/* fill the table with given functions*/
int i;
for(i = 0; i < nup; i++)/*copy upvalues to the top*/
lua_pushvalue(L, -nup);
lua_pushclosure(L, l->func, nup);/*closure with those upvalues*/
lua_setfield(L, -(nup + 2), l->name);
}
lua_pop(L, nup);/*remove upvalues*/
}
相关文章推荐
- Lua内置库的实现(一)_math模块(二)_math模块API实现
- 在VC中怎样实现软件的注册机制
- 软件防拷贝注册机制的程序实现
- [EntLib]微软企业库5.0 学习之路——第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——上篇
- eShop电子商城的SSH实现的用户模块(1)登录和注册Bean(Version 1.0)
- eShop电子商城的SSH实现的用户模块(1)登录和注册配置文件和页面关键代码(V...
- Lua中实现类似C#的事件机制
- 利用bigpipe机制实现页面模块的异步渲染 chunked技术
- PHP用户登录注册模块实现
- Lua中实现类似C#的事件机制
- 转:PAMIE- Python实现IE自动化的模块(附 网易注册代码)
- tomcat内置的访问控制机制来实现权限控制
- 在VC中怎样实现软件的注册机制
- 通过Cache机制实现通用的配置管理模块
- 通过类静态成员变量 可以实现自动注册机制
- Lua中实现类似C#的事件机制
- 通过Cache机制实现通用的配置管理模块(含源码)
- Struts2入门--Struts2和Hibernate实现的注册登录模块
- 微软企业库5.0 学习之路——第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——上篇
- 利用bigpipe机制实现页面模块的异步渲染