4
votes

My compiler reports this undefined reference to openWallet(..) function. As you can see I have linked responding libraries -L/usr/lib -lkdeui -kdecore -lkparts.

Error:

password.cpp:(.text+0x29): undefined reference to `KWallet::Wallet::openWallet(QString const&, unsigned long long, KWallet::Wallet::OpenType)'

Compile command:

g++ -Wl,-O1 -Wl,-rpath-link,/usr/lib/x86_64-linux-gnu -o password_client "ALL *.o FILES" -L/usr/lib -lkdecore -lkdeui -lkparts -lglib-2.0 -L/usr/X11R6/lib64 -L/usr/lib/x86_64-linux-gnu -lGL -lpthread

Same error is reported by QtCreator. .pro file contains

LIBS += -lkdecore \
        -lkdeui \
        -lkparts

I have all that required libs installed. Proof:

Output of nm -D /usr/lib/libkdeui.so | grep openWallet is :

000000000032df70 T _ZN7KWallet6Wallet10openWalletERK7QStringmNS0_8OpenTypeE

As you can see there is that funcion in libkdeui.so file. ^^

I have installed libraries with:

sudo apt-get install kdelibs5-dev libkparts4

Can someone tell me what am I doing wrong? Where is the mistake?

SSCCE:

#include <QCoreApplication>
#include <KWallet/Wallet>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    using namespace KWallet;

    Wallet* wallet = Wallet::openWallet(Wallet::LocalWallet(), 0);
    return a.exec();
}

.pro file:

QT       += core 

TARGET = untitled

TEMPLATE = app

SOURCES += main.cpp

LIBS += -lkdeui -lkdecore -lkparts

INCLUDEPATH += /usr/include/KDE \
               /usr/include/KDE/KWallet

Compilation:

g++ -c -m64 -pipe -O2 -Wall -W -D_REENTRANT -fPIE -DQT_NO_DEBUG -DQT_DBUS_LIB -DQT_CORE_LIB -I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++-64 -I. -I/usr/include/KDE -I/usr/include/KDE/KWallet -ITDIR/include/QtGui -ITDIR/include -I. -o main.o main.cpp

g++ -m64 -Wl,-O1 -o untitled main.o -L/usr/lib -L/usr/X11R6/lib64 -lkdeui -lkdecore -lkparts -L/usr/lib/x86_64-linux-gnu -lGL -lpthread

2
Can you provide an SSCCE reproducing the issue?lpapp
@lpapp I've edited the question, I had to update headers in kwallet.h because they were for old Qt. #include <QtCore/QStringList> -> #include <QStringList> etc.user1824918
Is it possible you have the 32 bit versions of the KWallet library installed? This will fail linking even though you've included them in the LIBS directive.Tyler Jandreau
sometimes problem occurs when ordering of libraries is improper. Try to put -lkdeui as last command line parameter. Or at least try to LIBS += -lkdecore -lkparts -lkdeuitriclosan
@Noturab: many thanks for the SSCCE, I upvoted your question.lpapp

2 Answers

1
votes

Your main issue is that you are mixing up Qt 5 with KDE Frameworks 5. That is not going to fly like that. See this yourself:

KDE 4 related linkage: -lkdeui -lkdecore -lkparts
Qt 5 related linkage: -lQt5Widgets -lQt5Gui -lQt5Core

The fix is relatively simple:

LIBS += -lkdecore -lkparts -lKF5Wallet
                           ^^^^^^^^^^^

Naturally, if you move onto KF5, you will also need to change the includepaths to:

INCLUDEPATH += \
    ...
    /usr/include/KF5 \
    /usr/include/KF5/KWallet/ \
    ...

You will need to link against that library should you be using Qt 5 and KF 5. Basically, you were using kde 4, as kdeui is a KDE 4 library. You can check that yourself by issuing the following command:

dpkg -S /usr/lib/libkdeui.so

In short, the WId was unsigned long in the kdeui library since that is what was used for this on X11 platforms, whereas the Qt 5 mix may have confused the quintptr in for the WId, somehow. While Qt 4's WId was different for different platforms, Qt 5's WId is quintptr, so that is clearer.

If you plan to use Qt 4 with KDE 4, your initial code is fine, but you need to make sure that you run Qt 4's qmake in that case as opposed to Qt 5's. This can be either by using qtchooser or running the proper qmake binary directly. qmake --version is always your friend to verify the version that is being run. On my Debian and Archlinux, the corresponding qmake binary is called qmake-qt4.

On a side note, it is strange that you add the widgets module, but you wish to remove the gui, whereas the former depends on the latter. Having seen the widgets module used in the project file, my opinion is even more clear that you probably wish to use the Qt 5 and KF 5 combination at this point in time.

Here is my working Qt 5 and KF 5 test snippet:

main.cpp

#include <QCoreApplication>
#include <KWallet>

using KWallet::Wallet;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    KWallet::Wallet* wallet = Wallet::openWallet(Wallet::LocalWallet(), 0);
    return a.exec();
}

main.pro

TARGET = kwallet-test
TEMPLATE = app
SOURCES += main.cpp
LIBS += -lKF5Wallet
INCLUDEPATH += /usr/include/KF5/KWallet

Build

qmake && make

For this to work on Ubuntu, you will need to install the following package which was added to Utopic (14.10):

sudo apt-get install libkf5wallet-dev

Unfortunately, Trusty Tahr (14.04) did not have this available, but you might be able to backport it if you wish to.

1
votes

Running c++filt over the mangled name you identified from the library gives: $ c++filt _ZN7KWallet6Wallet10openWalletERK7QStringmNS0_8OpenTypeE KWallet::Wallet::openWallet(QString const&, unsigned long, KWallet::Wallet::OpenType)

Note that the type of the second parameter here (unsigned long) does not match the declaration you provided for KWallet::Wallt::openWallet, which expects an unsigned long long. These are not the same type.

EDIT: Example:

#include <cstdio>

class QString;

namespace KWallet {
class  __attribute__((__visibility__("default"))) Wallet {
public:
    enum OpenType {
       whatever
    };
    void openWallet(QString const&, unsigned long, OpenType);


    void openWallet(QString const&, unsigned long long, OpenType);
};
}

void KWallet::Wallet::openWallet(QString const&, unsigned long, OpenType) {
   printf("unsigned long\n");
}

void KWallet::Wallet::openWallet(QString const&, unsigned long long, OpenType) {
    printf("unsigned long long\n");
}

Compile to a shared library:

g++ ./madeup.cpp -shared -fPIC

Note that the symbols mangle differently: nm --dynamic --defined-only ./a.out 0000000000002020 A __bss_start 0000000000002020 A _edata 0000000000002021 A _end 00000000000007d4 T _fini 0000000000000638 T _init 0000000000000786 T _ZN7KWallet6Wallet10openWalletERK7QStringmNS0_8OpenTypeE 00000000000007ac T _ZN7KWallet6Wallet10openWalletERK7QStringyNS0_8OpenTypeE

Piping through C++ filt: m --dynamic --defined-only ./a.out | c++filt 0000000000002020 A __bss_start 0000000000002020 A _edata 0000000000002021 A _end 00000000000007d4 T _fini 0000000000000638 T _init 0000000000000786 T KWallet::Wallet::openWallet(QString const&, unsigned long, KWallet::Wallet::OpenType) 00000000000007ac T KWallet::Wallet::openWallet(QString const&, unsigned long long, KWallet::Wallet::OpenType)

The mangled name of the prototype seen by the application doesn't match the mangled name in the shared library that is being linked.