【问题标题】:Linking error: undefined reference链接错误:未定义的引用
【发布时间】:2015-01-23 15:33:19
【问题描述】:

我的编译器将这个未定义的引用报告给openWallet(..) 函数。如您所见,我已链接响应库-L/usr/lib -lkdeui -kdecore -lkparts

错误:

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

编译命令:

g++ -Wl,-O1 -Wl,-rpath-link,/usr/lib/x86_64-linux-gnu -o 密码客户端“所有 *.o 文件”-L/usr/lib -lkdecore -lkdeui -lkparts -lglib-2.0 -L/usr/X11R6/lib64 -L/usr/lib/x86_64-linux-gnu -lGL -lpthread

QtCreator 报告了同样的错误。 .pro 文件包含

LIBS += -lkdecore \
        -lkdeui \
        -lkparts

我已经安装了所有必需的库。证明:

nm -D /usr/lib/libkdeui.so | grep openWallet 的输出是:

000000000032df70 T _ZN7KWallet6Wallet10openWalletERK7QStringmNS0_8OpenTypeE

如您所见,libkdeui.so 文件中有该函数。 ^^

我已经安装了以下库:

sudo apt-get install kdelibs5-dev libkparts4

谁能告诉我我做错了什么?哪里错了?

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文件:

QT       += core 

TARGET = untitled

TEMPLATE = app

SOURCES += main.cpp

LIBS += -lkdeui -lkdecore -lkparts

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

编译:

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

【问题讨论】:

  • 你能提供一个 SSCCE 来重现这个问题吗?
  • @lpapp 我已经编辑了问题,我必须更新 kwallet.h 中的标题,因为它们是用于旧 Qt 的。 #include &lt;QtCore/QStringList&gt; -> #include &lt;QStringList&gt;
  • 您是否可以安装 32 位版本的 KWallet 库?即使您已将它们包含在 LIBS 指令中,链接也会失败。
  • 当库的排序不正确时,有时会出现问题。尝试将-lkdeui 作为最后一个命令行参数。或者至少尝试LIBS += -lkdecore -lkparts -lkdeui
  • @Noturab:非常感谢 SSCCE,我赞成你的问题。

标签: c++ linux compiler-errors g++ kde


【解决方案1】:

您的主要问题是您将 Qt 5 与 KDE Frameworks 5 混合在一起。这不会像那样发展。自己看这个:

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

修复比较简单:

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

当然,如果您转向 KF5,您还需要将包含路径更改为:

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

如果您使用 Qt 5 和 KF 5,则需要链接到该库。基本上,您使用的是 kde 4,因为 kdeui 是一个 KDE 4 库。您可以通过发出以下命令自行检查:

dpkg -S /usr/lib/libkdeui.so

简而言之,kdeui 库中的WIdunsigned long,因为这是在X11 平台上使用的,而Qt 5 混合可能会以某种方式混淆WId 中的quintptr .虽然 Qt 4 的 WId 对于不同的平台是不同的,但 Qt 5 的 WId 是quintptr,这样就更清楚了。

如果您打算将 Qt 4 与 KDE 4 一起使用,那么您的初始代码是可以的,但您需要确保在这种情况下运行 Qt 4 的 qmake 而不是 Qt 5。这可以通过使用 qtchooser 或直接运行正确的 qmake 二进制文件来实现。 qmake --version 始终是您验证正在运行的版本的朋友。在我的 Debian 和 Archlinux 上,对应的 qmake 二进制文件称为 qmake-qt4

顺便说一句,您添加widgets 模块很奇怪,但您希望删除gui,而前者取决于后者。看过项目文件中使用的widgets模块后,我的看法更加明确,此时您可能希望使用Qt 5和KF 5的组合。

这是我工作的 Qt 5 和 KF 5 测试 sn-p:

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

构建

qmake && make

要在 Ubuntu 上运行,您需要安装以下已添加到 Utopic (14.10) 的软件包:

sudo apt-get install libkf5wallet-dev

很遗憾,Trusty Tahr (14.04) 没有此功能,但如果您愿意,您可以将其向后移植。

【讨论】:

  • 所以不可能用 QT 5 和 KDE 4 构建它吧?我使用 QT4 和 KDE4 还是 QT5 和 KD5?还有一个问题,你知道是否可以在 Ubuntu 上安装它?因为我找不到与此相关的任何东西。非常感谢您的回答,我会尝试并接受您的回答。
  • 好的,我一测试就接受,下载kubuntu。感谢您的帮助
【解决方案2】:

对您从库中识别的错误名称运行 c++filt 会给出: $ c++filt _ZN7KWallet6Wallet10openWalletERK7QStringmNS0_8OpenTypeE KWallet::Wallet::openWallet(QString const&, unsigned long, KWallet::Wallet::OpenType)

注意这里第二个参数的类型(unsigned long)与你为KWallet::Wallt::openWallet提供的声明不匹配,它需要一个unsigned long long。它们不是同一类型。

编辑:示例:

#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");
}

编译到共享库:

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

请注意,符号的处理方式不同: 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

通过 C++ 过滤器管道: 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)

应用程序看到的原型的错位名称与正在链接的共享库中的错位名称不匹配。

【讨论】:

  • 这看起来不正确。如果设置了正确的链接,0 确实有效。
  • @lpapp 请看我上面更新的回复,问题不是在调用站点使用文字 0,问题是应用程序看到的原型名称不匹配从共享库中导出的符号。
  • 啊,好的,在你原来的答案中我不清楚“第二个参数”;感谢您的澄清。是的,这可能是由于合并造成的问题。 WId 在 Qt 5 中是 quintptr,而 WId 之前可能有所不同,或者其他什么。
猜你喜欢
  • 2014-04-21
  • 2013-03-15
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-04
  • 2016-06-10
相关资源
最近更新 更多