文章对应视频教程:

在下方喔 ~~~ 欢迎关注


点击图片或链接访问我的B站主页~~~

lau解释器移植与功能验证


1、引言

本文将介绍如何将Lua解释器移植到标准的ANSI C环境。
实现ANSI C的移植,就可以实现在嵌入式各类板卡的移植。
当然,你的板卡得具备ANSI C环境,一般情况keil、GCC都会有C库实现。
关于Lua解释器的重要性,或者有何特殊指出,可以看看我得上篇文章:
《可用于嵌入式的解释器调研对比,及lua解释器介绍》


2、环境准备

2.1 源码下载

您可以在Lua官方网站上下载Lua解释器的源代码。以下是Lua官方网站的链接:

Lua解释器下载

在该网页上,点击的Lua解释器源代码的下载链接(图中红色框部分),进行源代码下载,可能有点慢。

在这里插入图片描述
下载完成后,进行接下,得到下图的文件,提取其中的src文件夹,将src中的makefilelua.cluac.c文件删除,待用。
在这里插入图片描述

2.2 项目构建环境准备

参考往期博客《Cmake+Kconfig项目构建》,搭建一个空的项目框架,用来测试Lua是否移植成功。

复制项目构建模板,修改名字,修改CMakeLists.txt和kconfig文件,方便后续模块化移植到自己的项目中,目录结构如下。

在这里插入图片描述
这里也可以直接复制到keil工程中,只要你的环境具有ANSI C接口即可。

将前面准备好的源码复制到source/lua文件夹下,注意是将src中的makefilelua.cluac.c文件删除后,剩下的代码。


3、项目编译

3.1 添加main.c

我们需要在main.c中实现对lua代码的解释功能。
由于我在window环境下,我可以很轻松的打开文件,所以直接采用的文件读取的方式执行。
大家也可以直接将代码写在内存中,类似与下面这种方式:

char buff[] = "printf(123)";

我这边的代码比较复杂,还是用读取文件实现。

main.c内容如下:

#include "stdio.h"
#include <stdlib.h>

#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "string.h"

#define BUFFER_SIZE 1024*1024*1

static lua_State *L = NULL ;

int lua_deal_line(const char *str)
{
	int ret = luaL_dostring(L,str);
	if(ret != LUA_OK)
	{
		printf("%s\r\n",lua_tostring(L ,-1));
		return -1;
	}	
	return 0;
}


int main(void)
{
	L = luaL_newstate();
	luaL_openlibs(L);

    FILE *file;
    char buffer[BUFFER_SIZE] = {0};
    size_t read_size;

    // 打开文件
    file = fopen("test.lua", "rb"); // 使用"rb"模式以二进制方式读取文件
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    // 读取文件内容到缓冲区
    read_size = fread(buffer, 1, BUFFER_SIZE - 1, file); // 保留一个字节给'\0'
    if (read_size == 0 && ferror(file)) {
        perror("read file error\r\n");
        fclose(file);
        return 1;
    }

    // 添加字符串末尾的空字符
    buffer[read_size] = '\0';

    // 关闭文件
    fclose(file);


    lua_deal_line(buffer);

    lua_close(L);
    return 1;
}

创建test.lua文件放在当前路径下。

-- Lua 基本语法
print("Running basic syntax test...")
assert(true)  -- 如果代码运行到这里,没有错误发生,那么基本语法测试通过

-- Lua 数据类型
print("Running data type test...")
local num = 10          -- number
local str = "Hello"     -- string
local bool = true       -- boolean
local tbl = {1, 2, 3}   -- table
local func = function() return "I am a function" end  -- function
assert(type(num) == "number")
assert(type(str) == "string")
assert(type(bool) == "boolean")
assert(type(tbl) == "table")
assert(type(func) == "function")

-- Lua 变量
print("Running variable test...")
local localVar = "I am local"
_G.globalVar = "I am global"
assert(localVar == "I am local")
assert(_G.globalVar == "I am global")

-- Lua 循环
print("Running loop test...")
local sum = 0
for i = 1, 5 do
    sum = sum + i
end
assert(sum == 15)

sum = 0
local i = 1
while i <= 5 do
    sum = sum + i
    i = i + 1
end
assert(sum == 15)

-- Lua 流程控制
print("Running control flow test...")
local x = 10
local result
if x > 5 then
    result = "greater"
elseif x == 5 then
    result = "equal"
else
    result = "less"
end
assert(result == "greater")

-- Lua 函数
print("Running function test...")
function add(a, b)
    return a + b
end
assert(add(5, 3) == 8)

-- Lua 运算符
print("Running operator test...")
local a, b = 10, 20
assert(a + b == 30)
assert(a - b == -10)
assert(a * b == 200)
assert(a / b == 0.5)
assert(a % b == 10)
assert(a ^ 2 == 100)

-- Lua 字符串
print("Running string test...")
local s = "Lua"
assert(#s == 3)
assert(s .. " programming" == "Lua programming")

-- Lua 数组
print("Running array test...")
local arr = {10, 20, 30, 40, 50}
assert(arr[1] == 10)
assert(#arr == 5)

-- Lua 迭代器
print("Running iterator test...")
local function squareIterator(max, current)
    current = current + 1
    if current <= max then
        return current, current * current
    end
end
local results = {}
for i, n in squareIterator, 5, 0 do
    table.insert(results, n)
end
assert(#results == 5)
assert(results[1] == 1)
assert(results[5] == 25)

-- Lua table(表)
print("Running table test...")
local person = {name = "John", age = 30}
assert(person.name == "John")
assert(person.age == 30)

-- Lua 模块与包
print("Running module test...")
-- 假设有一个 module_name.lua 文件,内容如下:
-- local M = {}
-- function M.hello() return "Hello, module!" end
-- return M
-- local module = require("module_name")
-- assert(module.hello() == "Hello, module!")

-- Lua 元表(Metatable)
print("Running metatable test...")
local mt = {
    __add = function(table1, table2)
        local sum = {}
        for k, v in pairs(table1) do
            sum[k] = v + table2[k]
        end
        return sum
    end
}
local t1 = {1, 2, 3}
local t2 = {4, 5, 6}
setmetatable(t1, mt)
local t3 = t1 + t2
assert(t3[1] == 5)
assert(t3[2] == 7)
assert(t3[3] == 9)

-- Lua 协同程序(coroutine)
-- print("Running coroutine test...")
-- local co = coroutine.create(function()
--     for i = 1, 5 do
--         coroutine.yield(i)
--     end
-- end)
-- local _, first = coroutine.resume(co)
-- assert(first == 1)
-- local _, second = coroutine.resume(co)
-- assert(second == 2)

-- Lua 文件 I/O
-- print("Running file I/O test...")
-- local file = io.open("test.txt", "w")
-- file:write("Hello, file!")
-- file:close()
-- file = io.open("test.txt", "r")
-- local content = file:read("*all")
-- file:close()
-- assert(content == "Hello, file!")

-- Lua 错误处理
print("Running error handling test...")
local status, err = pcall(function()
    error("An error occurred")
end)
assert(not status)
assert(string.find(err, "An error occurred"))

-- Lua 调试(Debug)
-- print("Running debug test...")
-- local debug = require("debug")
-- local traceback
-- local function myfunc()
--     traceback = debug.traceback("Stack trace")
-- end
-- myfunc()
-- assert(string.find(traceback, "Stack trace"))

-- Lua 垃圾回收
print("Running garbage collection test...")
local tbl = {1, 2, 3}
setmetatable(tbl, {__gc = function() print("Garbage collected") end})
tbl = nil
collectgarbage()  -- 在控制台中应能看到 "Garbage collected"

-- Lua 面向对象
print("Running object-oriented test...")
local Animal = {name = "", age = 0}
function Animal:new(o, name, age)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    self.name = name or ""
    self.age = age or 0
    return o
end
function Animal:speak()
    return "I am " .. self.name .. ", " .. self.age .. " years old."
end

local dog = Animal:new(nil, "Dog", 5)
assert(dog:speak() == "I am Dog, 5 years old.")

print("All tests passed!")


3.2 Kconfig选择模块

project\pro1目录下,打开powershell,输入python .\ck_script.py cn进入到图形配置界面。

在这里插入图片描述

确保回车选中该模块,再按Q Y按键退出。


3.3 项目构建

在powershell,输入python .\ck_script.py b进行项目构建,构建完成后,对文件的编译规则就已经生成。
在这里插入图片描述


3.4 项目编译

在powershell,输入python .\ck_script.py m进行项目编译,结果如下。

在这里插入图片描述


4、运行

在powershell,输入.\lua.exe运行程序,结果如下。
在这里插入图片描述
这个Lua脚本验证了我们需要的基本语法、数据类型、变量、循环、流程控制、函数、运算符、字符串、数组、迭代器、table(表)、元表(Metatable)、错误处理、垃圾回收、面向对象等功能。


时间流逝、年龄增长,是自己的磨炼、对知识技术的应用,还有那不变的一颗对嵌入式热爱的心!

到这里就结束了!希望大家给我的文章和B站视频
点赞o( ̄▽ ̄)d、关注(o)/~、评论(▽)!

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部