Я создаю специальное приложение, в котором определенные части функциональности разделены на плагины Qt. Это работало довольно хорошо, используя QPluginLoader
и qobject_cast
, но до сих пор я использовал жестко запрограммированный абсолютный путь (не хотел усложнять вещи, прежде чем он заработал!).
Я близок к необходимости развертывания приложения на других машинах, поэтому я решил попробовать упаковать плагины в комплект приложений (я делаю это в основном для OSX). Потребовалось некоторое исследование, но вот что я придумал:
Файл MyApp.pro:
# ...
macx {
plugins.path = Contents/Plugins
plugins.files = ../PluginDir-build-desktop/libMyPlugin.dylib
QMAKE_BUNDLE_DATA += plugins
}
Это дает хорошую структуру пакета, которая выглядит примерно так:
MyApp.app
|
+- Contents
|
+- MacOS
| |
| +- MyApp
|
+- Plugins
| |
| +- libMyPlugin.dylib
|
... other support files ...
Поэтому я добавляю путь к плагину к путям поиска в библиотеке:
main.cpp:
// ...
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDir pluginsDir(a.applicationDirPath());
pluginsDir.cdUp();
pluginsDir.cd("Plugins");
a.addLibraryPath(pluginsDir.absolutePath());
// ...
return a.exec();
}
А затем попробуйте загрузить плагин, вот так:
// ...
QPluginLoader pluginLoader;
pluginLoader.setFileName("libPhotoshopPlugin.dylib");
IMyPluginInterface* plugin = qobject_cast<IMyPluginInterface*>(pluginLoader.instance());
// ...
К сожалению, плагин всегда выходит NULL. Но когда я делаю это:
// ...
QPluginLoader pluginLoader;
pluginLoader.setFileName("../Plugins/libPhotoshopPlugin.dylib");
IMyPluginInterface* plugin = qobject_cast<IMyPluginInterface*>(pluginLoader.instance());
// ...
Я получаю экземпляр плагина просто отлично, и все работает как надо.
Почему я должен указывать путь в имени файла, который я передаю QPluginLoader? Разве это не должно быть взято из библиотечных путей QApplication
? Есть что-то, что я просто делаю тупо неправильно? (Я предполагаю и надеюсь, что это более вероятно)
Дополнительное примечание:
Если я изменю plugins.path в файле MyApp.pro на Contents/MacOS
, libMyPlugin.dylib получит вывод рядом с MyApp, и все будет работать нормально. Если я все равно так поступлю, я с удовольствием продолжу это делать.
Но в документации Qt показаны подключаемые модули Qt (qtjpeg и аналогичные), развертываемые в каталоге Contents/plugins
, и аналогичный метод добавления каталога в путь к библиотеке QApplication
.