Я работаю над программой, которая динамически загружает библиотеки DLL как плагины. Я компилирую программу с использованием Microsoft Visual C ++ 2008. Тем не менее, давайте предположим, что любая версия Visual C ++, с которой работает Qt, должна поддерживаться. Структура каталога программы следующая:
| plugins/
| plugin1.dll
| plugin2.dll
| QtCore4.dll
| QtGui4.dll
| program.exe
program.exe
обнаруживает все DLL-файлы плагинов, выполняет LoadLibrary () над ними и вызывает определенную функцию подписи, чтобы выяснить, действительно ли это плагин или нет. Это хорошо работает на компьютерах, на которых установлен vcredist для MSVC90. Естественно, чтобы программа работала на всех компьютерах, мне нужно распространить ее вместе с файлами msvc * .dll и с соответствующим файлом манифеста. Библиотеки Qt также требуют, чтобы редист был запущен.
Теперь я настроил cmake для автоматического копирования соответствующих DLL-файлов перенаправления и манифеста в зависимости от выбранной версии Visual Studio. Для простоты давайте продолжим предполагать, что я работаю с MSVC90. Когда redist копируется в каталог программы, макет выглядит следующим образом:
| plugins/
| plugin1.dll
| plugin2.dll
| QtCore4.dll
| QtGui4.dll
| msvcm90.dll
| msvcp90.dll
| msvcr90.dll
| Microsoft.VC90.CRT.manifest (I'm also aware that this file is bugged in VS2008)
| program.exe
Что касается ошибки в файле манифеста: http://www.cmake.org/pipermail/cmake/2008-September/023822.html
Программа с этим макетом теперь работает на компьютерах, на которых не установлен redist, но плагины не загружаются. Чтобы загрузить плагины, мне нужно выполнить одно из следующих действий:
plugins/
каталог. Удалите все ссылки на файлы msvc * .dll из файла манифеста. Это работает, но это нехорошо, потому что мне придется поддерживать разные версии отредактированных файлов манифеста в зависимости от версии используемого MSVC. Кроме того, я понятия не имею, не нарушит ли это Visual Studio, кроме 2008 года.plugins/
каталог. Это не требует каких-либо изменений в файле манифеста, но теперь program.exe
тупо пытается загрузить файлы msvc * .dll, думая, что они плагины. Естественно, это изящно терпит неудачу, поэтому не причинит большого вреда. Другим недостатком является то, что размер пакета программы увеличивается более чем на 1 МБ. Обе эти проблемы — то, с чем я могу жить.program.exe
являются / MD.Какое лучшее решение? Какое правильное решение? Если существует более одного правильного решения, то какой метод является лучшим? Я первый человек, который когда-либо пытался сделать это?
Пока вопрос остается без ответа, я решил пойти по пути, который вызывает наименьшую головную боль. До сих пор я использовал решение № 1 и решил придерживаться его. Если CMake обнаружит, что пользователь использует версию MSVC, отличную от 2008, он отобразит предупреждающее сообщение о том, что автоматическая упаковка не полностью поддерживается.
Вы можете предоставить полные пути к файлам «LoadLibrary», чтобы вы могли загрузить свои плагины с их путями. Я использовал этот точный макет для загрузки нескольких версий одной и той же библиотеки из подкаталогов текущей библиотеки DLL в Visual Studio 2005.
Сначала вам нужно получить текущий путь текущей библиотеки DLL, используя:
static LPSTR strDLLPath1 = new TCHAR[_MAX_PATH+1];
::GetModuleFileName((HINSTANCE)&__ImageBase, strDLLPath1, _MAX_PATH);
Хотя, если ваш program.exe уже обнаруживает эти файлы плагинов, я предполагаю, что у вас уже есть доступ к их полным путям.
Если ваша целевая ОС имеет _WIN32_WINNT> = 0x0502, вы можете использовать функцию
SetDllDirectory()
перед загрузкой плагинов.
Укажите путь к основной папке программы.
Вызов переопределяет порядок загрузки системы:
Таким образом, вы можете вызвать функцию после запуска приложения. Это безопасно во всех случаях. Удачи!
Вы можете создать жесткие ссылки на библиотеки VC с помощью функции CreateHardLink () в процессе установки. При использовании метода (1), который вы описали, могут возникнуть проблемы с разными копиями VCRT-библиотек. Жесткие ссылки или SetDllDirectory () кажется лучшим решением.
Не смешивайте в одном процессе статическую и динамическую ссылку на MSVCRT — это ВСЕГДА создает проблемы!