lua学习笔记之userdata
这一段时间看了《programming in lua》中的第28章,看一遍并不是很难,但是只是朦胧的感觉,雾里看花,水中望月。最终还是决定敲出来自己看看,练练手,结果受益不少,也遇到了一些问题,记在这里。自己做一个总结,也希望能帮助和我一样lua的初学者。
1. 书上并没有写清楚对于CAPI的制作和使用内容。主要包括dll的生成,以及使用
(1)dll生成。
直接用vs新建一个dll工程,要记得包含依赖路径。如下图所示,包含你的lua安装路径。
工程名要和库的最终名字一致(默认是一致的)。luaopen_array(lua_State *L)也最好一致。这一块,我没有去研究和测试,就是按照书上来做的,没有碰到什么大的问题,主要和使用方式有一些关系。
(2)使用
两种方法:
第一种:require "myarray"。这就需要dll的名字是myarray.dll。而且luaopen_xxx(lua_State *L)也是luaopen_array的形式;
第二种:package.loadlib("array", "luaopen_array")()。这种的话,第一个参数array是你在写c代码时候注册的table名字,后面一个函数名。这种使用方式我个人觉得是需要dll名字以及注册的table名必须是"array",但是luaoepn_xxx就不需要了。
(3)linux
直接使用命令:gcc mylib.c -fPIC -shared -o libmylib.so即可生成可以使用的动态库。
使用和window下面的使用一样,自己用的是第二种方法:package.loadlib("./libmydir.so", "luaopen_mydir")()
2. 一些问题
(1)直接使用loadlib不行
mylib = loadlib("mylib", "luaopen_mylib")
解决:加上库,package.loadlib
(2)使用package.loadlib的时候报错
描述:lua: capi_study.lua:57: attempt to call a nil value
原因:工程名字生成的库名字和使用的时候不一致出错
(3)luaL_openlib和luaL_register
*接口变化,我用的lua版本是5.1.所以用luaL_register接口,而不是书上仍然使用的luaL_openlib接口。官网的document的5.1《reference manual》中有提到,可以自己去看。
*linux却仍然还是需要使用前者。(linux下面的版本是5.2.0了,不明白是什么原因)
(4)面向对象例子报错
描述:lua: capi_study.lua:102: calling 'size' on bad self (luaBook.array expected, got userdata)
原因:void *ud = luaL_checkudata(L, 1, "LuaBook.array");中的"LuaBook.array"写成了"luaBook.array"
结果:Success!
package.loadlib("array", "luaopen_array")()
a = array.new()
print(a:size())
a:set(, 3.4)
print(a:get())
输出结果:
3.4
(5)linux编译报错
描述:“错误:数组元素的类型不完全”
原因:
*用gcc4编译时出现数组元素的类型不完全错误,这是因为gcc4不允许类型在声明前使用。【引用:http://blog.csdn.net/horsefaced/article/details/1678965】
*luaL_Reg写成了luaL_reg
解决:
(6)linux编译警告
描述:警告:传递参数 2 (属于 ‘lua_getmetatable’)时将指针赋给整数,未作类型转换
原因:低级错误luaL_getmetatable写成了lua_getmetatable,希望碰到这个问题的能够不用再纠结了
3.一个例子
附上dir例子的源码,linux编译通过。
#include <math.h>
#include <dirent.h>
#include <errno.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h" /* forward declaration */
static int dir_iter(lua_State *L); static int l_dir(lua_State *L){
const char *path = luaL_checkstring(L, ); /* create a userdatum */
DIR **d = (DIR **)lua_newuserdata(L, sizeof(DIR *)); /* set its metatable */
luaL_getmetatable(L, "LuaBook.dir");
lua_setmetatable(L, -); /* try to pen then given dirctory */
*d = opendir(path);
if (*d == NULL)
luaL_error(L, "cannot open %s: %s", path, strerror(errno)); /* creates and returns the iterator function */
lua_pushcclosure(L, dir_iter, );
return ;
} static int dir_iter(lua_State *L){
DIR *d = *(DIR **)lua_touserdata(L, lua_upvalueindex());
struct dirent *entry;
if (( entry = readdir(d)) != NULL){
lua_pushstring(L, entry->d_name);
return ;
}
else return ; /* no more valuse to return */
} static int dir_gc(lua_State *L){
DIR *d = *(DIR **)lua_touserdata(L, );
if (d) closedir(d);
return ;
} int luaopen_mydir (lua_State *L){
luaL_newmetatable(L, "LuaBook.dir"); /* set its __Gc field */
lua_pushstring(L, "__gc");
lua_pushcfunction(L, dir_gc);
lua_settable(L, -); /* register the 'dir' function */
lua_pushcfunction(L, l_dir);
lua_setglobal(L, "dir"); return ;
}
使用和结果
> package.loadlib("./libmydir.so", "luaopen_mydir")()
> for fname in dir(".") do print(fname) end
.
..
libmylib.so
libdir.so
dir.c
.dir.c.swp
dir.so
mydir_none.c
mylib.c
libmydir.so
mydir.c
capi_study.lua
lua-5.1.
>
4. 总结
(1)lua调用c函数,返回的就是栈上的内容。例如:你在c函数压入一个整数,那么返回的第一个就是这个整数。
(2)linux命令:gcc mylib.c -fPIC -shared -o libmylib.so
(3)看书学习的时候,当觉得朦胧不清晰的时候,要放慢速度,最好的就是Do it。敲出来去看看,会有不同的收获,感觉有东西,这种感觉个人觉得是学习的时候最好的。
最新文章
- 代码的坏味道(20)——过度耦合的消息链(Message Chains)
- 在CentOS 6.7中安装NVIDIA GT730显卡驱动的手记
- easyUI datagraid的列排序
- 在OS X中使用Homebrew
- A sample of procedure in using
- PASCALmath库
- 1040. Longest Symmetric String (25)
- HDU 4035 Maze(树形概率DP)
- 用定时器T0查询方式P0口8位控制LED闪烁
- Matlab: 路径的操作
- phpcms实现全站搜索
- 从css 3d说到空间坐标轴
- Android Interpolator解析
- java中List<;Map<;String, Object>;>;关于null的判断
- SpringBoot之解决云服务器VPS在所处云端集群的内网不能解析域名的问题:java.net.UnknownHostException:abc.cn: Temporary failure in name resolution
- Golang的方法传递值应该注意的地方
- vs2008 使用百度编辑器
- 23种设计模式之原型模式(Prototype)
- 质因子分解(Pollard_Rho法)
- js添加select中option
热门文章
- AngularJs学习笔记--Managing Service Dependencies
- poj 3748 位操作
- [转载+补充][PY3]——环境配置(2)——windows下安装pycharm并连接Linux的python环境
- MySQL触发器基本介绍
- SSRS 通过Customer Code访问Dataset
- PHP学习10——Cookie和Session技术
- WPF简单的数据库查询
- spring mvc如何优雅的使用fastjson
- Spring学习笔记:声明式事务管理增删改查业务
- JavaScript事件流--事件冒泡、目标与事件捕获