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的元素

相关文章
|
存储 NoSQL Redis
Redis的Lua脚本有什么作用?
Redis Lua脚本用于减少网络开销、实现原子操作及扩展指令集。它能合并操作降低网络延迟,保证原子性,替代不支持回滚的事务。通过脚本,代码复用率提高,且可自定义指令,如实现分布式锁,增强Redis功能和灵活性。
621 1
|
缓存 NoSQL 搜索推荐
【📕分布式锁通关指南 03】通过Lua脚本保证redis操作的原子性
本文介绍了如何通过Lua脚本在Redis中实现分布式锁的原子性操作,避免并发问题。首先讲解了Lua脚本的基本概念及其在Redis中的使用方法,包括通过`eval`指令执行Lua脚本和通过`script load`指令缓存脚本。接着详细展示了如何用Lua脚本实现加锁、解锁及可重入锁的功能,确保同一线程可以多次获取锁而不发生死锁。最后,通过代码示例演示了如何在实际业务中调用这些Lua脚本,确保锁操作的原子性和安全性。
719 6
【📕分布式锁通关指南 03】通过Lua脚本保证redis操作的原子性
|
消息中间件 NoSQL Java
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
740 0
|
NoSQL Redis 数据库
Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
通过本文的介绍,我们详细讲解了 Lua 脚本在 Redis 中的作用、`eval` 命令的使用方法以及 `redis.call` 和 `redis.pcall` 的区别和用法。通过合理使用 Lua 脚本,可以实现复杂的业务逻辑,确保操作的原子性,并减少网络开销,从而提高系统的性能和可靠性。
882 13
|
监控 安全
公司用什么软件监控电脑:Lua 脚本在监控软件扩展功能的应用
在企业环境中,电脑监控软件对保障信息安全、提升效率至关重要。Lua 脚本在此类软件中用于扩展功能,如收集系统信息、监控软件使用时长及文件操作,向指定服务器发送数据,支持企业管理和运营。
240 6
|
缓存 分布式计算 NoSQL
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
221 2
|
存储 JSON Ubuntu
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
|
JSON 监控 数据格式
使用Lua代码扩展上网行为管理软件的脚本功能
本文介绍了如何使用Lua脚本增强上网行为管理,包括过滤URL、记录用户访问日志、控制带宽和自动提交监控数据到网站。Lua是一种轻量级语言,适合编写扩展脚本。文中提供多个示例代码,如URL过滤器、用户活动日志记录器和带宽控制器,帮助用户根据需求定制网络管理功能。通过这些示例,用户可以快速掌握Lua在上网行为管理中的应用。
380 4
|
存储 NoSQL Redis
Tair的发展问题之在Redis集群模式下,Lua脚本操作key面临什么问题,如何解决
Tair的发展问题之在Redis集群模式下,Lua脚本操作key面临什么问题,如何解决
|
存储 NoSQL 调度
Redis Lua脚本:原子性的真相揭秘
【4月更文挑战第20天】
2109 0
Redis Lua脚本:原子性的真相揭秘