梦想的彼岸花开 2024-12-03 10:05 采纳率: 77.8%
浏览 21

QT Dll界面类使用出错

使用QT创建一个界面DLL给另一个QT程序使用,调用方是VS+QT使用Layout实现的程序。在DLL中有一个导出的界面类:

// 这个宏定义是在 PictureLoadDlg_global.h 里
#if defined(DLLPICTUREEDIT_LIBRARY)
#  define DLLPICTUREEDIT_EXPORT Q_DECL_EXPORT
#else
#  define DLLPICTUREEDIT_EXPORT Q_DECL_IMPORT
#endif

// PictureLoadDlg.h
class DLLPICTUREEDIT_EXPORT PictureLoadDlg
    : public QDialog
{
    Q_OBJECT

public:
    explicit PictureLoadDlg(QWidget *parent, const QString &qstrTitle);
    ~PictureLoadDlg();

    bool loadPicture(const QString & qstrPicturePath);

signals:
    void sigClose();

private slots:
    void onSigClose();

private:
    Ui::PictureEditDlg    * ui;
};

我在调用该DLL的QT程序里的对应的类的头文件中引入了PictureLoadDlg_global.h 和 PictureLoadDlg.h,并在项目中加入了这两个文件,在类中创建该导出界面类的指针,在初始化时创建对象,并隐藏,这里都是可以的,但是我需要在指定的操作后调用导出的界面类的 loadPicture 方法,这时候编译 VS 就会报错了。

// 声明 .h
#include "PictureLoadDlg.h"

class QPictureView 
    : public QWidget
{
    Q_OBJECT

public:
    QPictureView (QWidget *parent);
    ~QPictureView ();

private slots:
    void onBtnLoadClicked();

private:
    void setupUI();
    void connectSignalsSlots();

private:
    PictureLoadDlg* m_pLoadPictureDlg;
};
// 实现 .cpp
QPictureEditPage::QPictureEditPage(QWidget *parent)
    : QWidget(parent)
{
    m_pLoadPictureDlg= new PictureLoadDlg(this, “”);
    m_pLoadPictureDlg->hide();
}

// ...

void QPictureEditPage::onBtnLoadClicked()
{
        // 获取图片路径 
        // ... qsPicPath

        if (m_pLoadPictureDlg->loadPicture(qsPicPath))
    {
        m_pLoadPictureDlg->show();
    }
}

在调用类中调用了 m_pLoadPictureDlg->loadPicture 后 VS 编译提示错误。

警告    C4273    “qt_static_metacall”: dll 链接不一致
警告    C4273    “staticMetaObject”: dll 链接不一致
错误    C2491    “::staticMetaObject”: 不允许 dllimport 静态数据成员的定义
警告    C4273    “::metaObject”: dll 链接不一致
// 还有其他的警告,都是 dll 链接不一致
  • 写回答

1条回答 默认 最新

  • 越重天 新星创作者: Java技术领域 2024-12-03 11:05
    关注

    本答案参考 多次询问 ChatGPT-3.5 后选择的最佳回答,若是满意,还请采纳,谢谢

    1. 问题分析

      • 这些编译错误和警告与DLL的导出和导入机制有关,特别是在涉及到Qt的元对象系统(Meta - Object System)时。
      • 在Qt中,元对象系统用于实现信号与槽、属性系统等功能。当在DLL中导出包含Q_OBJECT宏的类时,需要特别注意处理与元对象相关的导出和导入。
      • 这里的C4273警告表示函数在DLL和主程序之间的链接不一致,C2491错误表示不允许以dllimport方式定义静态数据成员。
    2. 解决方案

      • 正确处理元对象的导出和导入

        • 对于包含Q_OBJECT宏的类,确保在导出类时正确处理元对象相关的内容。在PictureLoadDlg.h文件中,Q_DECL_EXPORTQ_DECL_IMPORT宏用于处理DLL的导出和导入,但对于元对象相关的部分可能处理不当。
        • 一种解决方案是将元对象相关的定义放在一个单独的源文件(.cpp文件)中,并且在该源文件中只在DLL构建时定义元对象相关的内容,在主程序中不重新定义。
      • 示例修改

        • PictureLoadDlg.cpp文件中:

          • 确保在构建DLL时正确初始化元对象相关的内容。
            ```cpp
            #include "PictureLoadDlg.h"
            #include "PictureLoadDlg_global.h"

          #if defined(DLLPICTUREEDIT_LIBRARY)
          PictureLoadDlg::PictureLoadDlg(QWidget *parent, const QString &qstrTitle) :

          QDialog(parent),
          ui(new Ui::PictureEditDlg)
          

          {

          ui->setupUi(this);
          setWindowTitle(qstrTitle);
          

          }

          PictureLoadDlg::~PictureLoadDlg()
          {

          delete ui;
          

          }

          bool PictureLoadDlg::loadPicture(const QString &qstrPicturePath)
          {

          // 这里实现加载图片的逻辑
          return true;
          

          }

          void PictureLoadDlg::onSigClose()
          {

          emit sigClose();
          

          }
          #endif
          ```

        • 在主程序中,确保正确链接DLL并且不要重新定义元对象相关的内容。如果仍然有问题,可以尝试在主程序中使用Q_IMPORT_PLUGIN宏(如果适用)来正确导入插件(这里的DLL可以看作是一种插件形式)。

      • 检查项目配置

        • 确保在VS项目中,DLL项目和主程序项目的编译和链接设置正确。例如,检查预处理器定义是否正确设置了DLLPICTUREEDIT_LIBRARY宏,并且在主程序中没有错误地重新定义了DLL中应该导出的内容。
        • 检查DLL和主程序的Qt版本是否一致,不同版本的Qt可能在元对象系统的实现上有细微差异,这也可能导致链接不一致的问题。
    评论

报告相同问题?

问题事件

  • 创建了问题 12月3日