首页 > 解决方案 > 为什么 Lua 报告“找不到指定的程序”。对于从源代码编译的这个库?

问题描述

我已经为此工作了一段时间,但我不知道出了什么问题。

在这一点上,我已经从源代码构建了所有内容,但它仍然无法正常工作。我的环境是 Windows 10 x64,我正在使用 Cygwin 的 MinGW-w64 进行编译。一切都编译为 i686(32 位)而不是 x86_64。

作为参考,我使用gcc的实例实际上是i686-w64-mingw32-gcc. liblua53.dll.alibyaml.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。我还尝试使用与 Lua 相同的错误动态链接到 libyaml.dll 进行编译。

我的 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 的错误,但我不知道缺少什么程序或它来自哪里。

我还检查了是否满足所有动态链接依赖项并且正在导出函数:

在此处输入图像描述

我该如何进一步调试呢?

标签: lua

解决方案


我最终在 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(),导出符号和正在加载的库的文件名之间存在紧密耦合。


推荐阅读