Почему Lua сообщает, что «Указанная процедура не найдена».для этой библиотеки скомпилированы из источника? - PullRequest
2 голосов
/ 16 апреля 2019

Я уже некоторое время работаю над этим и не могу понять, в чем дело.

На данный момент я построил все из исходного кода, и он все еще не работает. Моя среда - 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, но я не знаю, какая процедура отсутствует или откуда она берется.

Я также проверил, что все зависимости динамического связывания выполняются и функции экспортируются:

enter image description here

Как я могу отладить это дальше?

Ответы [ 2 ]

1 голос
/ 21 апреля 2019

Я закончил сборку всего на 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(), символом экспорта и именем файла загружаемой библиотеки.

1 голос
/ 16 апреля 2019

Поскольку вы уже используете Dependency Walker, я рекомендую использовать его функцию «Профиль».Вы можете запустить профилирование для файла lua53.exe, а когда вы выполните команду require, профилировщик покажет вам трассировку всех загружаемых библиотек DLL и любые ошибки, связанные с их загрузкой, а также подробные сведения об ошибке, которую вы не указали.см. сообщение Lua.

Вы также можете выполнить package.loadlib("lyaml.dll", "luaopen_yaml"), чтобы подтвердить, что подпись действительна;Вы должны получить обратно функцию, которая при выполнении вернет фактический пакет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...