本文目录
- 1、引言
- 2、环境准备
- 2.1 源码下载
- 2.2 项目构建环境准备
- 3、项目编译
- 3.1 添加main.c
- 3.2 Kconfig选择模块
- 3.3 项目构建
- 3.4 项目编译
- 4、运行
文章对应视频教程:
在下方喔 ~~~ 欢迎关注
点击图片或链接访问我的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
中的makefile
、lua.c
、luac.c
文件删除,待用。
2.2 项目构建环境准备
参考往期博客《Cmake+Kconfig项目构建》,搭建一个空的项目框架,用来测试Lua是否移植成功。
复制项目构建模板,修改名字,修改CMakeLists.txt和kconfig文件,方便后续模块化移植到自己的项目中,目录结构如下。
这里也可以直接复制到keil工程中,只要你的环境具有ANSI C接口即可。
将前面准备好的源码复制到source/lua
文件夹下,注意是将src
中的makefile
、lua.c
、luac.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)、错误处理、垃圾回收、面向对象等功能。
时间流逝、年龄增长,是自己的磨炼、对知识技术的应用,还有那不变的一颗对嵌入式热爱的心!
点赞o( ̄▽ ̄)d、关注(o)/~、评论(▽)!