开发者

Distributing custom Qt plugins in OSX application bundle

开发者 https://www.devze.com 2023-02-01 06:39 出处:网络
I am building a custom application that has certain pieces of the functionality separated out into Qt plugins. This has been working quite well using QPluginLoader and qobject_cast, but up until now,

I am building a custom application that has certain pieces of the functionality separated out into Qt plugins. This has been working quite well using QPluginLoader and qobject_cast, but up until now, I have been using a hard-coded absolute path (didn't want to complicate things before I had it working!).

I'm getting close to needing to deploy the application to other machines, so I decided to try to package the plugins up into the application bundle (I'm building this primarily for OSX). It took some research, but this is what I've come up with:

MyApp.pro file:

# ...

macx {
    plugins.path = Contents/Plugins
    plugins.files = ../PluginDir-build-desktop/libMyPlugin.dylib

    QMAKE_BUNDLE_DATA += plugins
}

This gives a nice bundle structure that looks something like this:

MyApp.app
 |
 +- Contents
     |
     +- MacOS
     |   |
     |   +- MyApp
     |
     +- Plugins
     |   |
     |   +- libMyPlugin.dylib
     |
     ... other support files ...

So I add the plugin path to the library search paths:

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();
}

And then try to load the plugin, like so:

// ...

QPluginLoader pluginLoader;
pluginLoader.setFileName("libPhotoshopPlugin.dylib");
IMyPluginInterface* plugin = qobject_cast<IMyPluginInterface*>(pluginLoader.instance());

// ...

Unfortunately, plugin always comes out NULL. But when I do this:

// ...

QPluginLoader pluginLoader;
pluginLoader.setFileName("../Plugins/libPhotoshopPlugin.dylib");
IMyPluginInterface* plugin = qobject_cast<IMyPluginInterface*>(pluginLoader.instance());

// ...

I get the plugin instance just fine and everything works as it should.

Why do I have to specify the path in the filename I pass to the QPluginLoader? Shouldn't it pick that up from the QApplication library paths? Is there something I'm just doing stupidly wrong? (I'm guessing and hoping this is more likely)


Additional note:

If I change the plugins.path in the MyApp.pro file to Contents/MacOS, the libMyPlugin.dylib get output next to MyApp and everything works just fine. If this is the way I should be doing it anyway, I will gladly continue doing it.

But the Qt documentation shows the Qt plugins (qtjpeg and similar) being开发者_StackOverflow社区 deployed in the Contents/plugins directory and a similar method for adding the directory to the QApplication library path.


I store plugins in application.app/Contents/plugins and use the following code to obtain the plugins directory:

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

Now you have the correct path to the plugins dir, and can load the plugin. I also have a file qt.conf in application.app/Contents/Resources with the following contents:

[Paths]
Plugins = plugins
0

精彩评论

暂无评论...
验证码 换一张
取 消