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

爲了重複利用已有的代碼,我使用自定義插件進行開發。當每個插件獨立開發時沒有遇到問題,但是當插件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 。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章