esp32集成lua

参考

lua在线运行.luatos

lua菜鸟教程.runoob

嵌入式终端AtShell的精简版.csdn

工程目录

要下载 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
相关推荐
番茄炒鸡蛋加糖20 小时前
Redis--Lua 脚本原子性与滑动窗口限流
数据库·redis·lua
星空露珠2 天前
28种颜色对应名称,
开发语言·数据库·算法·游戏·lua
吴声子夜歌10 天前
Redis 3.x——事务与Lua
redis·lua
豆瓣鸡12 天前
Redis Lua 脚本——把多条命令打包成一个原子操作
java·redis·lua
橙色阳光五月天14 天前
MATLAB函数如何打包成独立EXE
开发语言·matlab·lua
耀耀_很无聊17 天前
12_Redis Lua 脚本踩坑:为什么 tonumber(ARGV[x]) 会得到 nil?
java·redis·lua
章老师说18 天前
NGINX官方谈Lua风险:这其实是两条网关技术路线之争
运维·nginx·负载均衡·lua·openresty
会周易的程序员19 天前
使用 LuaBridge 封装 C++ 日志库 microLog 为 Lua 模块
c++·物联网·junit·lua·日志·iot·aiot
欢呼的太阳20 天前
在上一篇随笔中介绍了四种编程语言。这次再介绍四种编程语言:Fortran、Lua、Lisp 和 Logo。
junit·lua·lisp