• 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。敲出来去看看,会有不同的收获,感觉有东西,这种感觉个人觉得是学习的时候最好的。

  • 相关阅读:
    舍不得花钱的心理分析
    DLL编程的导入导出,__declspec(dllimport),__declspec(dllexport)
    浅谈C/C++内存泄漏及其检测工具
    C++多线程编程简单实例
    linux镜像源设置
    Linux基础教程 linux无密码ssh登录设置
    兄弟连教育分享:用CSS实现鼠标悬停提示的方法
    PHP基础教程 PHP的页面缓冲处理机制
    Linux基础教程 linux下cat 命令使用详解
    PHP基础教程 php 网络上关于设计模式一些总结
  • 原文地址:https://www.cnblogs.com/pk-run/p/3622947.html
Copyright © 2020-2023  润新知