编写C函数的技术-《lua程序设计》 27章 学习-阿里云开发者社区

开发者社区> 技术小阿哥> 正文

编写C函数的技术-《lua程序设计》 27章 学习

简介:
+关注继续查看

1.数组操作

void lua_rawgeti(lua_State * L ,int index,int key)

void lua_rewseti(lua_State * L,int index,int key)

index表示table在栈的位置,key表示元素在table中的位置

test.lua内容

复制代码
tab = {"a","b","c","c","e","f","g","h","i"}

function ShowTable(tabb)
    print("显示table")
    for k,v in pairs(tabb) do
        print(v .. ' ')
    end    
end

ShowTable(tab)

print(GetTableFromIndex(tab,6))
SetTableFromIndex(tab,2,"aaaaaaaaaa")
ShowTable(tab)
复制代码
复制代码
static int GetTableFromIndex(lua_State * L )
{
    //GetTableFromIndex(tab,6)
    int index = luaL_checkint(L,2);
    lua_rawgeti(L,1,index);
    const char *  ret = luaL_checkstring(L,-1);
    return 1;
}
static int SetTableFromIndex(lua_State * L )
{
    //SetTableFromIndex(tab,2,"aaaaaaaaaa")
    int index = luaL_checkint(L,2);
    const char *  szNewValue = luaL_checkstring(L,3);
    lua_pushstring(L,szNewValue);
    lua_rawseti(L,1,index);
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    lua_State * L = luaL_newstate();
    luaL_openlibs(L);
    lua_register(L,"GetTableFromIndex",GetTableFromIndex);
    lua_register(L,"SetTableFromIndex",SetTableFromIndex);
    if(0 != luaL_dofile(L,"test.lua"))
    {
        cout<<"error:"<<luaL_checkstring(L,-1)<<endl;
        lua_pop(L,1);
    }
    statckDump(L,"最后");
    lua_close(L);
    system("pause");
    return 0;
}
复制代码

2.字符串操作

lua_pushlstring(L,s+I,j-i+1) 把一个字符串区间为[I,j]传递给lua

下面函数将一个字符串以分隔符生成一个表 例如调用 split(“he,3,66,22”) 会返回table {“he”,”3”,”66”,”22”}

test.lua

tableStrings = l_split("1111,2222,3333,4444,6666",",");
ShowTable(tableStrings)
复制代码
static int l_split(lua_State * L )
{
    const char * s = luaL_checkstring(L,1);  //第一个参数要分隔的字符串
    const char * sep = luaL_checkstring(L,2);   //第二个参数分隔符
    const char * e;
    int i = 1;

    lua_newtable(L); //创建返回值 

    //遍历所有字符串分隔
    while((e = strstr(s,sep)) != NULL)
    {
        lua_pushlstring(L,s,e-s);  //压入子串
        lua_rawseti(L,-2,i++);     //修改table
        s = e + 1;  //跳过分隔符
    }
    //压入最后一个子串
    lua_pushstring(L,s);
    lua_rawseti(L,-2,i);
    return 1;
}
复制代码

还有一些相关的函数 lua_pushfstring,luaL_buffinit,luaL_addchar,luaL_add 等lua帮助文件都有说明

3.在c函数中保存状态

对于一个lua函数 来说,有3种地方可以保存非局部数据他们是,全局变量,函数环境和非局部的变量(closure中)

3.1注册表

注册表是位于一个”伪索引“上,这个索引值由LUA_REGISTRYINDEX定义。伪索引就像一个栈中的索引,但它所关联的值不在栈中。为了获取注册表中的key为”Key”的值,可以这么做

lua_getfield(L,LUA_REGISTRYINDEX,”KEY”)

在注册表中为了避免冲突的key尽量不要用常用的名字,在注册表中不应使用数字类型的key,因为这种key是被”引用系统“所保留的,这个系统由辅助库中的一系列函数组成,它可以在向一个table存储value时忽略如何创建一个唯一 的key

int r = luaL_ref(L,LUA_REGISTRYINDEX);  //弹出一个值,然后用新分配的整数key来将这个值保存到注册表中,最后返回这个key,这个key被称为”引用 “

lua_rewgeti(L,LUA_REGISTRYINDEX,r); //将与引用关联的值压入栈中

luaL_unref(L,LUA_REGISTRYINDEX,r); //释放该值和引用

3.2 C函数环境

lua5.1开始每一个c函数都有自己的一个环境table一个函数可以像访问注册表一样通过一个伪索引来访问他的环境table环境table的伪索引是LUA_ENVIRONINDEX。在在C语言中设置环境的代码如下:

复制代码
int luaopen_foo(lua_State * L)
{
    lua_newtable(L);
    lua_replace(L,LUA_ENVIRONINDEX);
    luaL_register(L,<库名>,<函数列表>);
    ...

}
复制代码

3.3 upvalue

注册表提供了全局变量的存储,环境提供了模块变量的存储,而upvalue机制则实现了一种类似于c语言中静态变量的机制。这种变量只在一个特定函数中可见。每当lua中创建一个函数时,都可以瘵任务数量的upvalue与这个函数关联

将这种c函数与upvalue关联称为closureg一个c closure类似于Lua closure。closure可以用同一个函数代码来创建多个closure,每个closre可以拥有不同的upvalue

 

复制代码
static int counter(lua_State * L)
{
    int val = lua_tointeger(L,lua_upvalueindex(1));  //luaj_upvalueindex可以生成一个upvalue的伪索引,注意这个索引可以像其它栈索引一样,但不存在于栈中
    lua_pushinteger(L,++val);  
    lua_pushvalue(L,-1);
    lua_replace(L,lua_upvalueindex(1)); //更新updavalue
    return 1;
}
int newCounter_(lua_State * L)
{
    lua_pushinteger(L,0);  //创建cclosure前必须将cclosure初始值压栈
    lua_pushcclosure(L, //创建一个cclosure
        &counter, //基础函数
        1);  //upvalue个数
    return 1;
}
复制代码

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
14.Linux shell编程(函数)
(创建于2018/2/1) 1.简单的一个函数 1 #!/bin/bash 2 3...
728 0
C/C++程序编译流程(预处理-&gt;编译-&gt;汇编-&gt;链接)
程序的基本流程如图: 1. 预处理 预处理相当于根据预处理指令组装新的C/C++程序。经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内容上有所不同。
759 0
《多核与GPU编程:工具、方法及实践》----第2章 多核和并行程序设计 2.1 引言
本章目标 学习设计并行程序的PCAM方法。 使用任务图和数据依赖图来识别可以并行执行的计算部分。 学习将问题的解法分解为可并发执行部分的流行的分解模式。 学习编写并行软件的主要程序结构模式,如主/从和fork/join。 理解分解模式的性能特点,如流水线。
993 0
多线程编程学习四(Lock 的使用)
一、前言     本文要介绍使用Java5中 Lock 对象,同样也能实现同步的效果,而且在使用上更加方便、灵活,主要包括 ReentrantLock 类的使用和ReentrantReadWriteLock 类的使用。
814 0
《JavaScript启示录》——1.4 用户自定义/非原生对象构造函数
关于构造函数比较复杂的一点就是this值在函数内部的使用方式。请记住,构造函数只是一个饼干模具,在将它与new关键字一起使用时,它会创建一个拥有构造函数内部定义的属性和值的对象。在使用new关键字时,this值的字面意思是基于构造函数内部的语句创建的新对象/新实例。
1029 0
机器学习实战:基于概率论的分类方法:朴素贝叶斯(源码解析,错误分析)
按照惯例,先把代码粘到这里 from numpy import * def LoadDataSet(): postingList = [['my', 'dog', 'has', 'flea', 'proble...
838 0
13694
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载