zoukankan      html  css  js  c++  java
  • Userdata

    我们首先关心的是如何在Lua中表示数组的值。Lua为这种情况提供专门提供一个基本的类型:userdata。一个userdatum提供了一个在Lua中没有预定义操作的raw内存区域。

    Lua API提供了下面的函数用来创建一个userdatum:

    void *lua_newuserdata (lua_State *L, size_t size);

    lua_newuserdata函数按照指定的大小分配一块内存,将对应的userdatum放到栈内,并返回内存块的地址。如果出于某些原因你需要通过其他的方法分配内存的话,很容易创建一个指针大小的userdatum,然后将指向实际内存块的指针保存到userdatum里。我们将在下一章看到这种技术的例子。

    使用lua_newuserdata函数,创建新数组的函数实现如下:

    static int newarray (lua_State *L) {

        int n = luaL_checkint(L, 1);

        size_t nbytes = sizeof(NumArray) + (n - 1)*sizeof(double);

        NumArray *a = (NumArray *)lua_newuserdata(L, nbytes);

        a->size = n;

        return 1;  /* new userdatum is already on the stack */

    }

    (函数luaL_checkint是用来检查整数的luaL_checknumber的变体)一旦newarray在Lua中被注册之后,你就可以使用类似a = array.new(1000)的语句创建一个新的数组了。

    为了存储元素,我们使用类似array.set(array, index, value)调用,后面我们将看到如何使用metatables来支持常规的写法array[index] = value。对于这两种写法,下面的函数是一样的,数组下标从1开始:

    static int setarray (lua_State *L) {

        NumArray *a = (NumArray *)lua_touserdata(L, 1);

        int index = luaL_checkint(L, 2);

        double value = luaL_checknumber(L, 3);

     

        luaL_argcheck(L, a != NULL, 1, "`array' expected");

     

        luaL_argcheck(L, 1 <= index && index <= a->size, 2,

                  "index out of range");

     

        a->values[index-1] = value;

        return 0;

    }

    luaL_argcheck函数检查给定的条件,如果有必要的话抛出错误。因此,如果我们使用错误的参数调用setarray,我们将得到一个错误信息:

    array.set(a, 11, 0)

    --> stdin:1: bad argument #1 to 'set' ('array' expected)

    下面的函数获取一个数组元素:

    static int getarray (lua_State *L) {

        NumArray *a = (NumArray *)lua_touserdata(L, 1);

        int index = luaL_checkint(L, 2);

     

        luaL_argcheck(L, a != NULL, 1, "'array' expected");

     

        luaL_argcheck(L, 1 <= index && index <= a->size, 2,

                             "index out of range");

     

        lua_pushnumber(L, a->values[index-1]);

        return 1;

    }

    我们定义另一个函数来获取数组的大小:

    static int getsize (lua_State *L) {

        NumArray *a = (NumArray *)lua_touserdata(L, 1);

        luaL_argcheck(L, a != NULL, 1, "`array' expected");

        lua_pushnumber(L, a->size);

        return 1;

    }

    最后,我们需要一些额外的代码来初始化我们的库:

    static const struct luaL_reg arraylib [] = {

        {"new", newarray},

        {"set", setarray},

        {"get", getarray},

        {"size", getsize},

        {NULL, NULL}

    };

     

    int luaopen_array (lua_State *L) {

        luaL_openlib(L, "array", arraylib, 0);

        return 1;

    }

    这儿我们再次使用了辅助库的luaL_openlib函数,他根据给定的名字创建一个表,并使用arraylib数组中的name-function对填充这个表。

    打开上面定义的库之后,我们就可以在Lua中使用我们新定义的类型了:

    a = array.new(1000)

    print(a)                 --> userdata: 0x8064d48

    print(array.size(a))     --> 1000

    for i=1,1000 do

        array.set(a, i, 1/i)

    end

    print(array.get(a, 10))  --> 0.1

    在一个Pentium/Linux环境中运行这个程序,一个有100K元素的数组大概占用800KB的内存,同样的条件由Lua 表实现的数组需要1.5MB的内存。

  • 相关阅读:
    安卓手机数据库和自动寻路插件
    快速找图找字插件
    大龙快速找图,找字插件
    C星【多线程】寻路插件最新更新2019-8-17
    大龙数据库插件,通用所有数据库,支持任何语言调用
    开源一个自己造的轮子:基于图的任务流引擎GraphScheduleEngine
    Java中使用CountDownLatch进行多线程同步
    TensorFlow实验环境搭建
    Java中Semaphore(信号量)的使用
    CNN在中文文本分类的应用
  • 原文地址:https://www.cnblogs.com/xiaoleiel/p/8295736.html
Copyright © 2011-2022 走看看