编写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;
}
编写C函数的技术-《lua程序设计》 27章 学习的更多相关文章
- lua程序设计 第一章习题答案
练习1.1:运行阶乘的示例并观察,如果输入负数,程序会出现什么问题?试着修改代码来解决问题. 答:当输入负数时,循环无法终止,因为原本程序中的终止条件为n==0,而在输入为负数情况下,无法达成此终止条 ...
- 关于Lua程序设计{读书笔记}
1.lua中的标识符可以是由任意字母.数字和下划线构成的字符串,但不能以数字开头.2.lua将通常类似"_VALUE"的标识符作为保留标识符3.lua的保留字 and break ...
- Lua 程序设计 (Roberto,Ierusalimschy 著)
1 开始 2 类型与值 3 表达式 4 语句 5 函数 6 深入函数 7 迭代器与泛型for 8 编译,执行与错误 9 协同程序(coroutine) 10 完整的示例 11 数据结构 12 数据文件 ...
- lua程序设计(一)
摘要:lua程序设计第二版学习笔记 脚本语言的基础语法大都比较简单,这里只列举一些lua独有,或者需要特别注意的语法点. 书中前三章的内容是一些惯常的引言,基础数据类型,运算符等内容,相对简单,这里就 ...
- 《Lua程序设计》第5章 函数 学习笔记
Lua为面向对象式的调用也提供了一种特殊的语法——冒号操作符.表达式o.foo(o, x)的另一种写法是o:foo(x),冒号操作符是调用o.foo时将o隐含地作为函数的第一个参数.Lua可以调用C语 ...
- Lua 学习 chapter30 编写c函数的技巧 - Jow的博客
目录 数组操作 字符串操作 在c函数中保存状态 生活总需要一点仪式感,然后慢慢的像那个趋向完美的自己靠近. 数组操作 Lua中的数组就是以特殊的方式使用边.像lua_setttable and lua ...
- c程序设计语言_习题1-16_自己编写getline()函数,接收整行字符串,并完整输出
Revise the main routine of the longest-line program so it will correctly print the length of arbitra ...
- Lua程序设计入门
在Lua中,一切都是变量,除了关键字.TTMD强大了. 1.注释 -- 表示注释一行 --[[ ]]表示注释一段代码,相当于C语言的/*....*/ 注意:[[ ... ]]表示一段字符串 2.lua ...
- 蒲公英 · JELLY技术周刊 Vol 27: 平平无奇 React 17
蒲公英 · JELLY技术周刊 Vol.27 这个热闹的十月终于要走到尾声,React 17 历经 4 个 RC 版本之后,也于数天前正式发布了,而同在几天前发布的 CRA 4.0 也已经完成了 Re ...
随机推荐
- 【转】如何只用CSS做到完全居中
英文原版链接:http://codepen.io/shshaw/full/gEiDt 我们都知道 margin:0 auto; 的样式能让元素水平居中,而 margin: auto; 却不能做到垂直居 ...
- Submile text3 安装使用技巧
第一次用submile text3,发现还是有一些东西需要配置的,而且submile text3是最近发布的,和原来的submile text2还是有一些区别的.这两天自己配置了一下,用起来感觉还是不 ...
- 微信token
<?php define("TOKEN", "lmaster"); function checkSignature() { //从GET参数中读取三个字段 ...
- HDU 4528 小明系列故事――捉迷藏
广搜. 根据题意,可以知道状态总共有$4*n*m$种.每一个位置四种状态:两个都没有发现:发现$E$没发现$D$:发现$D$没发现$E$:两个都发现. 每次移动的花费都是$1$,队列里面状态的费用是单 ...
- 超级素数(sprime) (BFS)
问题 G: 超级素数(sprime) 时间限制: 1 Sec 内存限制: 64 MB提交: 47 解决: 11[提交][状态][讨论版] 题目描述 超级素数是指一个素数,每去掉后面一个数字,总能保 ...
- 【函数式权值分块】【分块】bzoj1901 Zju2112 Dynamic Rankings
论某O(n*sqrt(n))的带修改区间k大值算法. 首先对序列分块,分成sqrt(n)块. 然后对权值分块,共维护sqrt(n)个权值分块,对于权值分块T[i],存储了序列分块的前i块的权值情况. ...
- python3中zipfile模块的常用方法
一.zipfile模块的简述 zipfile是python里用来做zip格式编码的压缩和解压缩的,由于是很常见的zip格式,所以这个模块使用频率也是比较高的, 在这里对zipfile的使用方法做一些记 ...
- [OpenJudge8471][划分DP]切割回文
切割回文 总时间限制: 1000ms 内存限制: 65536kB [描述] 阿福最近对回文串产生了非常浓厚的兴趣. 如果一个字符串从左往右看和从右往左看完全相同的话,那么就认为这个串是一个回文串.例如 ...
- opencv在vc2010 express下环境搭建方法笔记+空白通用工程(已编译测试通过)(提供下载)
opencv在VC2010 express版本下的环境搭建可以参见下面的wiki,这里面讲的非常清楚. http://wiki.opencv.org.cn/index.php/VC_2010_Expr ...
- C++类的复习
1.C++ 类的声明:class class_name{ private: /* *私有的数据和成员函数 *只能被本类中的成员函数引用,类外不能调用 ...