我已经为此工作了一段时间,我不知道出了什么问题。
至此,我已经从源代码构建了所有内容,但仍然无法正常工作。我的环境是Windows 10 x64,我正在使用Cygwin的MinGW-w64进行编译。一切都编译为i686(32位)而不是x86_64。
作为参考,我使用gcc
的实例实际上是i686-w64-mingw32-gcc
。 liblua53.dll.a
和libyaml.a
是使用Lua 5.3.5和LibYAML 0.2.2。从源代码编译的。
我建立了对象:
gcc -DVERSION=\"git-5695363\" -Ilua-5.3/src -Ilibyaml/src/include -c ext/yaml/emitter.c -o emitter.o
gcc -DVERSION=\"git-5695363\" -Ilua-5.3/src -Ilibyaml/src/include -c ext/yaml/scanner.c -o scanner.o
gcc -DVERSION=\"git-5695363\" -Ilua-5.3/src -Ilibyaml/src/include -c ext/yaml/parser.c -o parser.o
gcc -DVERSION=\"git-5695363\" -Ilua-5.3/src -Ilibyaml/src/include -c ext/yaml/yaml.c -o yaml.o
然后链接:
gcc -shared -static -s -Llua-5.3/dist -Llibyaml/dist emitter.o parser.o scanner.o yaml.o -lyaml -llua53.dll -o lyaml.dll
我将其链接为-shared
,因为输出是dll,而将其链接为-static
,因为我静态链接了libyaml.a。我还尝试通过动态链接到libyaml.dll进行编译,但出现了Lua的相同错误。
我的Lua环境是从源代码和编译器编译的:
> lua53.exe -v
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
运行一个简单的脚本可以正常工作:
> lua53.exe -e 'print("Hello!")'
Hello!
但是我无法加载库:
> lua53.exe -e 'require("lyaml")'
lua53.exe: error loading module 'lyaml' from file 'lyaml.dll':
The specified procedure could not be found.
stack traceback:
[C]: in ?
[C]: in function 'require'
(command line):1: in main chunk
[C]: in ?
我知道这是Windows的错误,但我不知道缺少什么过程或它来自哪里。
我还检查了是否满足所有动态链接依赖关系并导出了功能:
如何进一步调试?
答案 0 :(得分:1)
由于您已经在使用Dependency Walker,因此我建议使用其“配置文件”功能。您可以开始对lua53.exe
文件进行性能分析,并在执行require
命令时,分析器将向您显示所有正在加载的DLL的跟踪以及与它们相关的所有错误以及错误的详细信息在Lua消息中看不到的内容。
您也可以执行package.loadlib("lyaml.dll", "luaopen_yaml")
来确认签名有效;您应该返回一个函数,该函数在执行时将返回实际的包。
答案 1 :(得分:1)
我最终在Linux上构建了所有内容,并遇到了同样的问题,但是出现了一个更有用的错误:
$LD_LIBRARY_PATH=. ./test.lua
/bin/lua: error loading module 'lyaml' from file './lyaml.so':
./lyaml.so: undefined symbol: luaopen_lyaml
stack traceback:
[C]: in ?
[C]: in function 'require'
./test.lua:5: in main chunk
[C]: in ?
问题是Lua将“ luaopen_”符号绑定到正在加载的库的名称。因此,require("somelib")
适用于somelib.dll
,具有完全匹配的luaopen_somelib
导出符号。我可以将库构建为lyaml.dll
(以匹配库名),但是此符号已导出为luaopen_yaml
,这意味着Lua正在寻找luaopen_lyaml
(不存在)。
可能有几种解决方案:
package.loadlib()
允许。我选择了第三个解决方案。谢谢@PaulKulchenko的第三个解决方案。
由此得出的主要结论是,默认情况下,require()
,导出符号和要加载的库文件名之间紧密耦合。