lua学习笔记(3)——C API基础和栈

Lua不仅可以是一个独立运行的程序包,也可以是一个用来嵌入到其他应用程序库。Lua解释器是一个使用lua标准库实现的独立的解释器,是一个很小的应用。解释器负责程序和使用者的接口:从使用者哪里获取文件或者字符串,并传给lua标准库,lua标准库负责最终的代码运行。

Clua的两种交互方式:

1、C作为应用程序语言,lua作为一个库使用;

2、Lua作为应用程序语言,C作为库使用。

这两种方式,C语言都使用相同的APIlua通信,因此Clua交互部分的接口成为C APIC API是一个C代码与lua进行交互的函数集。包括以下组成部分:读写lua全局变量的函数,调用lua函数的函数,运行lua代码批那段的函数,注册C函数然后可以在lua中被调用的函数。

使用C编程时,Clua之间通信的关键在于一个虚拟的栈,几乎所有的API调用都是对栈上的值进行操作,所有的Clua之间的数据交换也都是通过这个栈来完成。下面我们先介绍lua常用的一些函数,再介绍栈操作函数。

一、lua基础库函数

    在上一次的学习中已经搭建了lua运行环境,因此现在仅介绍函数用法用途。

lua_open() : 创建一个新的lua环境函数,相当于lua库(模块启动)

open返回lua结构体指针(lua_State),指向这个结构体的指针作为所有lua函数的第一个参数。

lua_pcall() : 读取/写入lua环境的全局变量函数,注册可以被lua调用的新函数的函数;

    以下函数加载lua各辅助库:

        luaopen_base(L);

luaopen_table(L);

luaopen_io(L);

luaopen_string(L);

luaopen_math(L);

    在5.0之后的版本,上面的几个函数用下面函数替代即可,使用更简单了:

luaL_openlibs(L);

Lua_close();

二、堆栈操作函数

1、压栈函数

void lua_pushnil (lua_State *L);  /* 空值 */
void lua_pushboolean (lua_State *L, int bool); /* 布尔值*/
void lua_pushnumber (lua_State *L, double n); /* 数值 */
void lua_pushlstring (lua_State *L, const char *s,
size_t length);  /* 字符串(指定长度,忽略\0) */
void lua_pushstring (lua_State *L, const char *s); /* 字符串,\0则结束*/

2、判断堆栈中的值类型

int lua_isnil(lua_State *L, int index);

int lua_isboolean(lua_State *L, int index);

int lua_isnumber(lua_State *L, int index);

int lua_isstring(lua_State *L, int index);

lua_isnumberlus_isstring函数不检查这个值是否是制定的类型,而是看它是否能被转换成制定的那个类型。任何数字类型都满足lua_isstring

Lua.h定义的类型:

LUA_TNIL
LUA_TBOOLEAN

LUA_TNUMBER

LUA_TSTRING

LUA_TTABLE
LUA_TFUNCTION

LUA_TUSERDATA

LUA_TTHREAD

堆栈索引:

    栈中第一个入栈的元素索引为1,第二个入栈的元素索引为2,以此类推,即从栈底数起123...。同时,索引可以为负数,即从栈顶起,-1-2-3...

3、其他堆栈操作

int lua_gettop (lua_State *L);

返回堆栈中元素个数,也既是栈顶元素的索引。

void lua_settop (lua_State *L, int index);

设置栈顶位置。如果开始的栈顶高于新的栈顶,顶部的值被丢弃。否则,为了得到指定的大小这个函数压入相应个数的空值( nil)到栈上。特别的,lua_settop(L,0)清空堆栈。

void lua_pushvalue (lua_State *L, int index);

拷贝索引指定的值到栈顶。(不论指定索引中的值的类型是什么)
void lua_remove (lua_State *L, int index);

lua_remove 移除指定索引位置的元素,并将其上面所有的元素下移来填补这个位置的空白。
void lua_insert (lua_State *L, int index);

lua_insert 移动栈顶元素到指定索引的位置,并将这个索引位置上面的元素全部上移至栈顶被移动留下的空
隔。
void lua_replace (lua_State *L, int index);

lua_replace 从栈顶弹出元素值并将其设置到指定索引位置,没有任何移动操
作。

三、例子

下面的两个函数可以很好的理解栈的操作和过程,例子本身比较简单,分析一下代码就能理解。

static void stackdump(lua_State *L)
{
    int i;
    int top = lua_gettop(L);    /* 取栈顶标号 */

    for(i = 1; i <= top; i++)
    {
        int t = lua_type(L, i); /* 取值类型 */

        switch(t)
        {
            case LUA_TSTRING:   /* type string */
            {
                printf("%s", lua_tostring(L, i));
                break;
            }
            case LUA_TBOOLEAN:  /* type boolean */
            {
                printf(lua_toboolean(L, i) ? "true" : "false");
                break;
            }
            case LUA_TNUMBER:   /* type number */
            {
                printf("%g", lua_tonumber(L, i));
                break;
            }
            default:            /* type other */
            {
                printf("%s", lua_typename(L, t));
                break;
            }            
        }

        printf("   ");
    }

    printf("\n");
}


void stack_op()
{
    lua_State *L = lua_open();

    lua_pushboolean(L, 1);
    lua_pushnumber(L, 10);
    lua_pushnil(L);
    lua_pushstring(L, "hello");

    /* true 10 nil 'hello' */
    stackdump(L);

    /* true 10 nil 'hello'  true*/
    lua_pushvalue(L, -4);
    stackdump(L);

    /* true 10 true 'hello'  */
    lua_replace(L, 3);
    stackdump(L);

    lua_settop(L, 6);
    stackdump(L);

    lua_remove(L, -3);
    stackdump(L);

    lua_settop(L, -5);
    stackdump(L);

    lua_close(L);
    //return 0;
}


输出结果:

$ ./lua_test
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   



猜你喜欢

转载自blog.csdn.net/xiaofeng881105/article/details/78583648