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;
}

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

  1. lua程序设计 第一章习题答案

    练习1.1:运行阶乘的示例并观察,如果输入负数,程序会出现什么问题?试着修改代码来解决问题. 答:当输入负数时,循环无法终止,因为原本程序中的终止条件为n==0,而在输入为负数情况下,无法达成此终止条 ...

  2. 关于Lua程序设计{读书笔记}

    1.lua中的标识符可以是由任意字母.数字和下划线构成的字符串,但不能以数字开头.2.lua将通常类似"_VALUE"的标识符作为保留标识符3.lua的保留字 and break ...

  3. Lua 程序设计 (Roberto,Ierusalimschy 著)

    1 开始 2 类型与值 3 表达式 4 语句 5 函数 6 深入函数 7 迭代器与泛型for 8 编译,执行与错误 9 协同程序(coroutine) 10 完整的示例 11 数据结构 12 数据文件 ...

  4. lua程序设计(一)

    摘要:lua程序设计第二版学习笔记 脚本语言的基础语法大都比较简单,这里只列举一些lua独有,或者需要特别注意的语法点. 书中前三章的内容是一些惯常的引言,基础数据类型,运算符等内容,相对简单,这里就 ...

  5. 《Lua程序设计》第5章 函数 学习笔记

    Lua为面向对象式的调用也提供了一种特殊的语法——冒号操作符.表达式o.foo(o, x)的另一种写法是o:foo(x),冒号操作符是调用o.foo时将o隐含地作为函数的第一个参数.Lua可以调用C语 ...

  6. Lua 学习 chapter30 编写c函数的技巧 - Jow的博客

    目录 数组操作 字符串操作 在c函数中保存状态 生活总需要一点仪式感,然后慢慢的像那个趋向完美的自己靠近. 数组操作 Lua中的数组就是以特殊的方式使用边.像lua_setttable and lua ...

  7. c程序设计语言_习题1-16_自己编写getline()函数,接收整行字符串,并完整输出

    Revise the main routine of the longest-line program so it will correctly print the length of arbitra ...

  8. Lua程序设计入门

    在Lua中,一切都是变量,除了关键字.TTMD强大了. 1.注释 -- 表示注释一行 --[[ ]]表示注释一段代码,相当于C语言的/*....*/ 注意:[[ ... ]]表示一段字符串 2.lua ...

  9. 蒲公英 · JELLY技术周刊 Vol 27: 平平无奇 React 17

    蒲公英 · JELLY技术周刊 Vol.27 这个热闹的十月终于要走到尾声,React 17 历经 4 个 RC 版本之后,也于数天前正式发布了,而同在几天前发布的 CRA 4.0 也已经完成了 Re ...

随机推荐

  1. CSU 1330 字符识别? 【找规律】

    你的任务是写一个程序进行字符识别.别担心,你只需要识别1, 2, 3,如下: .*.  ***  *** .*.  ..*  ..* .*.  ***  *** .*.  *..  ..* .*.  ...

  2. linux程序与进程内存结构

    1.可执行文件结构: 1)代码区:包含操作码和操作对象.常量数据(const声明).立即数,代码区是共享的, 只提供只读. 2)全局/静态数据区:包含被初始化的全局数据和初始化静态数据. 3)未初始化 ...

  3. 训练指南 UVALive - 4043(二分图匹配 + KM算法)

    layout: post title: 训练指南 UVALive - 4043(二分图匹配 + KM算法) author: "luowentaoaa" catalog: true ...

  4. Linux命令之find(一)

    find [-H] [-L] [-P] [-Olevel] [-D help| tree| search| stat| rates| opt| exec] [路径] [表达式] find是查找文件的命 ...

  5. 【找规律】URAL - 2069 - Hard Rock

    题解及证明:http://www.cnblogs.com/StupidBoy/p/5241258.html #include<cstdio> #include<algorithm&g ...

  6. [POI2001]Peaceful Commission

    题目大意: 有n个国家要派代表开会,每个国家有两个代表可供选择. 有m对代表有仇,不能同时开会. 若每个国家只能派一个代表开会,问是否存在一种方案,使得每个国家都能正常参会? 如果有,输出字典序最小的 ...

  7. 使用history命令查看作业的整体执行情况

    1)通过使用history命令,我们可以深入到一个Job的任务级层面查看执行最快的任务,以及执行最慢的任务,以及其他的有用信息.命令如下: hadoop job -history /output “/ ...

  8. Scala零基础教学【102-111】Akka 实战-深入解析

    第102讲:通过案例解析Akka中的Actor运行机制以及Actor的生命周期 Actor是构建akka程序的核心基石,akka中actor提供了构建可伸缩的,容错的,分布式的应用程序的基本抽象, a ...

  9. PHP线程安全和非线程安全的区别

    Windows版的PHP从版本5.2.1开始有Thread Safe.这两者不同在于何处?到底应该用哪种?这里做一个简单的介绍. 从2000年10月20日发布的第一个Windows版的PHP3.0.1 ...

  10. ubi层次

    转:http://www.360doc.com/content/11/0518/13/496343_117643185.shtml UBI是什么? 它是一种flash管理方式 flash是一系列连续的 ...