C ++未定义的对定义常量的引用

时间:2016-02-01 12:04:21

标签: c++ mingw qt5.5 rtaudio

我已经阅读了关于未定义引用的StackOverflow上的一些问题,但似乎没有特别关于对包含头中定义的常量的未定义引用。如果我在某个地方错过了有效答案,请道歉。

我间接使用MinGW 32bit(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指令,我可以告诉该定义运行,但奇怪的是它不会抛出“重新定义”的警告。即似乎没有#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.5\mingw492_32\include -IC:\Qt\5.5\mingw492_32\include\QtQuick -IC:\Qt\5.5\mingw492_32\include\QtGui -IC:\Qt\5.5\mingw492_32\include\QtANGLE -IC:\Qt\5.5\mingw492_32\include\QtQml -IC:\Qt\5.5\mingw492_32\include\QtNetwork -IC:\Qt\5.5\mingw492_32\include\QtCore -Idebug -IC:\Qt\5.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

这可能是一个非常愚蠢的错误,但我现在已经连续两天了。有什么线索吗?

编辑:我已经包含了对mmreg.h中的内容的更全面的参考。

1 个答案:

答案 0 :(得分:1)

事实证明,问题是在编译语句中缺少库。在使用Microsoft Visual Studio进行编译时,这些库似乎是隐式的,但在使用MinGW进行编译时需要明确链接。

通过添加-lwinmm -lksuser -luuid,问题就解决了。

在Windows下为WASAPI控件编译RtAudio时,RtAudio page about compiling上列出了这些库,所以我没有包含它们是一个愚蠢的错误。

作为旁注,编译器错误似乎是在将RtAudio.cpp编译成RtAudio.o而不是在链接阶段,所以我很惊讶这个明显的链接错误出现在那个阶段。

感谢所有提出意见或答案的人。