Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Lua 如何列出所有';romtable&x27;当前运行的NodeMCU固件中内置的模块?_Lua_Esp8266_Esp32_Nodemcu_Firmware - Fatal编程技术网

Lua 如何列出所有';romtable&x27;当前运行的NodeMCU固件中内置的模块?

Lua 如何列出所有';romtable&x27;当前运行的NodeMCU固件中内置的模块?,lua,esp8266,esp32,nodemcu,firmware,Lua,Esp8266,Esp32,Nodemcu,Firmware,这个问题和标题一样,差不多就是这个问题 固件当然知道它内部携带什么。以下是NodeMCU的“欢迎”信息: 我非常乐意得到逗号分隔的“模块”字符串 由于内置模块通常以其名称作为全局变量提供,这有点类似于Lua中的“如何列出所有全局变量”,正如我所期望的,每个人都在普通Lua上使用它来检查一切,包括内置模块,如math。然而,这里却不一样。我查过了 从_G中列出全局变量并不能揭示诸如tmr或uart之类的变量的存在 > =tmr romtable: 0x3f406e30 > =uart

这个问题和标题一样,差不多就是这个问题

固件当然知道它内部携带什么。以下是NodeMCU的“欢迎”信息:

我非常乐意得到逗号分隔的“模块”字符串

由于内置模块通常以其名称作为全局变量提供,这有点类似于Lua中的“如何列出所有全局变量”,正如我所期望的,每个人都在普通Lua上使用它来检查一切,包括内置模块,如
math
。然而,这里却不一样。我查过了

从_G中列出全局变量并不能揭示诸如
tmr
uart
之类的变量的存在

> =tmr
romtable: 0x3f406e30

> =uart
romtable: 0x3f40acc8

> for k,v in pairs(_G) do print(k.." : "..tostring(v)) end
module : function: 0x3ffc2fa0
require : function: 0x3ffc2fd4
pairs : function: 0x3ffba950
newproxy : function: 0x3ffc90b4
package : table: 0x3ffba8fc
_G : table: 0x3ffc29c0
_VERSION : Lua 5.1
ipairs : function: 0x3ffba888

> for k,v in pairs(package.preload) do print(k.." : "..tostring(v)) end
((nothing!))

> for k,v in pairs(package.loaded) do print(k.." : "..tostring(v)) end
package
_G
如您所见,
tmr
uart
名称是可以识别的,但是它们没有列为
\u G
的内容

有趣的是,即使是
数学
也没有列在_G中,尽管它显然是可用的:

> =math
romtable: 0x3f420ef0
> =_G.math
romtable: 0x3f420ef0
> =math.PI
nil
> =math.pi
3.1415926535898
是什么让我思考,好吧,那些
tmr
uart
呢?是的,同样的:

> =_G.tmr
romtable: 0x3f406e30
> =_G.uart
romtable: 0x3f40acc8
现在我们有了。它们没有列在_G的内容中,但它们是可用的

我不是Lua或NodeMCU方面的专家,我可能错过了一些东西,但是翻阅文档,尝试各种Lua运行时检查方法,我就是不知道是否/如何从_G中列出它们

我有一种感觉,G有两个独立的元方法,一个用于列出,一个用于访问/获取,只有后一个由固件修补,以按名称实际提供模块,而前者没有修补以列出它们,但这只是一个猜测

顺便说一句,我在ESP32上的NodeMCU上遇到了这个问题,
dev-ESP32
版本(在上可用),但在我写这篇文章时,我在ESP8288上尝试了同样的方法,结果是一样的:math、tmr、uart可以直接使用,可以通过∗G使用,但在检查∗G的内容时没有列出

作为旁注#2,经过数小时的搜索,我发现它显示了一个“NodeMCU_firmware_info.lua”,也称为“AEW_NodeMCU_info.lua”(可能是品牌问题),它实际上只包含一个名称变量对列表,并对各个模块的所有硬编码引用进行迭代,尝试每个引用的值为
nil

是的,我知道那会有用的。这正是我想要避免的。我想读出内置信息,而不必硬编码或强制输入名称


编辑:正如koyaanisqatsi所建议的,我检查了G的元表和索引,结果是
romtable
。这里有一个垃圾场:

function printtable(t) for k,v in pairs(t) do print(k.." : "..tostring(v)) end end

> printtable(getmetatable(_G))
__index : romtable: 0x3f4218b8

> printtable(getmetatable(_G)['__index'])
assert : lightfunction: 0x40156de8
collectgarbage : lightfunction: 0x40156be8
dofile : lightfunction: 0x40156bac
error : lightfunction: 0x40156b60
gcinfo : lightfunction: 0x40156b44
getfenv : lightfunction: 0x40156b14
getmetatable : lightfunction: 0x40156e8c
loadfile : lightfunction: 0x401570f4
load : lightfunction: 0x40156da4
loadstring : lightfunction: 0x40157120
next : lightfunction: 0x40156aec
pcall : lightfunction: 0x40156600
print : lightfunction: 0x40156a44
rawequal : lightfunction: 0x40156a1c
rawget : lightfunction: 0x401569f8
rawset : lightfunction: 0x4015694c
select : lightfunction: 0x401568f4
setfenv : lightfunction: 0x40156874
setmetatable : lightfunction: 0x4015677c
tonumber : lightfunction: 0x401566e0
tostring : lightfunction: 0x40156cfc
type : lightfunction: 0x401566bc
unpack : lightfunction: 0x40156638
xpcall : lightfunction: 0x401565bc
__metatable : romtable: 0x3f421b28
因此,至少一些内置函数最终出现了,但遗憾的是,这两个模块都没有出现,甚至连标准的
math
debug
都没有


编辑:我还检查了我的ESP8266的屏幕上是什么样子

启动消息:

        branch: release
        commit: 64bbf006898109b936fcc09478cbae9d099885a8
        release: 3.0-master_20200910
        release DTS: 202009090323
        SSL: false
        build type: float
        LFS: 0x40000 bytes total capacity
        modules: adc,bit,cron,encoder,file,gpio,gpio_pulse,i2c,net,node,ow,pwm2,rtctime,sigma_delta,sntp,softuart,spi,tmr,wifi
 build 2020-10-10 21:38 powered by Lua 5.1.4 on SDK 3.0.1-dev(fce080e)
和_G的元表:

printtable(getmetatable(_G)['__index'])
string : table: 0x402710e0
table : table: 0x402704cc
debug : table: 0x402719b0
coroutine : table: 0x40271694
math : table: 0x40270d04
ROM : table: 0x3ffef580
assert : function: 0x402424cc
......
......
net : table: 0x40274e9c
sntp : table: 0x40275268
bit : table: 0x40275398
adc : table: 0x40275494
gpio : table: 0x402756e4
tmr : table: 0x40275880
ow : table: 0x40275b04
softuart : table: 0x40275cd8
cron : table: 0x40275e2c
gpiopulse : table: 0x40276120
所以事实上,内置模块确实出现在这里。 现在,这是一个谜,为什么他们不在ESP32上呢?

我找到了!耶

谢谢@koyaanisqatsi.
您的建议是,G的元表中的
\uu index
是正确的,对于ESP8266的NodeMCU 3.0.0固件来说是100%完美的,而对于带有
dev-ESP32 fb12af06e7e01f699d68496b80dae481e355adb7
固件的ESP32,几乎正好是解决方案的一半

在ESP8266上,这将检索我想要查看的所有密钥(与其他条目混在一起,但这是一个次要问题):

如您所见,像
string
debug
这样的内置模块首先列出,然后是所有可选模块,比如
ow
tmr
。当然,
pairs()
不能保证订单

然后,在ESP32的固件上,这段代码只显示了一些内置函数,如
getmetatable
tonumber
,但没有显示任何模块。但是,由于
\uu index
是一个
romtable
而不是一个函数,所以它本身可以有另一个元表

这一次我得到了我想要检查的东西,它甚至被清除掉了所有其他的噪音,它只是模块

function printtable(t) for k,v in pairs(t) do print(k.." : "..tostring(v)) end end

> printtable( getmetatable(getmetatable(_G)['__index'])['__index'] )
time : romtable: 0x3f403458
ow : romtable: 0x3f403600
net : romtable: 0x3f403c60
touch : romtable: 0x3f404a08
node : romtable: 0x3f405218
spi : romtable: 0x3f405570
sigma_delta : romtable: 0x3f405638
ledc : romtable: 0x3f405978
file : romtable: 0x3f405eb0
gpio : romtable: 0x3f406290
can : romtable: 0x3f406578
i2c : romtable: 0x3f406820
wifi : romtable: 0x3f406b78
tmr : romtable: 0x3f406e30
dac : romtable: 0x3f406fc8
adc : romtable: 0x3f407118
uart : romtable: 0x3f40acc8
string : romtable: 0x3f4212a8
table : romtable: 0x3f421ef0
debug : romtable: 0x3f421cc8
coroutine : romtable: 0x3f4217d0
math : romtable: 0x3f420ef0
ROM : romtable: 0x3f422ac8
当然,如果我们有第一个,然后是第二个元表,我必须检查我们是否可以更深入——不是,它是零

> =getmetatable(getmetatable(getmetatable(_G)['__index'])['__index'])
nil
无论如何,非常感谢koyaanisqatsi和小猪


编辑:正如马塞尔在评论中指出的那样,在ESP8266上,它实际上与

> = node.info('build_config')['modules']
adc,can,dac,file,gpio,i2c,ledc,net,node,ow,sigma_delta,spi,time,tmr,touch,uart,wifi

但是,目前在ESP32上不可能实现,因为尚未实现
node.info()
。在此之前,我的双getmetatable解决方案非常有用。

metamethod\uuu索引可以保存不可见的函数-如果它是一个包含函数的表-您是否有
getmetatable()
debug.getmetatable()
-然后尝试:
对于k,v成对(getmetatable(\u G)。\uu索引)进行打印(k...tostring(v))end
@koyaanisqatsi
\u G
是它自己的元表<代码>\u G.\u索引不是一个表,因此无法在itI上迭代。我不确定是否可以从Lua访问此信息。你为什么需要这个?我需要知道某个模块是否存在的唯一原因是我想使用它。所以,如果我已经知道我想要使用什么,我可以简单地检查一下是否可用。通常,如果有人设置了它,那么{uu索引可以是一个包含全局变量的影子表容器,试试看:
setmetatable({ug,{uu index=table})
那么所有的表函数都是全局的,就像
\G.concat(arg)
@koyaanisqatsi我知道如何使用元表。但是
\u G.\u索引
是NodeMCU固件中的一项功能。因此
对(getmetatable(_G)。\u索引)
将引发错误。此外,nodemcu中没有标准的
debug
库可供参考-使用Lua 5.3.5,我意识到字符串的metamethod索引中填充了所有字符串函数-因此我查看整数,它们没有
> =getmetatable(getmetatable(getmetatable(_G)['__index'])['__index'])
nil
> = node.info('build_config')['modules']
adc,can,dac,file,gpio,i2c,ledc,net,node,ow,sigma_delta,spi,time,tmr,touch,uart,wifi