如何使用另一个 DLL 为 Qt 制作第三方插件?

Posted

技术标签:

【中文标题】如何使用另一个 DLL 为 Qt 制作第三方插件?【英文标题】:How to make a third party plugin for Qt using another DLL? 【发布时间】:2013-12-28 14:10:47 【问题描述】:

免责声明:在 Linux 上一切正常。在 Windows 上,我最近从 MinGW 更改为 MSVC2012,因为我无法正确读取 MP3(请参阅Make the WMF plugin compile with MinGW.)

在我的项目中,我有:

核心 (DLL) 另一个使用 Core 构建的 DLL 媒体播放器(Qt 应用,同时使用 DLL 和加载插件)

为了让我的项目跨平台,我还将 Windows 特定功能 (progress bar, thumbnail buttons) 提取到了第 3 方插件中。事实上,我正在开始编写一个插件管理器,它在运行时加载/卸载插件,无需重新启动应用程序,它工作正常。

但自从我切换到 MSVC 后,我无法再构建我的插件了。我正面临:

C4273: 'staticMetaObject' : 不一致的 dll 链接

我不知道如何继续...我有以下结构:

在 MainProject\Core\Interfaces 中

 class MIAMCORE_LIBRARY MediaPlayerPluginInterface : public BasicPluginInterface
 
 public:
     virtual ~MediaPlayerPluginInterface() 

     virtual void setMediaPlayer(QWeakPointer<MediaPlayer>) = 0;

     virtual bool providesView() const = 0;

     virtual void toggleViews(QWidget *) 
 ;

在 Plugin.h 中

class Minimode : public QWidget, public MediaPlayerPluginInterface

            Q_OBJECT
            Q_PLUGIN_METADATA(IID MediaPlayerPluginInterface_iid)
            Q_INTERFACES(MediaPlayerPluginInterface)

    private:
            Ui::ConfigForm _ui;

            QWeakPointer<MediaPlayer> _mediaPlayer;
            bool _startMoving;
            QPoint _pos, _globalPos;

    public:
            explicit Minimode();

            virtual ~Minimode();
            inline virtual QString name() const  return "Minimode"; 
            inline virtual QString version() const  return "1.0"; 
            inline virtual bool providesView() const  return true; 
            virtual QWidget* configPage();
            virtual void setMediaPlayer(QWeakPointer<MediaPlayer> mediaPlayer);
            virtual void toggleViews(QWidget *view);
    protected:
            /** Redefined to be able to drag this widget on screen. */
            void mouseMoveEvent(QMouseEvent *e);

            /** Redefined to be able to drag this widget on screen. */
            void mouseReleaseEvent(QMouseEvent *e);

            void mousePressEvent(QMouseEvent *e);

    private:
            void applyColorToStandardIcon(QPushButton *button);

    ;

我的插件.pro

QT      += widgets multimedia
TARGET   = $$qtLibraryTarget(mini-mode)
TEMPLATE = lib

MiamPlayerBuildDirectory = C:\dev\Miam-Player\build\MiamPlayer
DEFINES += MINIMODE_MIAMPLUGIN

CONFIG  += c++11
CONFIG(debug, debug|release) 
    target.path = $$MiamPlayerBuildDirectory\debug\plugins
    LIBS += -Ldebug -lMiamCore


INSTALLS += target

Miamcore_global.h

#ifndef MIAMCORE_GLOBAL_H
#define MIAMCORE_GLOBAL_H

#include <QtCore/QtGlobal>

#if defined(MIAMCORE_LIBRARY)
#undef MIAMCORE_LIBRARY
#define MIAMCORE_LIBRARY Q_DECL_EXPORT
#else
#define MIAMCORE_LIBRARY Q_DECL_IMPORT
#endif

#endif // MIAMCORE_GLOBAL_H

我尝试了宏 MIAMCORE_LIBRARY 和另一个 MINIMODE_PLUGIN 的各种排列,但它们都不起作用(在类和 Minimode 之间,但上面没有显示)。我应该在我的 *.pro 文件中添加特定的关键字吗?

【问题讨论】:

显示“MIAMCORE_LIBRARY”的定义,同时修正你的代码格式... 【参考方案1】:

您的宏似乎对导出和导入有误。

前提是,您不需要为插件进行静态构建,这是一个有点现实的期望,因为它们是动态库,您应该使用如下所示的宏。

还请注意,您忘记包含定义导入和导出宏的全局 Qt 标头。

Miamcore_global.h

#ifndef MIAMCORE_GLOBAL_H
#define MIAMCORE_GLOBAL_H

#include <QtCore/qglobal.h>

#ifdef MINIMODE_MIAMPLUGIN
# define MIAMCORE_LIBRARY Q_DECL_EXPORT
#else
# define MIAMCORE_LIBRARY Q_DECL_IMPORT
#endif

#endif // MIAMCORE_GLOBAL_H

然后您需要在项目文件中指定以下定义:

YourPlugin.pro

...
DEFINES += MINIMODE_MIAMPLUGIN
...

这种设计在我们使用 Qt 4 以及 Windows 和 Unix 上的 Qt 5 的插件架构中运行良好。

这里的导入是 Windows。没有这个在 Linux 上就好了,但是对于 Windows,你需要确保在构建它时导出插件,但在实际使用它时导入。

这就是为什么您需要将所需的名称传递给此构建时导出的项目文件。一旦,您的用户将使用该插件,此定义将不再存在,然后将被导入。

【讨论】:

以上是关于如何使用另一个 DLL 为 Qt 制作第三方插件?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Qt 中的另一个应用程序调用 DLL

在新机器部署Qt+mysql程序

使用 QT Creator,如何制作不需要在目标平台上安装 .dll 的 Windows 可执行文件? [复制]

连接 DLL 后出现 QT 5.4 错误

如何创建清单文件以将我的可执行文件/插件指向我的特定版本的 Qt.dll?

C++、Qt - 如何摆脱 dll 依赖项?