我有两个使用Qt的项目。一个是用QtCreator开发的,另一个是用eclipse开发的。两者都使用相同的Qt 5.3.1库,两者都是用GCC编译的。但是,当我运行eclipse中的程序时,它会崩溃并显示消息Undefined symbol: _ZN7QString13toUtf8_helperERKS_
。
查找显示产生此错误的代码是
path.toStdString().c_str() // path is a QString
并且qstring.h中的确切位置是
#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP)
QByteArray toLatin1() const & Q_REQUIRED_RESULT
{ return toLatin1_helper(*this); }
QByteArray toLatin1() && Q_REQUIRED_RESULT
{ return toLatin1_helper_inplace(*this); }
QByteArray toUtf8() const & Q_REQUIRED_RESULT
{ return toUtf8_helper(*this); } // <- here
QByteArray toUtf8() && Q_REQUIRED_RESULT
{ return toUtf8_helper(*this); }
QByteArray toLocal8Bit() const & Q_REQUIRED_RESULT
{ return toLocal8Bit_helper(constData(), size()); }
QByteArray toLocal8Bit() && Q_REQUIRED_RESULT
{ return toLocal8Bit_helper(constData(), size()); }
将另一个项目中的QString
转换为std::string
(QtCreator中的那个)可以正常工作。可能是什么问题? eclipse中是否缺少任何编译器选项?
修改 来自这两个项目的样本文件的编译器输出是(为了便于阅读,我添加了换行符):
的Eclipse
Building file: ../src/mysource1.cpp
Invoking: GCC C++ Compiler
g++ -I"/home/username/myfolder/myproject1/src"
-I"/home/username/myfolder/myproject1/src/dialogs"
-I"/home/username/myfolder/myproject1/src/ignore"
-I/usr/local/Qt-5.3.1/include -I/usr/local/Qt-5.3.1/include/QtCore
-I/usr/local/Qt-5.3.1/include/QtGui -I/usr/local/Qt-5.3.1/include/QtWidgets
-O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -fPIE -MMD -MP
-MF"src/mysource1.d" -MT"src/mysource1.d" -o "src/mysource1.o"
"../src/mysource1.cpp"
QtCreator
g++ -c -pipe -g -Wall -W -D_REENTRANT -fPIE -DQT_WIDGETS_LIB -DQT_GUI_LIB
-DQT_CORE_LIB -I/usr/local/Qt-5.3.1/mkspecs/linux-g++ -I../myproject2
-I../myproject2/src -I../myproject2/src/data -I../myproject2/src/dialogs
-I../myproject2/src/widgets -I../myproject2/src/widgets/overlays
-I../myproject2/src/widgets/tools -I/usr/local/Qt-5.3.1/include
-I/usr/local/Qt-5.3.1/include/QtWidgets -I/usr/local/Qt-5.3.1/include/QtGui
-I/usr/local/Qt-5.3.1/include/QtCore -I. -I. -o mainwind.o
../myproject2/src/mainwind.cpp
EDIT2: 链接器输出如下:
的Eclipse
Invoking: GCC C++ Linker
g++ -L/usr/local/Qt-5.3.1/lib -o "myproject1" /*list of .o files*/
-lQt5Core -lQt5Gui -lQt5Widgets -lgit2
QtCreator
g++ -Wl,-rpath,/usr/local/Qt-5.3.1/lib -o myproject2 /*list of .o files*/
-L/usr/local/Qt-5.3.1/lib -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread
答案 0 :(得分:7)
qmake/cmake
是要走的路。但有趣的是看到链接器如何成功,然后在运行期间,我们得到一个未定义的引用(不是一个不匹配的DLL案例)。特别是因为QT github repo中toUtf8_helper
没有预处理器保护。再试一次。您是否可以添加-DQT_COMPILING_QSTRING_COMPAT_CPP
这样,我们对#else部分中的toUtf8()
采用略有不同的路径,而不是调用缺少的toUtf8_helper
方法。
原因:我认为这是因为QtCore dll是使用一组预处理程序标志构建的,这些标记在项目构建期间未匹配。然后像代码中包含的qstring.h
这样的头文件(具有内联函数)受到预处理器定义的保护,就像在toUtf8()
期间调用的toStdString()
一样,将采用不同的路径。
另请注意,建议不要像在此问题/答案中那样尝试使用qmake/cmake
个文件来构建QT项目,并且必然会在项目中造成更多问题。
答案 1 :(得分:2)
Undefined symbol: _ZN7QString13toUtf8_helperERKS_
可能由以下原因引起:
由于缺少-Wl,-rpath,/usr/local/Qt-5.3.1/lib
或LD_LIBRARY_PATH
,eclipse中的链接错误(过时的Qt库)。 Eclipse构建环境未设置为QtCreator构建环境。
您写道,您已使用ldd
检查了应用的动态链接,但您也应在eclipse中添加缺少的链接器选项-Wl,-rpath,/usr/local/Qt-5.3.1/lib
。
(另一种方法是使用LD_LIBRARY_PATH,但保持两个构建环境相同是合理的.Ldd受LD_LIBRARY_PATH的影响,就像应用程序一样.LD_LIBRARY_PATH可能无法正确导出?)
还添加编译器标志-D_REENTRANT -fPIE -DQT_WIDGETS_LIB -DQT_GUI_LIB
-DQT_CORE_LIB -I/usr/local/Qt-5.3.1/mkspecs/linux-g++
答案 2 :(得分:0)
我假设你想使用QString.toStdString()。c_str()函数将QString
转换为const char *
。这不是一种可行的方法。我不知道文件说的是什么,但我尝试使用此功能获取文件位置,这给了我一些奇怪的东西。请检查const char *是否与QString中的值相同。如果是这种情况,那么您有两种选择。
QString().toStdString()
和
在下一步中将其转换为const char*
。虽然不是
干净,但它的工作原理。 (主要问题是要进行深层复制&#39;。当你
将QString转换为std :: string,Qt直接创建临时对象
尝试读取此临时对象。使用此方法,您将创建两个
分开的对象。QString().toAscii.constData()
或QString():toUtf8().constData()
(首选)答案 3 :(得分:0)
从它的外观来看,你没有编译错误,而是链接错误。您还没有向我们展示正在使用的链接命令,您应该检查它们是否不同。要正确使用QString
方法,您必须链接到QtCore。
您使用的是哪种构建系统?小心从命令行尝试?如果你自己编译怎么办?我看了你的一些评论,你好像用ldd
检查了可执行文件,两者的输出是一样的吗?
另外,这些标志:-DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB
,它们可能会有所不同,您应该尝试在Eclipse项目中定义这些标志。
如果你没有适当的构建系统(例如,你在Eclipse项目中缺少正确的定义),Qt的库可能很复杂而无法使用,特别是如果你打算使用QtQuick或者你打算在Android中构建Android未来。我会选择 qmake 或 CMake 。如果您的计划是支持不同的IDE, CMake 是值得的,因为它可以为大多数IDE生成项目。