QT 自定義外掛問題 error: LNK2001: 無法解析的外部符號

永不停转發表於2024-03-29

為了重複利用已有的程式碼,我使用自定義外掛進行開發。當每個外掛獨立開發時沒有遇到問題,但是當外掛B引用了外掛A時就會在編譯時報錯 error: LNK2001: 無法解析的外部符號。
例如,先定義一個外掛ColorPicker,用於顏色選取。關鍵程式碼如下:

class QDESIGNER_WIDGET_EXPORT ColorPicker : public QWidget
{
    Q_OBJECT
    Q_PROPERTY(QColor color READ getColor WRITE setColor NOTIFY colorChanged)

public:
    explicit ColorPicker(QWidget *parent = nullptr);
    ~ColorPicker();
    QColor getColor() const;
    void setColor(QColor newColor);
Q_SIGNALS:
    void colorChanged(const QColor oldColor, const QColor newColor);
protected:
    void paintEvent(QPaintEvent *event);
    void mousePressEvent(QMouseEvent *event);
private:
    QScopedPointer<ColorPickerPrivate> d_ptr;
    Q_DECLARE_PRIVATE(ColorPicker)
};

該外掛在APP中使用正常,但是當在另外一個外掛LineProperty中使用ColorPicker 時就會報錯。

class QDESIGNER_WIDGET_EXPORT LineProperty : public QWidget
{
    Q_OBJECT
    Q_PROPERTY(Qt::PenStyle lineStyle READ lineStyle WRITE setLineStyle NOTIFY lineStyleChanged FINAL);
    Q_PROPERTY(qreal lineWidth READ lineWidth WRITE setLineWidth NOTIFY lineWidthChanged FINAL);
    Q_PROPERTY(QColor lineColor READ lineColor WRITE setLineColor NOTIFY lineColorChanged FINAL);
public:
    explicit LineProperty(QWidget *parent = nullptr);
    ~LineProperty();
    Qt::PenStyle lineStyle() const;
    void setLineStyle(Qt::PenStyle newLineStyle);
    qreal lineWidth() const;
    void setLineWidth(qreal newLineWidth);
    QColor lineColor() const;
    // 在UI中使用了ColorPicker 外掛
    void setLineColor(const QColor &newLineColor);

Q_SIGNALS:
    void linePropertyChanged(Qt::PenStyle style, QColor Color, qreal width);
    void lineStyleChanged(Qt::PenStyle style);
    void lineWidthChanged(qreal width);
    void lineColorChanged(QColor color);
protected:
    bool eventFilter(QObject *watched, QEvent *event) override;
private slots:
    void on_lineStyle_currentIndexChanged(int index);
    void on_lineColor_colorChanged(const QColor &oldColor, const QColor &newColor);
    void on_lineWidth_valueChanged(int arg1);
private:
    QScopedPointer<LinePropertyPrivate> d_ptr;
    Q_DECLARE_PRIVATE(LineProperty)
    Q_DISABLE_COPY(LineProperty)
};

網上大部分解決方法是這樣的:

如果用到訊號槽但類的定義沒有放在.h檔案中, qmake不會自動調moc, 你就需要寫#include "moc_ColorPicker.cpp"告訴qmake你有檔案需要moc

經過驗證,在LineProperty .cpp檔案末尾追加#include "moc_ColorPicker.cpp" 確實沒有再報錯。
實際上是編譯器在LINK這個環節沒有找到ColorPicker庫檔案,但是在pro檔案中已經配置LIBS += -L$$OUT_PWD/../ColorPicker/release/ -lcolorpickerplugin
問題只可能是ColorPicker.h檔案的定義問題。
ColorPicker類定義使用了QDESIGNER_WIDGET_EXPORT 宏,該宏用於將自定義元件類從外掛匯出給 Qt Designer 使用。檢視QDESIGNER_WIDGET_EXPORT 的定義如下:

#if defined(QDESIGNER_EXPORT_WIDGETS)
#  define QDESIGNER_WIDGET_EXPORT Q_DECL_EXPORT
#else
#  define QDESIGNER_WIDGET_EXPORT Q_DECL_IMPORT
#endif

LineProperty 引入ColorPicker.h檔案時QDESIGNER_WIDGET_EXPORT 仍然解釋為Q_DECL_EXPORT,從而導致ColorPicker庫檔案沒有被匯入到LineProperty ,所以LINK時會報錯。

只需要修改ColorPicker.h檔案定義,使用ColorPicker 專屬的COLOR_PICKER_EXPORT即可:

#if defined(COLOR_PICKER_LIB)
#define COLOR_PICKER_EXPORT Q_DECL_EXPORT
#else
#define COLOR_PICKER_EXPORT Q_DECL_IMPORT
#endif
class COLOR_PICKER_EXPORT ColorPicker : public QWidget
{
   ...略
};

參考:
error LNK2001: 無法解析的外部符號 Qt的moc機制
vs+qt error LNK2001: 無法解析的外部符號 “public: static struct QMetaObject 。。

相關文章