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