通过命名常量访问 LUA 索引表

Posted

技术标签:

【中文标题】通过命名常量访问 LUA 索引表【英文标题】:LUA indexed table access via named constants 【发布时间】:2021-12-17 15:05:38 【问题描述】:

我在 µC 项目中使用 LUA 作为嵌入式语言,因此资源有限。为了节省一些周期和内存,我总是只使用基于索引的表访问 (table[1]) 而不是基于哈希的访问 (table.someMeaning = 1)。这样可以节省大量内存。

这种方法的明显缺点是代码中的幻数。

类似 Cpp 的预处理器将有助于将数字替换为命名常量。

有没有好的方法来实现这一点? LUA 本身的预处理器,加载脚本并编辑块然后加载它是一个变体,但我认为这首先会耗尽资源......

【问题讨论】:

你可以使用GNU M4,这是一个通用的预处理器,非常容易使用并且非常适合你的用例。另一种解决方案可能是编写一个小脚本,用连续的 sed 文本替换替换您的 TOKENS。 GNU M4的第一个例子很有趣linuxjournal.com/article/…。 我认为最简单的方法是使用 cpp for lua ;-) 这可能也是个好主意,因为您不需要其他工具。 其实也有Lua通用的预处理器,比如lua-users.org/wiki/SlightlyLessSimpleLuaPreprocessor的那个 【参考方案1】:

所以,我找到了一个简单的解决方案:在Lua 中编写自己的预处理器! 这可能是最容易做到的事情。

首先,全局定义符号:

MySymbols = 
  FIELD_1 = 1,
  FIELD_2 = 2,
  FIELD_3 = 3,

然后你编写你的preprocessing 函数,它基本上只是用它们的值替换来自MySymbols 的字符串。

function Preprocess (FilenameIn, FilenameOut)
  local FileIn     = io.open(FilenameIn, "r")
  local FileString = FileIn:read("*a") 

  for Name, Value in pairs(MySymbols) do
    FileString = FileString:gsub(Name, Value)
  end

  FileIn:close()

  local FileOut = io.open(FilenameOut, "w")
  FileOut:write(FileString)
  FileOut:close()
end

那么,如果你尝试使用这个输入文件test.txt

TEST FIELD_1
TEST FIELD_2
TEST FIELD_3

并调用以下函数:

Preprocess("test.txt", "test-out.lua")

您将获得出色的输出文件:

TEST  1
TEST  2
TEST  3

我让您乐于将它与您的脚本/工具链集成。

如果你想避免手动分配数字,你可以添加一个很棒的闭包:

function MakeCounter ()
  local Count = 0
  return function ()
    Count = Count + 1
    return Count
  end
end

NewField = MakeCounter()

MySymbols = 
  FIELD_1 = NewField(),
  FIELD_2 = NewField(),
  FIELD_3 = NewField()

【讨论】:

此解决方案将替换字符串中的名称,这可能是也可能不是您想要的。 你是对的,但是对于他的微控制器的实际使用,这个解决方案非常好。你不用在微控制器里做很多字符串管理......他只需要找到一个名字,可能是大写的,不会有任何名字冲突。 遗憾的是整个 LUA 源代码不适合在 µC 上替换的 µC

以上是关于通过命名常量访问 LUA 索引表的主要内容,如果未能解决你的问题,请参考以下文章

UE4 Unlua源码解析7 - Lua通过UE命名空间访问C++类型的实现原理

UE4 Unlua源码解析7 - Lua通过UE命名空间访问C++类型的实现原理

如何通过键删除 lua 表条目?

JVM14_Class文件结构细节魔数Class文件版本常量池访问标识(或标志)类索引|父类索引|接口索引集合字段|方法|属性表集合

Lua getmetatable() 锁定表

LUA 表结构的使用