跳转至

C语言内存数组(zbuff)

一、ZBUFF(C 内存数组)简介

1.1 为什么要用 zbuff 库?

zbuff 库的作用是提供了一套类似于 C 的字节操作的接口。

在 lua 中一般是使用 string 来操作字符串的。但为什么要用 zbuff 库而不用 string?

因为 string 库有如下缺点:

1、无法多个变量持有同一份字符串。如:s2=s1,会将 s1 中的数据复制一份放到 s2 中。

2、不能直接以数组形式操作。如:不能使用 s[1]操作。而使用 s:byte(2)比较麻烦。

3、字符串新建后就无法修改。如:新建 local s = string.char(0x01,0x02)后,字符串是无法修改的,除非再新建一个字符串赋值给变量 s。

而 zbuff 库可以解决上述问题。

1.2 zbuff 库使用简介

可以在 sram 上或者 psram 上申请空间,也可以自动申请(如存在 psram 则在 psram 进行申请,如不存在或失败则在 sram 进行申请)。

操作里面的元素时,可以根据 光标进行增删改查。偏移方式有三种:从头、当前位置、末尾开始。常用参数如下:

常量
类型
解释
zbuff.SEEK_SET
number
以头为基点
zbuff.SEEK_CUR
number
以当前位置为基点
zbuff.SEEK_END
number
以末尾为基点
zbuff.HEAP_AUTO
number
自动申请(如存在 psram 则在 psram 进行申请,如不存在或失败则在 sram 进行申请)
zbuff.HEAP_SRAM
number
在 sram 申请
zbuff.HEAP_PSRAM
number
在 psram 申请

二、演示功能概述

本 demo 将演示 zbuff 的创建、写入数据、读取数据、获取 zbuff 长度、获取光标位置。

三、准备硬件环境

“古人云:‘工欲善其事,必先利其器。’在深入介绍本功能示例之前,我们首先需要确保以下硬件环境的准备工作已经完成。”

参考:硬件环境清单,准备以及组装好硬件环境。

四、软件环境

“凡事预则立,不预则废。”在详细阐述本功能示例之前,我们需先精心筹备好以下软件环境。

1. Luatools 工具

2. 内核固件文件(底层 core 固件文件):LuatOS-SoC_V10001_Air8101.soc;参考项目使用的内核固件

3. luatos 需要的脚本和资源文件, 脚本和资源文件

lib 脚本文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件;

准备好软件环境之后,接下来查看如何烧录项目文件到 Air8101 开发板,将本篇文章中演示使用的项目文件烧录到 Air8101 开发板中。

4. 本教程使用api接口

五、代码示例介绍

5.1 创建 zbuff,以 c 语言数组的形式操作 zbuff

local buff = zbuff.create(1024)
    -- 可当成数组直接赋值和取值
    buff[0] = 0xAE
    log.info("zbuff", "buff[0]", buff[0])

5.2 以 io 的形式操作

-- 写数据write, 操作之后指针会移动,跟文件句柄一样
    buff:write("123") -- 字符串
    buff:write(0x12, 0x13, 0x13, 0x33) -- 直接写数值也可以

    -- 设置指针位置, seek
    buff:seek(5, zbuff.SEEK_CUR) -- 指针位置+5
    -- 指针位置设置为0
    buff:seek(0)                 -- 绝对地址

    -- 读数据read, 指针也会移动
    -- 读取前三个字节,即"123"
    local data = buff:read(3)
    log.info("zbuff", "data", data)

5.3 清除 zbuff

-- 清除全部数据,但指针位置不变
    buff:clear() -- 默认填0
    buff:clear(0xA5) -- 也可以指定填充的内容

5.4 以 pack 库的形式写入或读取数据

-- 支持以pack库的形式写入或读取数据
    buff:seek(0)
    buff:pack(">IIHA", 0x1234, 0x4567, 0x12,"abcdefg")
    buff:seek(0)
    local cnt,a,b,c,s = buff:unpack(">IIHA10")

5.5 按类型读写数据

读取类型可为:I8、U8、I16、U16、I32、U32、I64、U64、F32、F64

读取的时候,记得注意下标位置。

-- 也可以直接按类型读写数据
    local len = buff:writeI8(10)
    local len = buff:writeU32(1024)
    local i8data = buff:readI8()
    local u32data = buff:readU32()

5.6 取出指定区间的数据

-- 取出指定区间的数据
    local fz = buff:toStr(0,5)

5.7 获取创建的 zbuff 的长度,和指针当前位置

-- 获取其长度
    log.info("zbuff", "len", buff:len())
    -- 获取其指针位置
    log.info("zbuff", "len", buff:used())

5.8 测试 F32(32 位单精度浮点数)类型数据的读写

-- 测试writeF32, 注意, EC618系列(Air780E等), V1106会死机, 在V1107修复
    buff:seek(0, zbuff.SEEK_SET)
    buff:writeF32(1.2)
    buff:seek(0, zbuff.SEEK_SET)
    log.info("buff", "rw", "f32", buff:readF32())

六、功能验证

zbuff 库使用 C 数组方式、io 方式操作。获取 zbuff 长度、获取当前指针位置、Float 类型操作测试如下:

七、总结

本示例介绍了为什么要用 zbuff,以及 zbuff 的用法。

常见问题

1、先 buff:write(0x12),再设置光标到正确位置后,使用 buff:read(1)读取不到数据。

直接读取是不可见字符,要使用 buff:read(1):toHex()读取数据。