zoukankan      html  css  js  c++  java
  • 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(1000)
    print(a:size())
    a:set(10, 3.4)
    print(a:get(10))

    输出结果:

    1000
    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, 1);
    
            /* create a userdatum */
            DIR **d = (DIR **)lua_newuserdata(L, sizeof(DIR *));
    
            /* set its metatable */
            luaL_getmetatable(L, "LuaBook.dir");
            lua_setmetatable(L, -2);
    
            /* 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, 1);
            return 1;
    }
    
    static int dir_iter(lua_State *L){
            DIR *d = *(DIR **)lua_touserdata(L, lua_upvalueindex(1));
            struct dirent *entry;
            if (( entry = readdir(d)) != NULL){
                    lua_pushstring(L, entry->d_name);
                    return 1;
            }
            else return 0;  /* no more valuse to return */
    }
    
    static int dir_gc(lua_State *L){
            DIR *d = *(DIR **)lua_touserdata(L, 1);
            if (d) closedir(d);
            return 0;
    }
    
    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, -3);
    
            /* register the 'dir' function */
            lua_pushcfunction(L, l_dir);
            lua_setglobal(L, "dir");
    
            return 0;
    }

     使用和结果

    > 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.2
    > 

    4. 总结

    (1)lua调用c函数,返回的就是栈上的内容。例如:你在c函数压入一个整数,那么返回的第一个就是这个整数。

    (2)linux命令:gcc mylib.c -fPIC -shared -o libmylib.so

    (3)看书学习的时候,当觉得朦胧不清晰的时候,要放慢速度,最好的就是Do it。敲出来去看看,会有不同的收获,感觉有东西,这种感觉个人觉得是学习的时候最好的。

  • 相关阅读:
    【Nginx】ngx_event_core_module模块
    ELMAH--Using HTTP Modules and Handlers to Create Pluggable ASP.NET Components 77 out of 90 rated th
    nyist oj 214 单调递增子序列(二) (动态规划经典)
    java 入门书籍(java7)
    ARCGIS将WGS84坐标投影到高斯平面
    【linux】linux下对java程序生成dump文件,并使用IBM Heap Analyzer进行分析,查找定位内存泄漏的问题代码
    【springboot】【socket】spring boot整合socket,实现服务器端两种消息推送
    【linux】linux修改open file 大小
    【docker】docker限制日志文件大小的方法+查看日志文件的方法
    【docker】docker部署spring boot服务,但是docker logs查看容器输出控制台日志,没有日志打印,日志未打印,docker logs不打印容器日志
  • 原文地址:https://www.cnblogs.com/pk-run/p/3622947.html
Copyright © 2011-2022 走看看