精华内容
下载资源
问答
  • 同样的数据,xml格式和json格式两种(目前主要是lua开发,测试c++的读取主要是作为性能参考)10MB的xml文件,一行45个属性,有1W多行测试行为都为创建相关对象,并存储所有行数据内存中。注:以下数据仅作参考,与...

    同样的数据,xml格式和json格式两种(目前主要是lua开发,测试c++的读取主要是作为性能参考)

    10MB的xml文件,一行45个属性,有1W多行

    测试行为都为创建相关对象,并存储所有行数据到内存中。

    注:以下数据仅作参考,与机器等环境有关。
    c++ pugixml库:180ms
    ps.c++的josn库太慢,就没测了(之前测试过,不如lua的cjson库)

    lua 的pugixml包装:390ms
    lua 的 cjson库:186ms

    看来数据导为json格式更好啊,加载快。

    转载于:https://www.cnblogs.com/lcinx/p/10570854.html

    展开全文
  •   在Lua和C语言之间进行数据交换时,由于两种语言之间有着较大的差异,比如Lua是动态类型,C语言是静态类型,Lua是自动内存管理,而C语言则是手动内存管理。为了解决这些问题,Lua的设计者使用了虚拟栈作为二者...

    一、lua c api 是什么

      C API是一组能使C/C++代码与Lua交互的函数。其中包括读写Lua全局变量、调用Lua函数、运行一段Lua代码,以及注册C函数以供Lua代码调用等。

    二、常用api

      在Lua和C语言之间进行数据交换时,由于两种语言之间有着较大的差异,比如Lua是动态类型,C语言是静态类型,Lua是自动内存管理,而C语言则是手动内存管理。为了解决这些问题,Lua的设计者使用了虚拟栈作为二者之间数据交互的介质。在C/C++程序中,如果要获取Lua的值,只需调用Lua的C API函数,Lua就会将指定的值压入栈中。要将一个值传给Lua时,需要先将该值压入栈,然后调用Lua的C API,Lua就会获取该值并将其从栈中弹出。为了可以将不同类型的值压入栈,以及从栈中取出不同类型的值,Lua为每种类型均设定了一个特定函数。

    1、压入元素
    Lua针对每种C类型,都有一个C API函数与之对应,如:

    void lua_pushnil(lua_State* L);  --nil值
    void lua_pushboolean(lua_State* L, int b); --布尔值
    void lua_pushnumber(lua_State* L, lua_Number n); --浮点数
    void lua_pushinteger(lua_State* L, lua_Integer n);  --整型
    void lua_pushlstring(lua_State* L, const char* s, size_t len); --指定长度的内存数据
    void lua_pushstring(lua_State* L, const char* s);  --以零结尾的字符串,其长度可由strlen得出。
    

      对于字符串数据,Lua不会持有他们的指针,而是调用在API时生成一个内部副本,因此,即使在这些函数返回后立刻释放或修改这些字符串指针,也不会有任何问题。
      在向栈中压入数据时,可以通过调用下面的函数判断是否有足够的栈空间可用,一般而言,Lua会预留20个槽位,对于普通应用来说已经足够了,除非是遇到有很多参数的函数。
      int lua_checkstack(lua_State* L, int extra) --期望得到extra数量的空闲槽位,如果不能扩展并获得,返回false。

    2、查询元素
      API使用“索引”来引用栈中的元素,第一个压入栈的为1,第二个为2,依此类推。我们也可以使用负数作为索引值,其中-1表示为栈顶元素,-2为栈顶下面的元素,同样依此类推。
      Lua提供了一组特定的函数用于检查返回元素的类型,如:

    int lua_isboolean (lua_State *L, int index);
    int lua_iscfunction (lua_State *L, int index);
    int lua_isfunction (lua_State *L, int index);
    int lua_isnil (lua_State *L, int index);
    int lua_islightuserdata (lua_State *L, int index);
    int lua_isnumber (lua_State *L, int index);
    int lua_isstring (lua_State *L, int index);
    int lua_istable (lua_State *L, int index);
    int lua_isuserdata (lua_State *L, int index);
    

      以上函数,成功返回1,否则返回0。需要特别指出的是,对于lua_isnumber而言,不会检查值是否为数字类型,而是检查值是否能转换为数字类型。
      Lua还提供了一个函数lua_type,用于获取元素的类型,函数原型如下:

     int lua_type (lua_State *L, int index);
    

      该函数的返回值为一组常量值,分别是:LUA_TNIL、LUA_TNUMBER、LUA_TBOOLEAN、LUA_TSTRING、LUA_TTABLE、LUA_TFUNCTION、LUA_TUSERDATA、LUA_TTHREAD和LUA_TLIGHTUSERDATA。这些常量通常用于switch语句中。

    3、转换函数

    Lua还提供了一组转换函数,如:

    int lua_toboolean (lua_State *L, int index);
    lua_CFunction lua_tocfunction (lua_State *L, int index);
    lua_Integer lua_tointeger (lua_State *L, int index);   
    const char *lua_tolstring (lua_State *L, int index, size_t *len);
    lua_Number lua_tonumber (lua_State *L, int index);
    const void *lua_topointer (lua_State *L, int index);
    const char *lua_tostring (lua_State *L, int index);
    void *lua_touserdata (lua_State *L, int index);
    //string类型返回字符串长度,table类型返回操作符'#'等同的结果,userdata类型返回分配的内存块长度。
    size_t lua_objlen (lua_State *L, int index); 
    

      对于上述函数,如果调用失败,lua_toboolean、lua_tonumber、lua_tointeger和lua_objlen均返回0,而其他函数则返回NULL。在很多时候0不是一个很有效的用于判断错误的值,但是ANSI C没有提供其他可以表示错误的值。因此对于这些函数,在有些情况下需要先使用lua_is*系列函数判断是否类型正确,而对于剩下的函数,则可以直接通过判断返回值是否为NULL即可。
      对于lua_tolstring函数返回的指向内部字符串的指针,在该索引指向的元素被弹出之后,将无法保证仍然有效。该函数返回的字符串末尾均会有一个尾部0。

    4、操作虚拟栈的普通函数

    int lua_gettop(lua_State* L); //返回栈中元素的个数。
    void lua_settop(lua_State* L, int index); //将栈顶设置为指定的索引值。
    void lua_pushvalue(lua_State* L, int index); //将指定索引的元素副本压入栈。
    void lua_remove(lua_State* L, int index); //删除指定索引上的元素,其上面的元素自动下移。
    void lua_insert(lua_State* L, int index); //将栈顶元素插入到该索引值指向的位置。
    void lua_replace(lua_State* L, int index); //弹出栈顶元素,并将该值设置到指定索引上。
    

    Lua还提供了一个宏用于弹出指定数量的元素:

    #define lua_pop(L,n)  lua_settop(L, -(n) - 1)    
    

    5、解析lua配置文件

    lua_State* luaL_newstate(); // 创建lua_State
    void luaL_openlibs(lua_State* L); // 打开lua标准库
    int luaL_loadfile (lua_State *L, const char *filename) // 载入配置文件
    lua_pcall(lua_State *L,int nargs,int nresults,int errfunc) //运行lua配置文件
    #define luaL_dofile(L,fn) (LuaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))
    void lua_close(lua_State* L); // 
    //获取索引为index的table中指定key的value,key要预先压入栈,函数调用结束key会被弹出栈,并把value压入栈中
    void lua_gettable (lua_State *L, int index); 
    void lua_rawget (lua_State *L, int index);  // lua_gettable类似,但不涉及元表
    //key不需要压入栈,直接当作第三个参数传入,得到的value同样会被压入栈中
    void lua_getfield (lua_State *L, int index, const char *k); 
    void lua_rawgeti (lua_State *L, int index, int n); // 除了不涉及元表,并且key只能为整数
    

    lua table操作实例一般步骤:

    lua_gettable
    lua_getglobal(L, "mytable") <== push mytable
    lua_pushnumber(L, 1)        <== push key 1
    lua_gettable(L, -2)         <== pop key 1, push mytable[1]
    
    lua_settable
    lua_getglobal(L, "mytable") <== push mytable
    lua_pushnumber(L, 1)        <== push key 1
    lua_pushstring(L, "abc")    <== push value "abc"
    lua_settable(L, -3)         <== mytable[1] = "abc", pop key & value
    
    lua_rawget:
    用法同lua_gettable,但更快(因为当key不存在时不用访问元方法 __index)
    
    lua_rawset :
    用法同lua_settable,但更快(因为当key不存在时不用访问元方法 __newindex)
    
    lua_rawgeti必须为数值键
    lua_getglobal(L, "mytable") <== push mytable
    lua_rawgeti(L, -1, 1)       <== push mytable[1],作用同下面两行调用
    --lua_pushnumber(L, 1)      <== push key 1
    --lua_rawget(L,-2)          <== pop key 1, push mytable[1]
    
    lua_rawseti必须为数值键
    lua_getglobal(L, "mytable") <== push mytable
    lua_pushstring(L, "abc")    <== push value "abc"
    lua_rawseti(L, -2, 1)       <== mytable[1] = "abc", pop value "abc"
    
    lua_getfield必须为字符串键
    lua_getglobal(L, "mytable") <== push mytable
    lua_getfield(L, -1, "x")    <== push mytable["x"],作用同下面两行调用
    --lua_pushstring(L, "x")    <== push key "x"
    --lua_gettable(L,-2)        <== pop key "x", push mytable["x"]
    
    lua_setfield必须为字符串键
    lua_getglobal(L, "mytable") <== push mytable
    lua_pushstring(L, "abc")    <== push value "abc"
    lua_setfield(L, -2, "x")    <== mytable["x"] = "abc", pop value "abc" 
    

    5、C API中的错误处理:

    1). C程序调用Lua代码的错误处理:

      通常情况下,应用程序代码是以“无保护”模式运行的。因此,当Lua发现“内存不足”这类错误时,只能通过调用“紧急”函数来通知C语言程序,之后在结束应用程序。用户可通过lua_atpanic来设置自己的“紧急”函数。如果希望应用程序代码在发生Lua错误时不会退出,可通过调用lua_pcall函数以保护模式运行Lua代码。这样再发生内存错误时,lua_pcall会返回一个错误代码,并将解释器重置为一致的状态。如果要保护与Lua的C代码,可以使用lua_cpall函数,它将接受一个C函数作为参数,然后调用这个C函数。

    2). Lua调用C程序:

      通常而言,当一个被Lua调用的C函数检测到错误时,它就应该调用lua_error,该函数会清理Lua中所有需要清理的资源,然后跳转回发起执行的那个lua_pcall,并附上一条错误信息。


    三、写代码,包装一下api

    仅仅是读取lua配置文件
    lua_c.h

    #ifndef __LUAC_H
    #define __LUAC_H
    
    
    int lua_get_integer(lua_State *L, ...);
    double lua_get_double(lua_State *L, ...);
    int lua_get_bool(lua_State *L, ...);
    const char* lua_get_string(lua_State *L, ...);
    
    
    // 用户调用
    lua_State* lua_c_loadfile(const char *filename);
    void lua_c_close(lua_State *L);
    #define lua_c_get_integer(L, ...) lua_get_integer(L, __VA_ARGS__, NULL)
    #define lua_c_get_double(L, ...) lua_get_double(L, __VA_ARGS__, NULL)
    #define lua_c_get_bool(L, ...) lua_get_bool(L, __VA_ARGS__, NULL)
    #define lua_c_get_string(L, ...) lua_get_string(L, __VA_ARGS__, NULL)
    
    #endif
    

    lua_c.c

    /* Copyright (C) 2017-2100 All right reserved
     * For free
     *
     * @file luac_r.c
     * @brief
     * @author qigaohua, qigaohua168@163.com
     * @version 1.0.0
     * @date 2021-01-08
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #include <lua5.2/lua.h>
    #include <lua5.2/lualib.h>
    #include <lua5.2/lauxlib.h>
    
    #define B_RED(str)      "\033[1;31m" str "\033[0m"
    #define B_GREEN(str)    "\033[1;32m" str "\033[0m"
    #define B_YELLOW(str)   "\033[1;33m" str "\033[0m"
    
    // #define _DEBUG
    #if defined( _DEBUG )
    #define ASSERT(x, msg) { \
        if (x) { \
            fprintf(stderr, B_RED("ASSERT at %s:%d : %s\r\n"), __FILE__, __LINE__, msg); \
            exit(1); \
        } \
    }
    
    #define DEBUG(code_segment) { code_segment }
    #else
    #define ASSERT(x, msg)
    #define DEBUG(code_segment)
    #endif
    
    
    #define logerr(fmt, ...) {\
        fprintf(stderr, B_RED("%s:%d : "fmt"\r\n"), __FILE__, __LINE__, ##__VA_ARGS__); \
        exit(1); \
    }
    
    #define logwarn(fmt, ...) {\
        fprintf(stderr, B_YELLOW("%s:%d  "fmt"\r\n"), __FILE__, __LINE__, ##__VA_ARGS__); \
    }
    
    
    #define logdebug(fmt, ...) {\
        fprintf(stdout, B_GREEN("%s:%d : "fmt"\r\n"), __FILE__, __LINE__, ##__VA_ARGS__); \
    }
    
    
    
    /**
     * @brief luc_c_loadfile 载入和运行lua配置文件
     *
     * @param filename lua 文件名称
     *
     * @return L
     */
    lua_State* lua_c_loadfile(const char *filename)
    {
        lua_State *L = NULL;
    
        if (!filename) {
            logwarn("param `filename' is null !");
            return NULL;
        }
    
        /* 创建lua_State, 打开lua标准库 */
        L = luaL_newstate();
        if (!L)
            logerr("Call luaL_newstate() failed !");
    
        luaL_openlibs(L);
    
        /* 载入和运行lua配置文件 */
        // luaL_loadfile(L, filename);
        // lua_pcall(L, 0, LUA_MULTRET, 0);
    
        /* 或者直接调用lua_dofile来完成载入和运行 */
        luaL_dofile(L, filename);
    
        return L;
    }
    
    
    void lua_c_close(lua_State *L)
    {
        ASSERT(!L, "param `L' is null !!!");
    
        lua_close(L);
    }
    
    
    
    /**
     * @brief lua_c_getvalue 根据给的参数得到值,把值放到栈顶
     *
     * @param L
     * @param stack_top  放入最后栈顶值
     * @param ap    传入的参数
     *
     * @return  -1 失败 0 成功
     */
    static int lua_c_getvalue(lua_State *L, int *stack_top, va_list ap)
    {
        const char *value = NULL;
        char *tmp = NULL; // 为参数值
        *stack_top = 0;
    
        ASSERT(!L, "param `L' is null !!!");
    
        tmp = va_arg(ap, char *);
        if (!tmp) {
            logwarn("Invaild params !");
            return -1;
        }
    
        //index为0,表示把栈全清空
        lua_settop(L, 0);
    
        // 根配置入栈
        lua_getglobal(L, tmp);
        (*stack_top)--; // note
    
        // 不是table直接返回
        if (!lua_istable(L, *stack_top)) {
            DEBUG (
            logdebug("It isn't table, stack_top: %d", *stack_top);
            )
            return 0;
        }
    
        tmp = va_arg(ap, char *);
        if (!tmp) {
            logwarn("why ! you are not smart !!!");
            return -1;
        }
    
        /*
         * 判断是否是数字索引, 在本代码中设定索引值不得大于4096
         * note: 如果索引大于4096,会发生错误
         */
        if (*(unsigned long *)&tmp < 4096) {
            // 压入index值
            int index = *(unsigned long*)&tmp;
            lua_pushnumber(L, index);
        }
        else {
            // 压入key值
            lua_pushstring(L, tmp);
        }
        (*stack_top)--;
    
        while ((tmp = va_arg(ap, char *)) != NULL) {
            /* 表示上一个key对应的是table, 把table值会放在栈顶,同时上一个压入的元素名字被弹出 */
            lua_gettable(L, *stack_top);
            *stack_top = -1;
    
            lua_pushstring(L, tmp);
            (*stack_top)--;
    
        }
    
        /* 值会放在栈顶,同时刚才压入的元素名字被弹出 */
        lua_gettable(L, *stack_top);
        *stack_top = -1;
    
        return 0;
    }
    
    
    // 获取整数值
    int lua_get_integer(lua_State *L, ...)
    {
        int v;  // 需要获取的值,返回
        int stack_top = 0; // 栈顶值
        va_list ap;
    
        ASSERT(!L, "param `L' is null !!!");
    
        va_start(ap, L);
        if (0 != lua_c_getvalue(L, &stack_top, ap))
            return -1;
    
        if (!lua_isnumber(L, stack_top)) {
            logwarn("Error: item isn't integer %d!", stack_top);
            return -1;
        }
    
        v = lua_tointeger(L, stack_top);
    
        return v;
    }
    
    
    // 获取浮点数
    double lua_get_double(lua_State *L, ...)
    {
        double v;  // 需要获取的值,返回
        int stack_top = 0; // 栈顶值
        va_list ap;
    
        ASSERT(!L, "param `L' is null !!!");
    
        va_start(ap, L);
        if (0 != lua_c_getvalue(L, &stack_top, ap))
            return -1.0;
    
        if (!lua_isnumber(L, stack_top)) {
            logwarn("Error: item isn't integer %d!", stack_top);
            return -1.0;
        }
    
        v = lua_tonumber(L, stack_top);
    
        return v;
    }
    
    
    
    int lua_get_bool(lua_State *L, ...)
    {
        int v;  // 需要获取的值,返回
        int stack_top = 0; // 栈顶值
        va_list ap;
    
        ASSERT(!L, "param `L' is null !!!");
    
        va_start(ap, L);
        if (0 != lua_c_getvalue(L, &stack_top, ap))
            return -1;
    
        if (!lua_isboolean(L, stack_top)) {
            logwarn("Error: item isn't boolean %d!", stack_top);
            return -1;
        }
    
        v = lua_toboolean(L, stack_top);
    
        return v;
    }
    
    
    const char* lua_get_string(lua_State *L, ...)
    {
        const char *v;
        int stack_top = 0; // 栈顶值
        va_list ap;
    
        ASSERT(!L, "param `L' is null !!!");
    
        va_start(ap, L);
        if (0 != lua_c_getvalue(L, &stack_top, ap))
            return NULL;
    
        if (!lua_isstring(L, stack_top)) {
            logwarn("Error: item isn't string!");
            return NULL;
        }
        v = lua_tostring(L, stack_top);
    
        return v;
    }
    
    
    
    /**
     *  lua_next() 这个函数的工作过程是:
     *   1) 先从栈顶弹出一个 key
     *   2) 从栈指定位置的 table 里取下一对 key-value,先将 key 入栈再将 value 入栈
     *   3) 如果第 2 步成功则返回非 0 值,否则返回 0,并且不向栈中压入任何值
    
     *  第 2 步中从 table 里取出所谓“下一对 key-value”是相对于第 1 步中弹出的 key 的。
     *  table 里第一对 key-value 的前面没有数据,所以先用 lua_pushnil() 压入一个 nil
     *  充当初始 key。
    
     *  注意开始的时候先用 lua_gettop() 取了一下 table 在栈中的正索引(前面说过了,在
     *  进行这个 lua_next() 过程之前先将 table 入栈,所以栈大小就是 table 的正索引),
     *  后面的 lua_next() 过程中不断的有元素出入栈,所以使用正索引来定位 table 比较方便。
    
     *  到了 table 中已经没有 key-value 对时,lua_next() 先弹出最后一个 key,然后发现
     *  已经没有数据了会返回 0,while 循环结束。所以这个 lua_next() 过程结束以后
     *   table 就又位于栈顶了。
     */
    
    /**
     * @brief lua_c_parse_table 打印table内容
     *
     * @param L
     * @param table_name 要打印表名称,可以为null, 但要确保栈索引-1处是一个表
     *
     * @return -1 for failed, 0 for ok
     */
    int lua_c_parse_table(lua_State *L, const char *table_name)
    {
        int key_type = -1;
        int value_type = -1;
    
        if (!L) {
            logwarn("Param `L' is null.");
            return -1;
        }
    
        if (table_name)
            lua_getglobal(L, table_name);
    
        if (!lua_istable(L, -1)) {
            logwarn("It not is a table .");
            return -1;
        }
        // 现在堆栈包含:-1 =>table
    
    
        /*
         * 这里直接设置-2最好,因为递归使用该函数,lua_gettop() 得到的应该是第一个
         * table的索引,对于嵌套表来说,有点不对。
         *
         *   lua_table3={
         *       lua_table4 = {
         *           lt4_width = 100,
         *           lt4_height = 200,
         *           lua_table5 = {
         *               test = "test ok",
         *               lua_table8 = {
         *                   l8_1 = 1234567,
         *                   l8_2 = "12345678"
         *               }
         *           }
         *       },
         *       lt3_name = "qgh168",
         *   }
         * 对于上个表来说:
         * 第一次调用该函数,运行到该处时栈内容:
         * -1 =>lua_table3
         * 第二次递归调用该函数,运行到该处时栈内容:
         * -1 => lua_table4; -2 => key; -3 => lua_table3
         * 第三次递归调用该函数,运行到该处时栈内容:
         * -1 ==> lua_table5; -2 ==>key  -3 => lua_table4; -4 => key; -5 => lua_table3
         * .....
         * 所以lua_pushnil(L);后,此次递归要打印的table栈索引一直是-2
         */
        // int index = lua_gettop(L);
    
        lua_pushnil(L);
        //现在堆栈包含 -1 => nil; -2 => table
    
        while(lua_next(L, -2)) {
            // 栈内容: -1 => value; -2 => key; -3 => table
            key_type = lua_type(L, -2);
            value_type = lua_type(L, -1);
    
            if (LUA_TSTRING == key_type) {
                fprintf(stdout, "%s: ", lua_tostring(L, -2));
            }
            else if (LUA_TNUMBER == key_type) {
                fprintf(stdout, "%ld: ", lua_tointeger(L, -2));
            }
            else {
                logwarn("Invaild key type !!!");
                lua_pop(L, 1);
                continue;
            }
    
            switch(value_type) {
                case LUA_TSTRING:
                    fprintf(stdout, "%s\n", lua_tostring(L, -1));
                    break;
                case LUA_TNUMBER:
                    fprintf(stdout, "%f\n", lua_tonumber(L, -1));
                    break;
                case LUA_TBOOLEAN:
                    fprintf(stdout, "%s\n",
                            lua_toboolean(L, -1) == 1 ? "true" : "false");
                    break;
                case LUA_TTABLE:
                    fprintf(stdout, "\n");
                    lua_c_parse_table(L, NULL);
                    break;
                default:
                      logwarn("Invaild value type !!!");
            }
    
            lua_pop(L, 1); // 弹出 value,让 key 留在栈顶
            // 栈内容: -1 => key; -2 => table
        }
        // 现在堆栈包含:-1 =>table
    }
    
    
    
    
    /**************************************************************************************/
    
    
    //for test
    
    #define TEST
    #if defined(TEST)
    
    #include "luac_r.h"
    
    // 测试 va_arg 把 int 类型 转换到char* 类型
    int test_va_list(const char *type, ...)
    {
        char *tmp = NULL;
        va_list ap;
    
        va_start(ap, type);
    
        tmp = va_arg(ap, char *);
        printf("1 -> %s\n", tmp);
        printf("1 -> %ld\n", *(unsigned long *)&tmp);
    
        tmp = va_arg(ap, char *);
        printf("2 -> %ld\n", *(unsigned long *)&tmp);
        tmp = va_arg(ap, char *);
        printf("3 -> %ld\n", *(unsigned long *)&tmp);
        tmp = va_arg(ap, char *);
        printf("4 -> %ld\n", *(unsigned long *)&tmp);
        return 0;
    }
    
    
    int main(int argc, char *argv[])
    {
    #if 0
        test_va_list("test", "abc", 123, 456, 789);
        exit(0);
    #endif
    
        lua_State *L;
    
        L = lua_c_loadfile("./example.lua");
    
    
        printf("******* test global *******\n");
    
        printf("width: %d\theight: %d\n", lua_c_get_integer(L, "width"),
                    lua_c_get_integer(L, "height"));
        printf("name: %s\n", lua_c_get_string(L, "name"));
        printf("bool_enable: %d\n", lua_c_get_bool(L, "bool_enable"));
        printf("bool_disable: %d\n", lua_c_get_bool(L, "bool_disable"));
        printf("double_test: %f\n", lua_c_get_double(L, "double_test"));
    
    
        printf("\n******* test table *******\n");
    
        printf("a: %d\tb: %d\tc: %d\n", lua_c_get_integer(L, "lua_table1", "a"),
                    lua_c_get_integer(L, "lua_table1", "b"),
                    lua_c_get_integer(L, "lua_table1", "c"));
        printf("d: %s\te: %s\tf: %s\n", lua_c_get_string(L, "lua_table2", "d"),
                    lua_c_get_string(L, "lua_table2", "e"),
                    lua_c_get_string(L, "lua_table2", "f"));
    
        printf("lt3_name: %s\n", lua_c_get_string(L, "lua_table3", "lt3_name"));
        printf("l3l4_w: %d\tl3l4_h: %d\n",
                    lua_c_get_integer(L, "lua_table3", "lua_table4", "lt4_width"),
                    lua_c_get_integer(L, "lua_table3", "lua_table4", "lt4_height")
            );
        printf("l3l4l5_test: %s\n",
                    lua_c_get_string(L, "lua_table3", "lua_table4",
                    "lua_table5", "test"));
    
        printf("\n******* test index table *******\n");
        printf("1 -> %d\t2 -> %d\t3 -> %d\n",
                    lua_c_get_integer(L, "lua_table6", 1),
                    lua_c_get_integer(L, "lua_table6", 2),
                    lua_c_get_integer(L, "lua_table6", 3));
    
        printf("l7[1].name: %s\tsex: %d\n",
                    lua_c_get_string(L, "lua_table7", 1, "name"),
                    lua_c_get_bool(L, "lua_table7", 1, "sex"));
    
        printf("l7[2]: %d\n", lua_c_get_integer(L, "lua_table7", 2));
    
    
        printf("\n******* test index table *******\n");
        lua_c_parse_table(L, "lua_table3");
    
    
    
        lua_c_close(L);
        return 0;
    }
    #endif
    

    测试文件:

    width = 300
    height = 400
    name = "qgh168"
    bool_disable = false
    bool_enable = true
    double_test = 1.234
    
    lua_table1={a=123, b=456, c=789}
    lua_table2={d="string1", e="string2", f="string3"}
    
    lua_table3={
        lua_table4 = {
            lt4_width = 100,
            lt4_height = 200,
            lua_table5 = {
                test = "test ok",
                lua_table8 = {
                    l8_1 = 1234567,
                    l8_2 = "12345678"
                }
            }
        },
        lt3_name = "qgh168",
    }
    lua_table6={123, 456, 789}
    lua_table7 = {
        [1] = {name = "qgh", sex = true},
        [2] = 222
    }
    

    对于更复杂的lua配置文件读取可能不支持,仅仅测试了上面测试文件的lua结构。



    c api lua : https://www.jb51.net/article/65224.htm

    展开全文
  • 最近在做项目的优化时发现,我们项目中有个锻造的UI界面...如果在lua中去读取一个很大的表,比如策划配置的excel表,假如这个表有4000多行,而且数据项比较多,那么会导致读取时间变长,而且会使临时内存暴涨。 ...

    最近在做项目的优化时发现,我们项目中有个锻造的UI界面打开特别慢而且使用内存分析工具发现每次打开这个界面都会导致内存暴涨,在手动GC后内存被回收,可确定是临时内存暴涨,最后发现这个界面每次打开都会去读取一个很大的表数据,造成临时内存的上涨。

    如果在lua中去读取一个很大的表,比如策划配置的excel表,假如这个表有4000多行,而且数据项比较多,那么会导致读取时间变长,而且会使临时内存暴涨

    就算这个表已经被加载到lua内存中,当你再次去读取这张表并且把它保存在局部变量时也会使临时内存暴涨 ,因为这个是值数据需要开辟临时内存空间

    所以在读取表数据时应该避免去读取整张表的数据,而是根据索引去读取单个数据或者是某些数据。如果表结构不满足条件就应该和策划商量把表拆开来配置,这样才不会导致临时内存暴涨。

    实在不行也不要每次打开界面都去读取这么大的表,应该在首次打开的时候把这个表数据保存起来,下次打开时避免再次读取。

    展开全文
  • 前提: ... 使用openresty读取redis内的数据时,在init_by_lua_file中是不能连接redis的,所以有时候只能在rewrite或者access阶段读取redis数据,用什么办法在初始化阶段读取呢? 解决办法: 采用在init

    前提

            关于 openresty 或者 ngx_lua 请参考:http://openresty.org/en/

    问题

            使用openresty读取redis内的数据时,在init_by_lua_file中是不能连接redis的,所以有时候只能在rewrite或者access阶段读取redis数据,用什么办法在初始化阶段读取呢?

    解决办法

    采用在init阶段调用shell命令的方法,相当于在init阶段,执行一个shell命令,读取redis数据,把读取的文本数据进行解析,即可以实现读取redis数据到nginx中

    举例

            1 redis中存在一个hash, 存储数据为:

    hmset  test_hash f1 v1 f2 v2 f3 v3

            2 init_by_lua_file中读取的代码为:

            local cmd = "redis-cli  hgetall test_hash"

    local f = io.popen(cmd)

            local content = f:read("*a")

             f:close()

    以上 content中内存即redis中的数据。

    需要注意,此处的content是字符串,需要自己重新解析成字典,可以存入变量,也可以存在共享内存中。


    展开全文
  • 程序运行时,代码将加到内存上运行,代码运行到需要存储数据时,内存将要存储的数据储存到磁盘上,当代码运行到需要读取数据时,内存将磁盘上的数据读取出来。   Json数据: 一种数据交换格式,可将数据转换成...
  • 上一节讲到了worker进程的共享内存,它利用丰富的指令使数据的缓存操作变得非常简单,但它也存在一些缺点。 1.worker进程之间会有锁竞争,在高并发的情况下会增加性能开销。2.只支持Lua布尔值、数字、字符串和nil...
  • 如果转换大型lua表,则将减少lua vm的内存使用量。 因此,垃圾收集器将运行得更快(标记更少的gc对象)。 有时您需要重新加载lua vm,表中的常量数据不再需要解析器。 支持的类型 键必须是32位整数或字符串,值...
  • lua 多国语言文本解决方案

    千次阅读 2013-05-14 16:38:53
    lua 多国语言文本解决方案 以前用c++做游戏,文本处理往往是从excel导出各语言文本的自定义二进制格式文件,游戏根据相应...现在我们使用Lua开发游戏,可以利用lua语言的特点,直接生成包含文本数据lua代码,并作
  • lua热更新方案总结

    2021-04-19 10:57:37
    1:clearcache ...4:内存数据存入redis,进行数据分离以后,只需要重新加载 5:进行打补丁方式热更数据 6:永久驻留的 数据 + 动态更新的代码(一个进程 保存 全局数据 其他工作进程 读取全局数据) ...
  • lua GC 回收效率研究

    2020-05-29 14:45:29
    最近项目里打算做一个缓存全服玩家...可以从上面图看出,对于30万的玩家来说,内存数据大概108M,即使把字段翻一翻,也就216M,对于服务器的开发换来的是不需要异步读取离线玩家数据,基础数据统一管理的结果,这个内存
  • 广州大彩物联型串口屏可以通过 LUA 脚本配合...在 LUA 脚本中使用文件 IO 系统把数据保存到内存中,并能在重新上电后把数据读出来。工程中通过点击按钮实现保存,再点击读取按钮后,读取上次保存的值,并设置背光亮度值
  • 本文将介绍在掉电状态下还能保存背光亮度...在 LUA 脚本中使用文件 IO 系统把数据保存到内存中,并能在重新上电后把数据读出来。工程中通过点击按钮实现保存,再点击读取按钮后,读取上次保存的值,并设置背光亮度值。
  • redis 的一般用法是对其基础数据结构的读写,因为数据都放在内存,读写非常迅速,进一步还支持执行 lua 脚本,redis 提供了一个 lua 的执行环境(注意是 5.1),并提供了一些在 lua 脚本中调用 redis 命令的方法...
  • luabean 所有的配置文件的读取(将文件内容转为内存数据结构) luaprotocolhandler 所有网络协议的处理函数(导出process函数) manager 几个管理器(beanconfigmanager获取配置,luaprotocolmanage
  • skynet源码分析之sharedata共享数据

    千次阅读 2021-01-06 15:07:03
    sharedata模块就是为了解决这种需求设计的,其原理是:将共享lua数据存放到一个c结构里,所有服务都共享这个c结构的内存块,各个服务可以获取这个共享内存对象,然后就可以像读取普通lua表一样读取数据。 1. 创建...
  • sharedata模块就是为了解决这种需求设计的,其原理是:将共享lua数据存放到一个c结构里,所有服务都共享这个c结构的内存块,各个服务可以获取这个共享内存对象,然后就可以像读取普通lua表一样读取数据。 一、创建...
  • (DSL):用于描述各种二进制数据结构的声明性语言,分布在文件或内存中 (Rust):Rust解析器组合器框架 (三):面向位的解析库 (Python):用于解析和构建数据结构(二进制或文本)的库。 以声明的方式定义您的...
  • Redis学习笔记

    2020-07-21 13:49:17
    redis数据库,与传统数据库不同,redis的数据存储在内存中,读写速度非常快。 redis可以应用的方向:缓存,分布式锁,事务,持久化,LUA脚本,LRU驱动事件,多种集群方案。 为什么要用redis 高性能: 假设数据存储...
  • Redis学习(一)

    2020-07-19 18:09:42
    redis将数据存储到内存中,相较于从磁盘读取(磁盘-内存-读取出来),速度快得多。如果数据库中的数据发送改变之后,同步缓存中的数据即可 高并发 在高请求的情况下,直接访问数据库必将对数据库产生高额的负载。...
  • redis从小白到大佬

    2020-03-09 21:12:38
    简单的说redis是一种在内存中存储数据的数据库,其内部采用 key-value的形式进行存储。redis的读取速度非常快。因为它与MySql等常规数据库不同,不用与硬盘交互来读取数据。另外,redis 也经常用来做分布式锁。redis...
  • Redis学习与使用

    2021-04-16 15:56:26
    Redis是一个使用C语言开发的数据库,不过与传统的数据库不同的是Redis的数据是存在内存中的,是内存数据库,读写速度非常快,被广泛用于缓存方向。此外,Redis除了做缓存之外,也经常用来做分布式锁,甚至是消息队列...
  • 4:xls表格读取,生成Protobuf文件,方便游戏表格数据处理,支持lua 5:lua的支持,基于sol2插件,实现c ++,lua的混合编程 6:实现Lua服务器基本框架功能,未确定的功能未加入,暂时实现lua的protobuf,json的格式...
  • Redis面试(一)

    2020-06-21 14:43:48
    而将用户访问的数据存在缓存,下次直接从缓存中读取,相当于直接操作内存,速度非常快。如果数据库中的对应数据发生变化,更新缓存即可。 高并发: 将数据库中的数据存在缓存中,减少部分请求直接打到数据库,减少数
  • MTA-IMGLoader-源码

    2021-04-29 21:39:14
    BinaryReader类,该类的每个实例都是新的阅读器,用于从文件中读取二进制数据,并使用BinaryConverter类将其转换为lua数据格式。 BinaryConverter类,它是一个单例,提供用于将二进制数据转换为lua数据格式的功能...
  • Redis 是一个开源(BSD许可),内存储存的数据结构服务器,可作为数据库,高速缓存,消息队列代理。它支持字符串,哈希表,列表,集合,有序集合,位图,hyperloglogs等数据类型。内置复制,lua脚本,LRU回收,事物...
  • elasticsearch(ES) 无事务、近实时、成本比数据库高,几乎靠吃内存提高性能、最逆天的是,mapping不能改、缺乏访问控制、数据丢失和污染的问题、写入慢,读取快 binlog 增量备份 主从同步 三种格式:STATEMENT、ROW...
  • cocos2d-x游戏开发之旅

    2016-03-16 21:59:58
    介绍Cocos2d-x更高阶的内容,包括渲染效率的提高、动画、TexturePacker图片打包、Tiled地图游戏实例、定时器、函数回调、内存管理、数据保存、Csv文件读取。介绍Lua、有限状态机启蒙知识和应用。分享基于Cocos2d-X的...
  • 5、支持用Lua脚本对接收到的数据进行解析,支持用脚本语言直接进行发送操作; 6、支持数据触发模式,当串口(Socket)接收到预定义格式的数据时,可以直接触发脚本内指定的函数事件; 7、支持串口回环模式,发出的...
  • lua+c/c++做数据处理的服务器,希望在内存中做缓存。我将nginx的Worker数量调整为1,理论上讲,应该就是单进程,应当可以从dll中传出缓存指针,并在下次的传入dll中使用...
  • 7.11.8 用户数据(User Data) 226 7.12 关节(Joints) 226 7.12.1 关节的定义(JointDef) 226 7.12.2 关节的属性 227 7.12.3 距离关节(Distance Joint) 228 7.12.4 旋转关节(Revolute Joint) 229 7.12.5 移动...

空空如也

空空如也

1 2
收藏数 39
精华内容 15
关键字:

lua读取内存数据