Delphi 11+: Указать DLL OpenSSL для Indy 10 в 64-bit
Решение конфликта DLL libssl и libeay32 в Delphi 11+ с Indy 10 для 64-битных приложений. Используйте IdOpenSSLSetLibPath() без модификации кода Indy. Разделите 32/64-bit версии по папкам, скачайте официальные binaries.
Как в 64-битном исполняемом файле Delphi 11+ указать Indy 10 загрузку конкретных DLL (libssl и libeay32) при инициализации OpenSSL? Стандартные имена 64-битных DLL конфликтуют с 32-битными версиями. Нужно ли модифицировать исходный код Indy или файл .inc для этого?
В 64-битном приложении Delphi 11+ с Indy 10 укажите путь к нужным DLL OpenSSL (libssl.dll и libeay32.dll) через функцию IdOpenSSLSetLibPath() из юнита IdSSLOpenSSLHeaders — это решает конфликт имен с 32-битными версиями без правки кода. Храните 64-битные DLL в отдельной папке, а стандартные имена оставьте как есть, чтобы избежать зависимостей. Модифицировать исходный код Indy или .inc-файлы нужно только если вы меняете сами имена DLL, что не рекомендуется.
Содержание
- Проблема конфликта DLL в Delphi 11+ с Indy 10
- Способы решения конфликта 32/64-бит DLL
- Модификация исходного кода Indy для кастомных DLL
- IdOpenSSLSetLibPath(): основной инструмент для путей
- Официальные бинарники OpenSSL для Indy
- Рекомендации по организации DLL в проекте
- Источники
- Заключение
Проблема конфликта DLL в Delphi 11+ с Indy 10
Представьте: вы разрабатываете приложение на Delphi 11+, переходите на 64-битную сборку с Indy 10 для работы с HTTPS через OpenSSL. И вдруг — краш. Причина? Стандартные имена DLL вроде libssl.dll и libeay32.dll (или ssleay32.dll в старых версиях) конфликтуют между 32- и 64-битными сборками. Windows не отличает их по битности по именам файлов, и если в одной папке лежат обе версии, загрузчик путается.
Почему это актуально именно для delphi indy и delphi openssl? Indy динамически загружает эти библиотеки при инициализации TIdSSLIOHandlerSocketOpenSSL. По умолчанию ищет их в текущей директории EXE, PATH или System32. В смешанной среде разработки (32/64 бит) или при деплое на машину с разными версиями — привет, “не найден модуль” или неверная битность. Remy Lebeau, ведущий разработчик Indy, неоднократно подчеркивал: проблема в жестко заданных именах и взаимных зависимостях DLL.
А что если проект большой, с несколькими EXE? Конфликт усугубляется. Но хорошие новости: Indy не требует OpenSSL 1.1.x (еще не полностью поддерживается), стандартные 1.0.2-binaries работают идеально.
Способы решения конфликта 32/64-бит DLL
Не хотите копаться в коде? Начните с простого. Основной подход — разделите DLL по папкам по битности. Создайте структуру вроде:
MyApp/
├── x86/ # 32-бит DLL: libssl-1_0-x86.dll, libeay32.dll
├── x64/ # 64-бит: libssl-1_0-x64.dll, libeay32.dll
└── MyApp.exe # 64-битный
Во время запуска 64-битного EXE вызовите IdOpenSSLSetLibPath('x64'). Indy загрузит оттуда нужные libeay32 delphi и ssleay32 delphi. Это работает без recompilation OpenSSL или Indy.
Альтернативы:
- Копирование в output-директорию: Передビルдом скриптом копируйте только нужные DLL. Но это хрупко при multi-target.
- Runtime проверка битности: Используйте
IsWow64Process()для автоопределения, но Indy уже имеет встроенный механизм путей.
Почему не переименовывать DLL? Lebeau предупреждает: libssl зависит от libeay32, переименование сломает загрузку, если не recompилировать весь OpenSSL. Лучше стандартные имена + пути.
Коротко: 90% случаев решается IdOpenSSLSetLibPath(). Если нет — копайтесь глубже.
Модификация исходного кода Indy для кастомных DLL
Нужно ли править исходники Indy? Только в крайних случаях. По умолчанию Indy хардкодит имена: libssl-1_0-x64.dll, libcrypto-1_0-x64.dll (для 64-bit) в IdSSLOpenSSLLoader.pas или .inc-файлах.
Чтобы изменить:
- Скачайте Indy с GitHub.
- Откройте
IdSSLOpenSSLLoader.pas. - В секции загрузки замените константы, напр.:
const
Id_OpenSSL_LibSSL64 = 'MyLibSSL64.dll';
Id_OpenSSL_LibCrypto64 = 'MyLibEAY64.dll';
- Перекомпилируйте Indy и ваш проект.
Но! В PR #529 на GitHub разработчики отмечают: это редко нужно. Если DLL стандартные, просто укажите путь. Модификация усложняет апдейты Indy. Плюс, для Delphi 11+ с 64-bit target — следите за платформой в условниках.
Когда модифицировать стоит? Если интегрируете кастомный OpenSSL или sideloading в виртуальные папки (AppContainer). Иначе — нет.
IdOpenSSLSetLibPath(): основной инструмент для путей
Это ваш лучший друг для delphi indy openssl. Функция из IdSSLOpenSSLHeaders статическая, вызывается до создания TIdSSLIOHandlerSocketOpenSSL.
Пример кода:
uses
IdSSLOpenSSLHeaders;
procedure TForm1.FormCreate(Sender: TObject);
begin
IdOpenSSLSetLibPath(ExtractFilePath(Application.ExeName) + 'x64');
// Теперь Indy загрузит DLL из этой папки
end;
Вызывайте рано, идеально в .dpr перед Application.Initialize. Поддерживает относительные/абсолютные пути. Lebeau рекомендует именно это для multi-bit сред.
Проверки: После вызова проверьте LoadOpenSSLLibrary на успех. Если DLL не найдены — Indy выдаст исключение при первом SSL-соединении.
Вопрос: а если путь меняется? Сохраните в INI или реестре, читайте на старте. Работает в сервисах, VCL/FMX.
Официальные бинарники OpenSSL для Indy
Забудьте fulgan — репозиторий пуст. Берите с IndySockets/OpenSSL-Binaries: готовые 32/64-bit для Windows, Linux.
| Битность | Файлы | Версия |
|---|---|---|
| x86 | libeay32.dll, ssleay32.dll, libssl-1_0.dll | 1.0.2u |
| x64 | libcrypto-1_0-x64.dll, libssl-1_0-x64.dll | 1.0.2u |
Скачайте, разложите по папкам. Indy 10 оптимизирован под них. Подробности в issue. Для 1.1.x — экспериментальный патч, но нестабильный.
Совет: Включите в deployment manifests или Inno Setup.
Рекомендации по организации DLL в проекте
Соберем все в систему:
- Структура папок: x86/x64 как выше.
- Автодеплой: В Post-Build Event:
xcopy "$(ProjectDir)x64*.dll" "$(OutputDir)" /Y. - Проверка на старте:
if not DirectoryExists(LibPath) then
raise Exception.Create('OpenSSL DLL не найдены!');
- Логирование:
IdOpenSSLSetLibPath()молчит об ошибках — добавьте try-except вокруг SSL-инициализации. - Для нескольких проектов: Shared folder + environment var.
Тестируйте на чистой Win10/11. Если сервис — запуск от SYSTEM, пути абсолютные. И помните: delphi 64 indy openssl dll конфликт — типичная засада, но решаемая.
Источники
- Delphi 11+ 64-bit executable - specify DLLs for Indy OpenSSL — Ответ Remy Lebeau о путях и модификации Indy: https://stackoverflow.com/questions/79878210/delphi-11-64-bit-executable-how-do-i-specify-which-dlls-to-load-when-indy-10-i
- libeay32.dll and ssleay32.dll need 32 and 64 bit simultaneously — Рекомендация по IdOpenSSLSetLibPath для разделения DLL: https://stackoverflow.com/questions/75314817/libeay32-dll-and-ssleay32-dll-need-32-and-64-bit-simultaneously
- Delphi 64-bit Indy OpenSSL libraries — Ссылки на официальные бинарники Indy OpenSSL: https://stackoverflow.com/questions/62530135/delphi-64-bit-indy-openssl-libraries
- IndySockets/Indy Pull Request #529 — Обсуждение загрузчика DLL в IdSSLOpenSSLLoader: https://github.com/IndySockets/Indy/pull/529
- IndySockets OpenSSL-Binaries — Репозиторий с 32/64-битными DLL для Indy: https://github.com/IndySockets/OpenSSL-Binaries
Заключение
В delphi indy openssl конфликты DLL решаются без хаков: используйте IdOpenSSLSetLibPath() для путей к 64-битным libssl и libeay32, храните версии отдельно. Модификация кода Indy — крайняя мера для нестандартных имен. Берите официальные binaries, автоматизируйте деплой — и ваш 64-битный проект на Delphi 11+ заработает стабильно. Это не только устранит краши, но и упростит поддержку. Удачи в разработке!
Компонент OpenSSL в Indy не позволяет указывать имена файлов DLL во время выполнения, только путь к папке, из которой они загружаются (через функцию IdOpenSSLSetLibPath() в юните IdSSLOpenSSLHeaders). Имена файлов жестко закодированы в исходном коде. Таким образом, да, вам придется модифицировать исходный код, если нужно загружать DLL с другими именами файлов. Однако вам не следует изменять имена файлов DLL вообще, вместо этого храните DLL разных разрядностей в отдельных папках. Это потому, что libssl и libeay зависят друг от друга, так что если вы не перекомпилируете сам OpenSSL для использования других имен файлов, то простое изменение имен файлов DLL все равно вызовет проблему, когда загрузчик ОС не сможет найти одну из DLL при загрузке другой.
Нельзя иметь 32-битные и 64-битные DLL в одной папке, поскольку их имена файлов конфликтуют, как вы отметили. Таким образом, поместите их в разные папки, а затем во время выполнения каждый EXE может вызвать функцию IdOpenSSLSetLibPath() из юнита IdSSLOpenSSLHeaders в Indy, чтобы указать Indy, из какой папки загружать DLL. Этот подход позволяет избежать необходимости модифицировать исходный код Indy и обеспечивает четкое разделение DLL по разрядности.
Репозиторий fulgan сейчас пуст. DLL OpenSSL для Indy недавно перемещены в новый репозиторий GitHub: https://github.com/IndySockets/OpenSSL-Binaries, который включает как 32-битные, так и 64-битные файлы. Indy 10 работает нормально со стандартными бинарными файлами OpenSSL, ПРИ УСЛОВИИ, что вы используете OpenSSL 1.0.2, а не 1.1.x. См. https://github.com/IndySockets/Indy/issues/183 для текущего состояния поддержки 1.1.x в Indy. Основной код еще не поддерживает 1.1.x, но есть экспериментальная реализация, ожидающая ревью, которую можно попробовать.
В Indy 10 используется динамическая загрузка OpenSSL. По умолчанию загружаются библиотеки libssl.dll и libcrypto.dll (в 64-битных сборках). Если вам нужно использовать другие имена DLL, то необходимо изменить список загружаемых библиотек в модуле IdSSLOpenSSLLoader (или в соответствующем .inc-файле). В PR отмечено, что можно просто скопировать 64-битные libssl.dll и libcrypto.dll в каталог проекта или указать путь к ним через параметр командной строки. При этом менять исходный код Indy не требуется, если вы используете стандартные имена. Если же нужны нестандартные имена, то потребуется изменить исходный код загрузчика.