nvmdso 是我们的模块名称。
之前我们说过, 对于lua中的table这种动态容器我们在静态类型的语言中可能会有handle类或代理类进行操作来映射他们之间的关联,然后通过系统类型包装我们封装了数组:
我们在lua内部使用的时候都是table,我们定义的数组的结构为
{ [ctype] = 类型, [data] = 数据 table}
我们在使用内存类型的时候, 需要考虑到宿主与脚本的类型在内存对齐方式, 存储方式,结构都是不一致的,所以我们必须使用同样一套标准。在我们的方案里,我们抛弃了lua 的堆栈式操作,转而使用的是neko的类型和内存操作方式来同一处理数据结构。
因为lua是弱类型的脚本语言,如果我们使用动态容器来内嵌table和其他的类型的符合类型, 我们需要区分lua内部使用的table 和数组, int 和 float 这些不同的数据结构。进而按照我们定下的规范来固定每个动态类型的区间。
nvmdso.newTypeArray
我们的第一个函数就是分配一个neko的数组的指针, neko的数组在内存里的表现形式和c++代理类相似, neko的数组是连续的 value 类型的指针,我们可以通过指针的偏移来获取数组内元素的位置。 因为是value指针,只要符合value定义的neko数据结构都可以存储在这个容器里。
上面看到我们的数组分配下来以后有两个属性, 一个是ctype 另外一个是data数据,我们的数据使用的也是table。
local arr = nvmdso.newTypeArray();arr.data [1] = 10;arr.data [2] = hash;
nvmdso.LuaArray2NekoArray(arr); 这个api可以将lua的数组转化为真正的neko数组,并且支持动态容器的特性。比如我们上面代码中的hash 是lua的一个table。 接下来需要将这个arr的结构转化成neko的内存。
local hash={};hash.a= 1;hash.a2= 3.14;hash.b= nil;hash.c = "asas";hash.d = true;hash.e = {};local arr = nvmdso.newTypeArray();arr.data [1] = 10;arr.data [2] = hash;local nekoArr = nvmdso.LuaArray2NekoArray(arr);print(nvmdso.getArrayLength(nekoArr));print(nvmdso.getArrayValue(nekoArr, 0));print(nvmdso.getArrayValue(nekoArr, 1));
nvmdso.getArrayLength(ptr)
这个函数是获取neko数组的长度。
nvmdso.getArrayValue(ptr, pos);
这个函数是根据数组的指针和位置获取数组在该位置上的元素, 同时还有setter操作等等。这种原子操作不需要直接使用,本例子为了直观体现结果才这样用。
完整测试代码:
package.cpath = './build/?.so;'install,b,c = package.loadlib("./build/nvmdso.so","luaopen_nvmdso");install();local vm = nvmdso.initVM();nvmdso.selectVM(vm);print("=======test lua array =======");local hash={};hash.a= 1;hash.a2= 3.14;hash.b= nil;hash.c = "asas";hash.d = true;hash.e = {};local arr = nvmdso.newTypeArray();arr.data [1] = 10;arr.data [2] = hash;print(arr);local nekoArr = nvmdso.LuaArray2NekoArray(arr);print(nvmdso.getArrayLength(nekoArr));print(nvmdso.getArrayValue(nekoArr, 0));print(nvmdso.getArrayValue(nekoArr, 1));
运行结果: