Virtual functions causing link errors

Jaroslaw Staniek staniek at kde.org
Mon Dec 8 07:49:46 GMT 2014


Hi Patrik,
Don't you mix Qt4 (calligra libs/headers/symbols) with a Qt5 code?

On 8 December 2014 at 08:30, Patrik Gwét <patrikgwet at gmail.com> wrote:
> I am struggling with an issue while I am using external .h files in my
> project.
>
> I am using Qt5 with MSVC2012. In my main file, I am including a header
> file from a KDE application. I put some INCLUDEPATH in the .pro file
> to link correctly.
>
> The piece of code I am in trouble with is the following:
>
>> main.cpp
>> ...
>> #include <Doc.h>
>>
>> int main(int argc, char *argv[])
>> ...
>
>
> The Doc.h belongs to the KDE application source code. Including that
> file includes many other files in several directories in the KDE
> application source code.
>
> Currently, the KUndo2Stack.h and the KUndo2Stack.cpp files are the
> files I am struggling with since three days now.
>
> When I run QMake and compile, I get a link 2001 errors due to
> unresolved externals with virtual functions in the KUndo2QStack class
> defined and implemented in those files. Here is an extract:
>
>> #ifndef QT_NO_UNDOSTACK
>>
>> class KUNDO2_EXPORT KUndo2QStack : public QObject
>> {
>>     Q_OBJECT
>> //    Q_DECLARE_PRIVATE(
>
> KUndo2QStack)
>     Q_PROPERTY(bool active READ isActive WRITE setActive)
>     Q_PROPERTY(int undoLimit READ undoLimit WRITE setUndoLimit)
>
> public:
>     explicit KUndo2QStack(QObject *parent = 0);
>     virtual ~KUndo2QStack();
>     void clear();
>
>     void push(KUndo2Command *cmd);
>
>     bool canUndo() const;
>     bool canRedo() const;
>     QString undoText() const;
>     QString redoText() const;
>
>     int count() const;
>     int index() const;
>     QString actionText(int idx) const;
>     QString text(int idx) const;
>
> #ifndef QT_NO_ACTION
>     QAction *createUndoAction(QObject *parent) const;
>     QAction *createRedoAction(QObject *parent) const;
> #endif // QT_NO_ACTION
>
>     bool isActive() const;
>     bool isClean() const;
>     int cleanIndex() const;
>
>     void beginMacro(const QString &text);
>     void endMacro();
>
>     void setUndoLimit(int limit);
>     int undoLimit() const;
>
>     const KUndo2Command *command(int index) const;
>
> public Q_SLOTS:
>     void setClean();
>     virtual void setIndex(int idx);
>     virtual void undo();
>     virtual void redo();
>     void setActive(bool active = true);
>
> Q_SIGNALS:
>     void indexChanged(int idx);
>     void cleanChanged(bool clean);
>     void canUndoChanged(bool canUndo);
>     void canRedoChanged(bool canRedo);
>     void undoTextChanged(const QString &undoActionText);
>     void redoTextChanged(const QString &redoActionText);
>
> private:
>     // from QUndoStackPrivate
>     QList<KUndo2Command*> m_command_list;
>     QList<KUndo2Command*> m_macro_stack;
>     int m_index;
>     int m_clean_index;
>     KUndo2Group *m_group;
>     int m_undo_limit;
>
>     // also from QUndoStackPrivate
>     void setIndex(int idx, bool clean);
>     bool checkUndoLimit();
>
>     Q_DISABLE_COPY(KUndo2QStack)
>     friend class KUndo2Group;
> };
>
> class KUNDO2_EXPORT KUndo2Stack : public KUndo2QStack
> {
> public:
>     explicit KUndo2Stack(QObject *parent = 0);
>
>     // functions from KUndoStack
>     QAction* createRedoAction(KActionCollection* actionCollection,
> const QString& actionName = QString());
>     QAction* createUndoAction(KActionCollection* actionCollection,
> const QString& actionName = QString());
> };
>
> #endif // QT_NO_UNDOSTACK
>
> Note that the unresolved links occur only for virtual functions. Those
> functions are implemented as it follows:
>
> KUndo2QStack::~KUndo2QStack()
> {
> #ifndef QT_NO_UNDOGROUP
>     if (m_group != 0)
>         m_group->removeStack(this);
> #endif
>     clear();
> }
>
> void KUndo2QStack::undo()
> {
>     if (m_index == 0)
>         return;
>
>     if (!m_macro_stack.isEmpty()) {
>         qWarning("KUndo2QStack::undo(): cannot undo in the middle of a
> macro");
>         return;
>     }
>
>     int idx = m_index - 1;
>     m_command_list.at(idx)->undo();
>     setIndex(idx, false);
> }
>
> void KUndo2QStack::redo()
> {
>     if (m_index == m_command_list.size())
>         return;
>
>     if (!m_macro_stack.isEmpty()) {
>         qWarning("KUndo2QStack::redo(): cannot redo in the middle of a
> macro");
>         return;
>     }
>
>     m_command_list.at(m_index)->redo();
>     setIndex(m_index + 1, false);
> }
>
> void KUndo2QStack::setIndex(int idx)
> {
>     if (!m_macro_stack.isEmpty()) {
>         qWarning("KUndo2QStack::setIndex(): cannot set index in the
> middle of a macro");
>         return;
>     }
>
>     if (idx < 0)
>         idx = 0;
>     else if (idx > m_command_list.size())
>         idx = m_command_list.size();
>
>     int i = m_index;
>     while (i < idx)
>         m_command_list.at(i++)->redo();
>     while (i > idx)
>         m_command_list.at(--i)->undo();
>
>     setIndex(idx, false);
> }
>
>
> I have turned this question upside down looking for answers on the web
> and the only time I got something was when I deleted the word virtual
> off all the related functions. It cancelled the errors but I got an
> unresolved link2019 error with the destructor of the class KUndo2Stack
> (see the code above). The destructor I am talking about is the default
> one, you won't see any definition or implementation of it.
>
> I need some help to understand what is really going on and how to fix it.
>
> The exact error messages are:
>
>> main.obj:-1: error: LNK2001: unresolved external symbol "public:
>> virtual struct QMetaObject const * __cdecl
>> KUndo2QStack::metaObject(void)const "
>> (?metaObject at KUndo2QStack@@UEBAPEBUQMetaObject@@XZ)
>>
>> main.obj:-1: error: LNK2001: unresolved external symbol "public:
>> virtual void * __cdecl KUndo2QStack::qt_metacast(char const *)"
>> (?qt_metacast at KUndo2QStack@@UEAAPEAXPEBD at Z)
>>
>> main.obj:-1: error: LNK2001: unresolved external symbol "public:
>> virtual int __cdecl KUndo2QStack::qt_metacall(enum
>> QMetaObject::Call,int,void * *)"
>> (?qt_metacall at KUndo2QStack@@UEAAHW4Call at QMetaObject@@HPEAPEAX at Z)
>>
>> main.obj:-1: error: LNK2001: unresolved external symbol "public:
>> virtual void __cdecl KUndo2QStack::setIndex(int)"
>> (?setIndex at KUndo2QStack@@UEAAXH at Z)
>>
>> main.obj:-1: error: LNK2001: unresolved external symbol "public:
>> virtual void __cdecl KUndo2QStack::undo(void)"
>> (?undo at KUndo2QStack@@UEAAXXZ)
>>
>> main.obj:-1: error: LNK2001: unresolved external symbol "public:
>> virtual void __cdecl KUndo2QStack::redo(void)"
>> (?redo at KUndo2QStack@@UEAAXXZ)
>>
>> main.obj:-1: error: LNK2019: unresolved external symbol
>> "__declspec(dllimport) public: virtual __cdecl
>> KUndo2Stack::~KUndo2Stack(void)" (__imp_??1KUndo2Stack@@UEAA at XZ)
>> referenced in function "public: virtual void * __cdecl
>> KUndo2Stack::`scalar deleting destructor'(unsigned int)"
>> (??_GKUndo2Stack@@UEAAPEAXI at Z)
>>
>> debug\whitehall_0_2.exe:-1: error: LNK1120: 7 unresolved externals
>
>
> Patrik GWET
>
> _______________________________________________
> calligra-devel mailing list
> calligra-devel at kde.org
> https://mail.kde.org/mailman/listinfo/calligra-devel
>



-- 
regards, Jaroslaw Staniek

KDE:
: A world-wide network of software engineers, artists, writers, translators
: and facilitators committed to Free Software development - http://kde.org
Calligra Suite:
: A graphic art and office suite - http://calligra.org
Kexi:
: A visual database apps builder - http://calligra.org/kexi
Qt Certified Specialist:
: http://www.linkedin.com/in/jstaniek



More information about the calligra-devel mailing list