zoukankan      html  css  js  c++  java
  • lua与CAPI概述

    1.  栈

    1.1 说明

    lua与C语言操作都是通过栈来进行的。这个栈是抽象的栈,栈中每一个元素都能保存任何类型的LUA值。
    要获得一个lua中的一个值时(例如一个全局变量),只要调用一个Lua的Api函数,Lua就会将指定的值压入栈中。
    要将一个值传入Lua时,需要先将这个值压入栈,然后再调用Lua Api,Lua就会获取值并将此值从栈中弹出。
    几乎所有的lua api都会使用到栈,luaL_loadbuffer将它的结果(编译好的程序或错误消息)留在栈中;lua_pcall会调用栈中的一个函数,若发生错误则将错误信息留在栈中。

    1.2 栈的索引与查询元素

    以栈底为参考物:api使用“索引”来引用栈中的元素。第一个压入栈中的元素索引为1;第二个压入的元素索引为2依此类推。
    以栈顶为参考物:使用负数的索引来访问栈中的元素。此时,-1表示栈顶元素(最后一个压入的元素),-2表示栈顶下面的一个,依此类推。

    image

    代码测试

    int _tmain(int argc, _TCHAR* argv[])
    {
        lua_State *L = luaL_newstate();
        luaL_openlibs(L);
        lua_pushstring(L,"this is a");
        lua_pushstring(L,"this is b");
        lua_pushstring(L,"this is c");
    
        cout<<lua_tostring(L,1)<<endl;
        cout<<lua_tostring(L,2)<<endl;
        cout<<lua_tostring(L,3)<<endl;
        cout<<"---------------"<<endl;
    
        cout<<lua_tostring(L,-1)<<endl;
        cout<<lua_tostring(L,-2)<<endl;
        cout<<lua_tostring(L,-3)<<endl;
        lua_close(L);
    
        system("pause");
        return 0;
    }

    以上代码的输出结果为:

    this is a
    this is b
    this is c
    ---------------
    this is c
    this is b
    this is a
    请按任意键继续. . .

    为了检查一个元素是否为特定类型,API提供了类似lua_is*的函数,例如lua_isnumber等。实际上lua_isnumber不会检查值是否为数字类别,而是检查能否转换为数字类型

    lua_tolstring返回的字符串在其末尾会有一个额外的零,不过这些字符串中间也可能有零,字条串长度通过第三个参数len返回,这才是真正的字符串长度。尽管下总为真

        size_t l;
        const char* s = lua_tolstring(L,-1,&l);
        assert(s[l] == '\0');
        assert(strlen(s) <= 1)

    因此遍历栈有以下方法

    //遍历栈
    static void statckDump(lua_State * L)
    {
        int nTop = lua_gettop(L);
        for(int i = 1;i <= nTop;i++ )
        {
            int t = lua_type(L,i);
    
            switch(t)
            {
            case LUA_TSTRING:
                printf(" '%s' ",lua_tostring(L,i));
                break;
            case LUA_TBOOLEAN:
                printf(lua_toboolean(L,i) ? "true" : "false");
            case LUA_TNUMBER:
                printf("%g",lua_tonumber(L,i));
                break;
            default:
                printf("%s",lua_typename(L,t));
                break;
            }
            printf("  ");
        }
        printf("\n");
    }

    1.2 其它栈操作

    int lua_gettop(lua_State * L)
    返回栈中元素的个数,也可以说是栈顶元素的索引。

    int lua_settop(lua_State * L ,int index)
    将栈顶设置为一个指定的位置,即修改元素数量。如果之前的栈比新设置的要高,那么高出来的那些会被丢弃。反之,会向栈中压入nil来补足大小。有一个特例,调用lua_settop(L,0)能清空栈。也可以用负数索引来使用lua_settop。另外,API根据这个函数还提供了一个宏,用于从栈中弹出n个元素。
    #define lua_pop(L,n) lua_settop(L,-(n)-1)

    lua_pushvalue函数会将指定索引上的值 的副本压入栈。lua_remove删除指定索引上的元素,并将该位置之上的所有元素下移以填补空缺。

    lua_insert 会上移指定位置之上的所有元素以开辟一个槽的空间。然后将栈顶元素移动到该位置。

    lua_replace弹出栈顶的值,并将该值 设置到指定索引上。但它不会移动任何东西。

    int _tmain(int argc, _TCHAR* argv[])
    {
        lua_State * L = luaL_newstate();
    
        lua_pushboolean(L,1);
        lua_pushnumber(L,10);
        lua_pushnil(L);
        lua_pushstring(L,"hello");
    
        statckDump(L);
    
        lua_pushvalue(L,-4);//将指定索引值压入副本
        statckDump(L);
    
        lua_replace(L,3); //弹出栈顶值 并把索引为3的元素替换
        statckDump(L); 
    
        lua_settop(L,6); //增高栈顶
        statckDump(L);
    
        lua_remove(L,-3); //移除索引为-3
        statckDump(L);
    
        lua_settop(L,-5);
        statckDump(L);
    
        lua_close(L);
        system("pause");
        return 0;
    }

    输出结果为:

    true  10  nil   'hello'
    true  10  nil   'hello'   true
    true  10  true   'hello'
    true  10  true   'hello'   nil  nil
    true  10  true  nil  nil
    true
    请按任意键继续. . .

    最后说一下lua_pop
    lua_pop(lua_State * L,int number);  
    此函数是从栈中弹出 number个元素,而不是弹出第number的元素

    本人新博客网址为:http://www.hizds.com
    本博客注有“转”字样的为转载文章,其余为本人原创文章,转载请务必注明出处或保存此段。c++/lua/windows逆向交流群:69148232
  • 相关阅读:
    python之并发编程
    python之并发编程(理论部分)
    python之网络部分
    python之异常处理
    py之包和日志
    mysql之general log 日志
    python之代码规范
    文件权限管理命令chmod,chown与文本搜索命令grep
    Linux用户与组管理命令
    Linux常见文件管理命令
  • 原文地址:https://www.cnblogs.com/zhangdongsheng/p/3009914.html
Copyright © 2011-2022 走看看