1.下载lua源码从官网,本文使用的是lua5.3.2,将加载到自己的工程中(不用添加lua.c和luac.c),修改luaconf.h,在其中增加宏定义#define LUA_32BITS;
2.增加文件stm32_lua_config.c,其内容如下,主要是重定义lua中文件操作的底层函数(即fopen、fread、fclose等函数要调用的函数):
#include "includes.h"
#include "LCD_Get_Res.h"
#include "ff.h"
#pragma import(__use_no_semihosting_swi)
#pragma import(_main_redirection)
const char __stdin_name[150];
const char __stdout_name[150];
const char __stderr_name[150];
typedef int FILEHANDLE;
void _sys_exit(int status)
{
while(1);
}
FILEHANDLE _sys_open(const char *name, int openmode)
{
uint32_t mode = 0;
int ret;
if(openmode == 0)
{
mode |= FA_READ;
}
if(openmode & 0x01)
{
mode |= FA_WRITE;
}
if(openmode & 0x10)
{
mode |= FA_READ | FA_WRITE;
}
if(openmode & 0x0100)
{
mode |= FA_CREATE_NEW;
}
ret = f_open(&sd_file, name, mode);
if(ret != FR_OK)
{
return 0;
}
return 1;
}
int _sys_close(FILEHANDLE fh)
{
f_close(&sd_file);
return 0;
}
int _sys_write(FILEHANDLE fh, const unsigned char *buf, unsigned len, int mode)
{
return 0;
}
int _sys_read(FILEHANDLE fh, unsigned char*buf, unsigned len, int mode)
{
int res,i = 0;
// int cou_sd;
// int size;
// int read_len = len;
// while(1)
// {
// (read_len > 512)? (size = 512) : (size = read_len);
// res = f_read(&sd_file, &buf[i], size, &cou_sd);
// if(res != FR_OK)
// {
// return EOF;
// }
// read_len -=cou_sd;
// i += cou_sd;
// if(read_len <= 0 || cou_sd == 0)
// {
// break;
// }
// }
return i;
}
//若此处重定义了fgetc则fread不会调用_sys_read
int fgetc(FILE *stream)
{
char ch = 0;
int res;
int cou_sd;
res = f_read(&sd_file, &ch, 1, &cou_sd);
if(res != FR_OK || cou_sd == 0)
{
return EOF;
}
return ch;
}
int _sys_seek(FILEHANDLE fh, long pos)
{
int res;
res = f_lseek(&sd_file, pos);
if(res != FR_OK)
{
return res;
}
return 0;
}
int _sys_istty(FILEHANDLE fh)
{
return 0;
}
int _sys_ensure(FILEHANDLE fh)
{
return 0;
}
long _sys_flen(FILEHANDLE fh)
{
return 0;
}
int _sys_tmpnam(char *name, int fileno, unsigned maxlength)
{
return 0;
}
void _ttywrch(int ch)
{
}
time_t time(time_t *t)
{
return 0;
}
int remove(const char *filename)
{
return 0;
}
char *_sys_command_string(char *cmd, int len)
{
return 0;
}
clock_t clock(void)
{
return 0;
}
int system(const char* a)
{
return 0;
}
int rename(const char *a, const char *b)
{
return 0;
}
3.在2中已经重新定义了lua中的文件操作的底层函数,但是lua中有一些函数如luaL_dofile需要从文件目录中加载.lua程序,这时我们只需实现上面的_sys_open、_sys_close、fgetc等函数再修改luaconf.h即可,在2中我已经实现文件操作一些函数的接口,修改luaconf.h:
在luaconf.h 190行左右有如下代码:
#define LUA_ROOT "/usr/local/"
#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/"
#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/"
#define LUA_PATH_DEFAULT \
LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \
"./?.lua;" "./?/init.lua"
#define LUA_CPATH_DEFAULT \
LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"
上面及时lua寻找文件的一个默认路径,因我们不存在这些路径,把它修改为我们自己的sd卡路径或其他存储设备路径即可,这里我用的是sd卡,把上面注释,修改如下:
#define LUA_PATH_DEFAULT "1:/LUALib/?.lua;"
#define LUA_CPATH_DEFAULT "1:/LUALib/?.so;"
4.上面的工作做完就可以执行在sd卡中的lua程序了,举例如下:
c程序:
static int Delay_ms(lua_State *L)
{
delay_ms(luaL_checkinteger(L, -1));
return 0;
}
static int print(lua_State *L)
{
int n=lua_gettop(L);
int i;
for (i=1; i<=n; i++)
{
if (lua_isstring(L,i))
printf("%s",lua_tostring(L,i));
else if (lua_isnil(L,i))
printf("%s","nil");
else if (lua_isboolean(L,i))
printf("%s",lua_toboolean(L,i) ? "true" : "false");
else
printf("%s:%p",luaL_typename(L,i),lua_topointer(L,i));
}
return 0;
}
static luaL_Reg LuaLib1_0[] =
{
//c接口函数都可以放在这里在lua中声明
{"Delay_ms", Delay_ms},
{"print", print},
{NULL, NULL}
};
void Lua_task(void)
{
lua_State* L;
L = luaL_newstate();
luaL_openlibs(L);
luaL_newlibtable(L, LuaLib1_0);
luaL_setfuncs(L, LuaLib1_0, 0);
//这里定义全局变量把栈顶的table赋值给LuaLib1_0,这个方式使用模块是因为无法将c模块生成动态链接库.so或.dll给LUA_CPATH_DEFAULT加载
lua_setglobal(L, "LuaLib1_0");
if (luaL_dofile(L, "1:/Lua.lua")!=0)//加载sd卡中的Lua.lua并运行
printf(lua_tostring(L,-1));
}
Lua.lua中程序:
local LuaLib1_0 = require("LuaLib1_0")
Windows = {
WINDOW1 = 0,
WINDOW2 = 1,
}
local i = 0
function window2()
i = i + 1;
if i == 256 then
i = 0
end
end
function window1()
i = i + 1;
if i == 256 then
i = 0
end
end
function window_handle()
Window_Cur = WINDOW1
if Window_Cur == Windows.WINDOW1 then
window1()
elseif Window_Cur == Windows.WINDOW2 then
window2()
end
end
function Lua_main()
while true do
window_handle()
LuaLib1_0.Delay_ms(200)
end
end
Lua_main()
这样就可以把c和lua分开,在lua中写自己的应用程序了,lua中想要什么数据由c提供。
以上内容均为自己理解,如有错误,欢迎指正