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

本文介绍了Lua作为一种轻量级脚本语言如何与C语言进行交互,涵盖了Lua的基础库函数、堆栈操作函数等内容,并通过实例演示了Lua与C交互的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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   



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值