在OSX应用程序包中分发自定义Qt插件

时间:2010-12-28 22:13:03

标签: macos qt plugins bundle

我正在构建一个自定义应用程序,它将某些功能部分分离到Qt插件中。使用QPluginLoaderqobject_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库路径中选择它吗?有什么我只是做愚蠢的错吗? (我猜测并希望这更有可能)


附加说明:

如果我将 MyApp.pro 文件中的 plugins.path 更改为Contents/MacOS,则在MyApp旁边的libMyPlugin.dylib获取输出,一切正常精细。如果这是我应该这样做的方式,我会很乐意继续这样做。

但是Qt documentation显示了部署在Contents/plugins目录中的Qt插件(qtjpeg和类似插件)以及用于将目录添加到QApplication库路径的类似方法。

1 个答案:

答案 0 :(得分:1)

我将插件存储在 application.app/Contents/plugins 中,并使用以下代码获取插件目录:

...    
#elif defined(Q_OS_MAC)
    QDir pluginsDir = QDir(qApp->applicationDirPath());
    pluginsDir.cdUp();
    pluginsDir.cd("plugins");
#else
...

现在你有了插件目录的正确路径,并且可以加载插件。我还在 application.app/Contents/Resources 中有一个 qt.conf 文件,其中包含以下内容:

[Paths]
Plugins = plugins