C++ 未定义对已定义常量的引用
C++ Undefined reference to defined constant
我在 Whosebug 上阅读了很多关于未定义引用的问题,但 none 似乎专门针对在包含的 header 中定义的常量的未定义引用。如果我在某处遗漏了有效答案,我们深表歉意。
我间接使用 MinGW 32 位 (4.9.2) 在 Qt (5.5) 中编译 C++。
其中一个包含的文件使用 #define
定义了一个常量,但是当构建项目时,编译器抱怨 .cpp 中存在未定义的引用。
奇怪的是,我已经尝试测试常量是否存在于其使用上方的行中,这没有问题。
编译器输出如下:
g++ -Wl,-subsystem,windows -mthreads -o debug\THEPROJECT.exe object_script.THEPROJECT.Debug -lmingw32 -LC:/Qt/5.5/mingw492_32/lib -lqtmaind -lshell32 -lole32 -lQt5Quickd -lQt5Guid -lQt5Qmld -lQt5Networkd -lQt5Cored
./debug\RtAudio.o: In function `ZN11RtApiWasapi13getDeviceInfoEj':
C:\Users\ME\Documents\Code\build-THEPROJECT-Desktop_Qt_5_5_1_MinGW_32bit-Debug/../THEPROJECT/thirdparty/RtAudio.cpp:4128: undefined reference to `KSDATAFORMAT_SUBTYPE_IEEE_FLOAT'
在 .cpp 的前面,有
#include <audioclient.h>
这反过来有
#include <mmreg.h>
#include <ks.h>
#include <ksmedia.h>
在 mmreg.h 内定义了常量
#define DEFINE_GUIDEX(name) EXTERN_C const CDECL GUID name
#define DEFINE_GUIDSTRUCT(g,n) DEFINE_GUIDEX(n)
#define DEFINE_GUIDNAMED(n) n
...
#define STATIC_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_IEEE_FLOAT)
DEFINE_GUIDSTRUCT("00000003-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
#define KSDATAFORMAT_SUBTYPE_IEEE_FLOAT #define DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
也许值得注意的是,在ksmedia.h中它也被定义了。通过放置(然后删除)#error 指令,我可以看出这个定义得到了 运行,尽管奇怪的是它没有抛出 'redefined' 警告。即似乎没有 #ifndef
绕过它。
#define KSDATAFORMAT_SUBTYPE_IEEE_FLOAT DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
在 .cpp 文件中使用常量
if ( deviceFormat->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
( deviceFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
( ( WAVEFORMATEXTENSIBLE* ) deviceFormat )->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT ) )
在上面的行中,我通过放置
测试了常量
#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
#pragma message __STR1__(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
并在失败前成功输出 #pragma message: KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
。这是编译器片段
g++ -c -pipe -fno-keep-inline-dllexport -g -std=c++0x -frtti -Wall -Wextra -fexceptions -mthreads -DUNICODE -D__WINDOWS_WASAPI__ -DQT_QML_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_NEEDS_QMAIN -I..\THEPROJECT -I. -I..\THEPROJECT\thirdparty -I..\THEPROJECT\thirdparty\maximilian -IC:\Qt.5\mingw492_32\include -IC:\Qt.5\mingw492_32\include\QtQuick -IC:\Qt.5\mingw492_32\include\QtGui -IC:\Qt.5\mingw492_32\include\QtANGLE -IC:\Qt.5\mingw492_32\include\QtQml -IC:\Qt.5\mingw492_32\include\QtNetwork -IC:\Qt.5\mingw492_32\include\QtCore -Idebug -IC:\Qt.5\mingw492_32\mkspecs\win32-g++ -o debug\RtAudio.o ..\THEPROJECT\thirdparty\RtAudio.cpp
..\THEPROJECT\thirdparty\RtAudio.cpp: In member function 'virtual RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo(unsigned int)':
..\THEPROJECT\thirdparty\RtAudio.cpp:4122:57: note: #pragma message: KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
这可能是一个非常愚蠢的错误,但我已经纠结了 2 天了。请问有什么线索吗?
编辑:我在 mmreg.h
中提供了更完整的参考
原来问题出在编译语句中缺少库。这些库在使用 Microsoft Visual Studio 编译时似乎是隐式的,但在使用 MinGW 编译时需要显式链接。
通过添加 -lwinmm -lksuser -luuid
问题已解决。
在 Windows 下为 WASAPI 控件编译 RtAudio 时,这些库列在 RtAudio page about compiling 上,所以我没有包含它们是一个愚蠢的错误。
作为旁注,编译器错误似乎是在将 RtAudio.cpp 编译成 RtAudio.o 而不是在链接阶段,所以我很惊讶这个明显的链接错误出现在那个阶段
感谢所有提供评论或回答的人。
我在 Whosebug 上阅读了很多关于未定义引用的问题,但 none 似乎专门针对在包含的 header 中定义的常量的未定义引用。如果我在某处遗漏了有效答案,我们深表歉意。
我间接使用 MinGW 32 位 (4.9.2) 在 Qt (5.5) 中编译 C++。
其中一个包含的文件使用 #define
定义了一个常量,但是当构建项目时,编译器抱怨 .cpp 中存在未定义的引用。
奇怪的是,我已经尝试测试常量是否存在于其使用上方的行中,这没有问题。
编译器输出如下:
g++ -Wl,-subsystem,windows -mthreads -o debug\THEPROJECT.exe object_script.THEPROJECT.Debug -lmingw32 -LC:/Qt/5.5/mingw492_32/lib -lqtmaind -lshell32 -lole32 -lQt5Quickd -lQt5Guid -lQt5Qmld -lQt5Networkd -lQt5Cored
./debug\RtAudio.o: In function `ZN11RtApiWasapi13getDeviceInfoEj':
C:\Users\ME\Documents\Code\build-THEPROJECT-Desktop_Qt_5_5_1_MinGW_32bit-Debug/../THEPROJECT/thirdparty/RtAudio.cpp:4128: undefined reference to `KSDATAFORMAT_SUBTYPE_IEEE_FLOAT'
在 .cpp 的前面,有
#include <audioclient.h>
这反过来有
#include <mmreg.h>
#include <ks.h>
#include <ksmedia.h>
在 mmreg.h 内定义了常量
#define DEFINE_GUIDEX(name) EXTERN_C const CDECL GUID name
#define DEFINE_GUIDSTRUCT(g,n) DEFINE_GUIDEX(n)
#define DEFINE_GUIDNAMED(n) n
...
#define STATIC_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_IEEE_FLOAT)
DEFINE_GUIDSTRUCT("00000003-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
#define KSDATAFORMAT_SUBTYPE_IEEE_FLOAT #define DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
也许值得注意的是,在ksmedia.h中它也被定义了。通过放置(然后删除)#error 指令,我可以看出这个定义得到了 运行,尽管奇怪的是它没有抛出 'redefined' 警告。即似乎没有 #ifndef
绕过它。
#define KSDATAFORMAT_SUBTYPE_IEEE_FLOAT DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
在 .cpp 文件中使用常量
if ( deviceFormat->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
( deviceFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
( ( WAVEFORMATEXTENSIBLE* ) deviceFormat )->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT ) )
在上面的行中,我通过放置
测试了常量#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
#pragma message __STR1__(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
并在失败前成功输出 #pragma message: KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
。这是编译器片段
g++ -c -pipe -fno-keep-inline-dllexport -g -std=c++0x -frtti -Wall -Wextra -fexceptions -mthreads -DUNICODE -D__WINDOWS_WASAPI__ -DQT_QML_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_NEEDS_QMAIN -I..\THEPROJECT -I. -I..\THEPROJECT\thirdparty -I..\THEPROJECT\thirdparty\maximilian -IC:\Qt.5\mingw492_32\include -IC:\Qt.5\mingw492_32\include\QtQuick -IC:\Qt.5\mingw492_32\include\QtGui -IC:\Qt.5\mingw492_32\include\QtANGLE -IC:\Qt.5\mingw492_32\include\QtQml -IC:\Qt.5\mingw492_32\include\QtNetwork -IC:\Qt.5\mingw492_32\include\QtCore -Idebug -IC:\Qt.5\mingw492_32\mkspecs\win32-g++ -o debug\RtAudio.o ..\THEPROJECT\thirdparty\RtAudio.cpp
..\THEPROJECT\thirdparty\RtAudio.cpp: In member function 'virtual RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo(unsigned int)':
..\THEPROJECT\thirdparty\RtAudio.cpp:4122:57: note: #pragma message: KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
这可能是一个非常愚蠢的错误,但我已经纠结了 2 天了。请问有什么线索吗?
编辑:我在 mmreg.h
中提供了更完整的参考原来问题出在编译语句中缺少库。这些库在使用 Microsoft Visual Studio 编译时似乎是隐式的,但在使用 MinGW 编译时需要显式链接。
通过添加 -lwinmm -lksuser -luuid
问题已解决。
在 Windows 下为 WASAPI 控件编译 RtAudio 时,这些库列在 RtAudio page about compiling 上,所以我没有包含它们是一个愚蠢的错误。
作为旁注,编译器错误似乎是在将 RtAudio.cpp 编译成 RtAudio.o 而不是在链接阶段,所以我很惊讶这个明显的链接错误出现在那个阶段
感谢所有提供评论或回答的人。