lua与python结合_Lua和Python:实现一个高效的List对象(3)
这一篇介绍一些列表函数的实现。
取值
取值用法和Table一样,用ls[idx]获得列表的值;并且除了可以用正索引,还可以像Python一样用负索引,如-1表示最后一个元素,-2表示倒数第2个元素等等,C层代码如下:
// 取list指针#define checklist(L) (list_t*)luaL_checkudata(L, 1, LIST_MT)// ls[idx]static int list_index(lua_State *L) {
list_t *ls = checklist(L);
int idx = (int)luaL_checkinteger(L, 2);
if (idx > 0) idx--; // 正索引 else if (idx < 0) idx += ls->size; // 负索引 if (idx < 0 || idx >= ls->size) { // 超出范围的一律返回nil lua_pushnil(L);
return 1;
}
int ref = ls->ary[idx].ref; // 取引用值 lua_getuservalue(L, 1); // 将list的关联Table放到栈上 lua_rawgeti(L, -1, ref); // 通过引用取Table的值,并返回 return 1;
}
设值
对列表设值必须限定在长度之内,超出会抛出错误,唯一的例外是在列表最后设值,那样将认为是往后面追加,比如这样写:ls[#ls+1] = "ok"。
不能将nil设置给列表,因为Lua认为设置nil是删除元素,要达到类似的需求,可给列表设置false。
设值和取值一样支持负索引。
// ls[idx] = vstatic int list_newindex(lua_State *L) {
list_t *ls = checklist(L);
int idx = (int)luaL_checkinteger(L, 2);
if (idx > 0) idx--; // 正索引 else if (idx < 0) idx += ls->size; // 负索引 luaL_argcheck(L, 0 <= idx && idx <= ls->size, 2, "index out of range"); // 范围检查 if (lua_isnoneornil(L, 3)) // 不允许设置为nil luaL_argerror(L, 3, "value can not be nil");
lua_getuservalue(L, 1); // 将list的关联Table放到栈上 lua_pushvalue(L, 3); // 将设置的值压栈 if (idx == ls->size) { // 往后追加 check_and_grow_size(ls, 1);
ls->ary[ls->size++].ref = ref_value(L, ls, -2);
} else { // 正常设值 lua_rawseti(L, -2, ls->ary[idx].ref);
}
return 0;
}
check_and_grow_size检查数组的内存是否够用,不够会按2倍来扩展内存:
static void check_and_grow_size(list_t *ls, int n) {
int newcap = ls->cap;
while (ls->size + n > newcap)
newcap <<= 1;
if (newcap != ls->cap) {
ls->ary = (refdata_t*)realloc(ls->ary, newcap*sizeof(refdata_t));
ls->cap = newcap;
}
}
取值/设值由于用了元表的方法,多了一个间接层,必然比直接访问Table要慢一点。
取列表长度
按Lua的习惯,取长度用#ls,只需将list的size返回即可,效率比Table取长度要快得多:
// #lsstatic int list_len(lua_State *L) {
list_t *ls = checklist(L);
lua_pushinteger(L, ls->size);
return 1;
}
清除列表内容
直接将list的size置0即可,对于关联的Table,干脆抛弃它,直接新建一个Table关联:
// list.clear(ls[, shink])static int list_clear(lua_State *L) {
list_t *ls = checklist(L);
int shink = lua_toboolean(L, 2); // 如果指定shink,会收缩内存 ls->size = 0; // 直接置0 ls->ref = 0;
if (shink) {
ls->cap = 4;
ls->ary = (refdata_t*)realloc(ls->ary, ls->cap * sizeof(refdata_t));
}
lua_createtable(L, ls->cap, 0); // 重新创建Table,替换掉老的Table,老Table会被Lua自动GC回收掉。 lua_setuservalue(L, 1);
return 0;
}
交换两个位置的元素
这同样是一个很高效的操作,不需要涉及到Table的操作,直接将两个引用交换:
// list.exchange(ls, idx1, idx2)static int list_exchange(lua_State *L) {
list_t *ls = checklist(L);
int idx1 = (int)luaL_checkinteger(L, 2) - 1;
int idx2 = (int)luaL_checkinteger(L, 3) - 1;
if (idx1 == idx2) return 0;
luaL_argcheck(L, 0 <= idx1 && idx1 < ls->size, 2, "index out of range");
luaL_argcheck(L, 0 <= idx2 && idx2 < ls->size, 3, "index out of range");
refdata_t ref = ls->ary[idx1]; // 交换引用即可 ls->ary[idx1] = ls->ary[idx2];
ls->ary[idx2] = ref;
return 0;
}
插入元素
接口和table.insert一样,如果不指定pos则往后插入,如果指定则插入到pos位置:
// list.insert(ls, [pos,] value)static int list_insert(lua_State *L) {
list_t *ls = checklist(L);
int pos, n, vidx;
if (lua_gettop(L) == 2) { // 只有两个参数,则认为没有指定pos,pos设置为size pos = ls->size;
vidx = 2;
} else { // 有指定pos pos = (int)luaL_checkinteger(L, 2) - 1;
vidx = 3;
}
if (lua_isnoneornil(L, vidx)) // 不允许设置nil luaL_argerror(L, vidx, "value can not be nil");
// 检查pos的合法性 luaL_argcheck(L, 0 <= pos && pos <= ls->size, 2, "index out of range");
// 检查和增长内存 check_and_grow_size(ls, 1);
// 如果不是往后插入,则要移动内存 if (pos != ls->size)
memmove(ls->ary + pos + 1, ls->ary + pos, (ls->size - pos) * sizeof(refdata_t));
lua_getuservalue(L, 1); // 取关联Table lua_pushvalue(L, vidx); // 将要设置的值入栈 ls->ary[pos].ref = ref_value(L, ls, -2); // 将值设为Table,同时返回一个引用,保存到数组。 ls->size++;
return 0;
}
我们后面的操作都是对引用的操作,Table只是设值和去除值。
删除元素
接口和table.remove一样,如果不指定pos则从最后删除,如果指定则删除pos的值,最后返回删除的值
// list.remove(ls[, pos]) -> vstatic int list_remove(lua_State *L) {
list_t *ls = checklist(L);
int pos = luaL_optinteger(L, 2, ls->size) - 1;
luaL_argcheck(L, 0 <= pos && pos < ls->size, 2, "index out of range");
int ref = ls->ary[pos].ref;
// 如果不是删除最后一个,则要移动内存 if (pos != ls->size - 1)
memmove(ls->ary + pos, ls->ary + pos + 1, (ls->size - pos - 1) * sizeof(refdata_t));
ls->size--;
lua_getuservalue(L, 1); // 取关联Table lua_rawgeti(L, -1, ref); // 将要删除的值取出,返回 unref_value(L, -2, ref); // 删除值,解除引用 return 1;
}
其他接口
除了上面的函数,还有其他的接口,这里就不一一介绍了,我最后会把完整代码共享出来。
下一篇单独把排序拿出来说,并给出一个高效的实现。
lua与python结合_Lua和Python:实现一个高效的List对象(3)相关推荐
- python和lua哪个有前途_lua、python对比学习
一.基本数据类型: lua:nil(空).boolean(false和nil为假).number(数值).string(字符串).table(表).function(方法).thread (线程).u ...
- python是不是特别垃圾-Python是垃圾?(转)
第一个常见看法是: python和basic差不多应该是容易学,但是功能弱的语言 basic是好多人的年幼时的回忆了,gvbasic,gwbasic,qbaisc,各种版本把很多人带入了快乐的世界里面 ...
- python 搜寻蓝牙_3 Python Web搜寻器和搜寻器
python 搜寻蓝牙 在理想环境中,您需要的所有数据都将以开放且有据可查的格式清晰呈现,您可以轻松下载并使用它们以实现所需的目的. 在现实世界中,数据是混乱的,很少按照您的需要打包,并且经常是过时的 ...
- python lua 性能比较 内存_Lua 的速度为什么比 Python 快?
最近研究了下Python的代码,有了一些新的发现.大量的内置字符串常量没有做Intern优化,在python源码中搜索形如"__dict__"之类的常量是这么用的: PyObjec ...
- python js 性能_lua与python性能测试比较
CLR/C#/Java/Python/IronPython/JavaScript/Lua/Ruby/Squirre l性能测试 今天蛋疼地看到一篇,考虑到已经是2年前的文章了,现在的编译器可能会进一步 ...
- python用途与前景-Python的发展前景及干货!!
如今,Python已经成为一种再主流不过的编程语言了.它天生丽质,易于读写,非常实用,从而赢得广泛的群众基础,被誉为"宇宙最好的编程语言",被无数程序员热烈追捧.随着时代的发展越来 ...
- python语言能干什么-python语言能做什么
python语言可以用来做许多事,常见的一般有web开发.爬虫开发.人工智能以及游戏开发和构建桌面软件等等 Python是一个非常好用的编程语言而且开发速度快,语法简单通俗易懂,容易上手.非常适合初学 ...
- Python学习笔记: Python 标准库概览二
本文来自:入门指南 开胃菜参考:开胃菜 使用Python解释器:使用Python解释器 本文对Python的简介:Python 简介 Python流程介绍:深入Python 流程 Python数据结构 ...
- c++调用python原理_C++调用Python浅析
环境 VS2005Python2.5.4 Windows XP SP3 简述 一般开发过游戏的都知道Lua和C++可以很好的结合在一起,取长补短,把Lua脚本当成类似动态链接库来使用,很好的利用了脚本 ...
最新文章
- C# 创建控制台应用程序
- oracle存储过程备份,利用ORACLE存储过程与JOB结合实现对数据表自动备份
- LeetCode OJ -Happy Number
- UA MATH563 概率论的数学基础I 概率空间1 基本概念
- 怎样快速画出一个正方体_人教版小学数学五年级下册 长方体和正方体的体积 教案、课件,公开课视频...
- [精选代码笔记]Anagram, group-anagrams, two sum
- 排除瓶颈和加速django项目
- Waveform Audio 驱动(Wavedev2)之:WAV API模拟
- TypeScript 常用的新玩法
- 高性能服务器机柜,TS系列网络服务器机柜
- 小清新自适应宇航员404页面丢失svg错误网页源码
- node.js 之 socket.io
- MYSQL 中varchar类型转text格式
- Java 避免创建不必要的对象
- jenkins教程菜鸟_Jenkins教程:在Windows平台安装Jenkins
- python调用r语言函数_让R与Python共舞
- Spark大数据面试题1
- 安装semantic segmentation editor
- C++笔记——第一个MFC程序
- Java生鲜电商平台-异常模块的设计与架构
热门文章
- VC6.0显示代码行号
- 机器人运动学(a simple car)
- 高级线性表——静态链表(最全静态链表解读)
- c 语言epc编码如何解开,EPC编码结构
- pycharm安装scrapy失败_Scrapy ——环境搭配与一个简单的例子
- U-Boot 之二 详解使用 eclipse + J-Link 进行编译及在线调试
- android qq分组展开,Android仿qq分组管理的第三方库
- mysql正确打开方式_MySQL中MVCC的正确打开方式
- Splash 渲染引擎简介
- mysql基础拓扑图