参考
工程目录
要下载 lua-5.4.2.tar.gz
bash
lib/
└──lua-5.4.2/src/*
└──src
└──── LuaEngine.h
└──── LuaEngine.cpp
└──── LuaGPIO.h
└──── LuaGPIO.cpp
└──── main.cpp
platformio.ini
源码
platformio.ini
bash
[platformio]
src_dir = .
[env:pico32]
platform = espressif32
board = pico32
framework = arduino
monitor_speed = 115200
monitor_port = COM3
upload_port = COM3
upload_speed = 921600
build_flags =
-Isrc
-Ilib/lua-5.4.2/src
-DLUA_32BITS
build_src_filter =
+<src/>
+<lib/lua-5.4.2/src/>
-<lib/lua-5.4.2/src/lua.c>
-<lib/lua-5.4.2/src/luac.c>
main.cpp
c
#include <Arduino.h>
#include "LuaEngine.h"
#include "LuaGPIO.h"
struct Motor {
int speed;
float voltage;
bool enable;
};
Motor motor;
int g_mode;
float g_vol;
LuaField motorFields[] =
{
{
"speed",
LUA_FIELD_INT,
offsetof(Motor, speed),
0
},
{
"voltage",
LUA_FIELD_FLOAT,
offsetof(Motor, voltage),
0
},
{
"enable",
LUA_FIELD_BOOL,
offsetof(Motor, enable),
0
}
};
static int showMotorInfo(lua_State *L) {
printf("g_mode=%d\r\n", g_mode);
printf("g_vol=%f\r\n", g_vol);
printf("motor.speed=%d\r\n", motor.speed);
printf("motor.voltage=%f\r\n", motor.voltage);
printf("motor.enable=%d\r\n", motor.enable);
return 0;
}
void setup() {
Serial.begin(115200);
Lua.init();
luaRegisterGPIO();
//绑定变量
LUA_BIND_INT(g_mode);
LUA_BIND_FLOAT(g_vol);
LUA_BIND_STRUCT(motor, motorFields, 3);
//绑定函数
LUA_BIND_FUNC(showMotorInfo);
Serial.println("Lua Ready");
}
String script;
void loop() {
while (Serial.available()) {
String line = Serial.readStringUntil('\n');
line.trim();
if (line == "END") {
Lua.run(script.c_str());
script = "";
} else {
script += line;
script += "\n";
}
}
}
LuaEngine.h
c
#ifndef LUA_ENGINE_H
#define LUA_ENGINE_H
extern "C" {
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
#include <stddef.h>
enum LuaFieldType
{
LUA_FIELD_INT,
LUA_FIELD_FLOAT,
LUA_FIELD_BOOL,
LUA_FIELD_STRING
};
struct LuaField
{
const char *name;
LuaFieldType type;
size_t offset;
size_t size;
};
class LuaEngine
{
public:
lua_State *L;
void init();
void run(const char *code);
// 添加普通函数
void registerFunction(const char *name,lua_CFunction func);
// 创建模块
void beginModule(const char *name);
// 添加模块函数
void addFunction(const char *name,lua_CFunction func);
// 结束模块
void endModule(const char *name);
//变量绑定
void bindInt(const char *name,int *ptr);
void bindFloat(const char *name,float *ptr);
void bindStruct(const char *name,void *ptr,const LuaField *fields,int count);
private:
static int intIndex(lua_State *L);
static int intNewIndex(lua_State *L);
static int floatIndex(lua_State *L);
static int floatNewIndex(lua_State *L);
static int boolIndex(lua_State *L);
static int boolNewIndex(lua_State *L);
static int structIndex(lua_State *L);
static int structNewIndex(lua_State *L);
};
//绑定
#define LUA_BIND_FUNC(func) Lua.registerFunction(#func, func)
#define LUA_BIND_INT(v) Lua.bindInt(#v, &v)
#define LUA_BIND_FLOAT(v) Lua.bindFloat(#v, &v)
#define LUA_BIND_STRUCT(v,fields,count) Lua.bindStruct(#v, &v, fields, count)
extern LuaEngine Lua;
#endif
LuaEngine.cpp
c
#include "LuaEngine.h"
#include <Arduino.h>
LuaEngine Lua;
// 当前模块名字
void LuaEngine::init()
{
L = luaL_newstate();
luaL_openlibs(L);
}
void LuaEngine::run(const char *code)
{
int ret = luaL_dostring(L,code);
if(ret != LUA_OK)
{
Serial.print("Lua Error:");
Serial.println(lua_tostring(L,-1));
lua_pop(L,1);
}
}
void LuaEngine::registerFunction(
const char *name,
lua_CFunction func
)
{
lua_register(L,name,func);
}
void LuaEngine::beginModule(
const char *name
)
{
lua_newtable(L);
}
void LuaEngine::addFunction(
const char *name,
lua_CFunction func
)
{
lua_pushcfunction(L,func);
lua_setfield(L,-2,name);
}
void LuaEngine::endModule(const char *name)
{
lua_setglobal(L,name);
}
//int绑定
struct LuaIntObject
{
int *ptr;
};
int LuaEngine::intIndex(lua_State *L)
{
LuaIntObject *obj =(LuaIntObject *)lua_touserdata(L,1);
const char *key =lua_tostring(L,2);
if(strcmp(key,"value")==0)
{
lua_pushinteger(L,*(obj->ptr));
return 1;
}
return 0;
}
int LuaEngine::intNewIndex(lua_State *L)
{
LuaIntObject *obj =(LuaIntObject *)lua_touserdata(L,1);
const char *key =lua_tostring(L,2);
if(strcmp(key,"value")==0)
{
*(obj->ptr)=luaL_checkinteger(L,3);
}
return 0;
}
void LuaEngine::bindInt(const char *name,int *ptr)
{
LuaIntObject *obj =(LuaIntObject *)lua_newuserdata(L,sizeof(LuaIntObject));
obj->ptr=ptr;
lua_newtable(L);
lua_pushcfunction(L,intIndex);
lua_setfield(L,-2,"__index");
lua_pushcfunction(L,intNewIndex);
lua_setfield(L,-2,"__newindex");
lua_setmetatable(L,-2);
lua_setglobal(L,name);
}
//float绑定
struct LuaFloatObject
{
float *ptr;
};
int LuaEngine::floatIndex(lua_State *L)
{
LuaFloatObject *obj =(LuaFloatObject *)lua_touserdata(L,1);
const char *key =lua_tostring(L,2);
if(strcmp(key,"value")==0)
{
lua_pushnumber(L,*(obj->ptr));
return 1;
}
return 0;
}
int LuaEngine::floatNewIndex(lua_State *L)
{
LuaFloatObject *obj =(LuaFloatObject *)lua_touserdata(L,1);
const char *key =lua_tostring(L,2);
if(strcmp(key,"value")==0)
{
*(obj->ptr) =luaL_checknumber(L,3);
}
return 0;
}
void LuaEngine::bindFloat(
const char *name,
float *ptr
)
{
LuaFloatObject *obj =(LuaFloatObject *)lua_newuserdata(L,sizeof(LuaFloatObject));
obj->ptr=ptr;
lua_newtable(L);
lua_pushcfunction(L,floatIndex);
lua_setfield(L,-2,"__index");
lua_pushcfunction(L,floatNewIndex);
lua_setfield(L,-2,"__newindex");
lua_setmetatable(L,-2);
lua_setglobal(L,name);
}
struct LuaStructObject
{
void *ptr;
const LuaField *fields;
int count;
};
static LuaField *findField(LuaStructObject *obj,const char *name)
{
for(int i=0;i<obj->count;i++)
{
if(strcmp(obj->fields[i].name,name)==0)
{
return (LuaField *)&obj->fields[i];
}
}
return NULL;
}
int LuaEngine::structIndex(lua_State *L)
{
LuaStructObject *obj =(LuaStructObject *)lua_touserdata(L,1);
const char *key =lua_tostring(L,2);
LuaField *field =findField(obj,key);
if(field==NULL)return 0;
uint8_t *addr =(uint8_t *)obj->ptr+field->offset;
switch(field->type)
{
case LUA_FIELD_INT: lua_pushinteger(L,*(int *)addr);break;
case LUA_FIELD_FLOAT: lua_pushnumber(L,*(float *)addr);break;
case LUA_FIELD_BOOL: lua_pushboolean(L,*(bool *)addr);break;
case LUA_FIELD_STRING: lua_pushstring(L,(char *)addr);break;
}
return 1;
}
int LuaEngine::structNewIndex(lua_State *L)
{
LuaStructObject *obj =(LuaStructObject *)lua_touserdata(L,1);
const char *key =lua_tostring(L,2);
LuaField *field =findField(obj,key);
if(field==NULL) return 0;
uint8_t *addr =(uint8_t *)obj->ptr+field->offset;
switch(field->type)
{
case LUA_FIELD_INT: *(int *)addr =luaL_checkinteger(L,3);break;
case LUA_FIELD_FLOAT: *(float *)addr =luaL_checknumber(L,3);break;
case LUA_FIELD_BOOL: *(bool *)addr =lua_toboolean(L,3);break;
case LUA_FIELD_STRING: strncpy((char *)addr,luaL_checkstring(L,3),field->size-1);break;
}
return 0;
}
void LuaEngine::bindStruct(const char *name,void *ptr,const LuaField *fields,int count)
{
LuaStructObject *obj;
obj =(LuaStructObject *)lua_newuserdata(L,sizeof(LuaStructObject));
obj->ptr = ptr;
obj->fields = fields;
obj->count = count;
lua_newtable(L);
lua_pushcfunction(L,structIndex);
lua_setfield(L,-2,"__index");
lua_pushcfunction(L,structNewIndex);
lua_setfield(L,-2,"__newindex");
lua_setmetatable(L,-2);
lua_setglobal(L,name);
}
LuaGPIO.h
c
#ifndef LUA_GPIO_H
#define LUA_GPIO_H
void luaRegisterGPIO();
#endif
LuaGPIO.cpp
c
#include <Arduino.h>
#include "LuaEngine.h"
#include "LuaGPIO.h"
static int lua_gpio_write(lua_State *L)
{
int pin =luaL_checkinteger(L,1);
int value =luaL_checkinteger(L,2);
pinMode(pin,OUTPUT);
digitalWrite(pin,value);
return 0;
}
static int lua_gpio_read(lua_State *L)
{
int pin =luaL_checkinteger(L,1);
pinMode(pin,INPUT);
lua_pushinteger(L,digitalRead(pin));
return 1;
}
void luaRegisterGPIO()
{
Lua.beginModule("gpio");
//gpio.write(pin, value)
Lua.addFunction("write",lua_gpio_write);
// gpio.read(pin)
Lua.addFunction("read",lua_gpio_read);
Lua.endModule("gpio");
}
测试
读写全局变量
bash
[20:47:29.752]发→◇g_mode.value=7;
g_vol.value=1.5;
motor.speed=5;
motor.voltage=5.3;
motor.enable=1;
showMotorInfo()
END
□
[20:47:29.765]收←◆g_mode=7
g_vol=1.500000
motor.speed=5
motor.voltage=5.300000
motor.enable=1
读按键
bash
[18:25:11.359]发→◇s1=gpio.read(0)
print(s1);
END
□
[18:25:11.367]收←◆1
算术运算
bash
[18:27:31.432]发→◇s1=1+2
print(s1);
END
□
[18:27:31.438]收←◆3
开灯
bash
[18:29:51.824]发→◇gpio.write(2, 1)
END
关灯
bash
[18:30:17.479]发→◇gpio.write(2, 0)
END