0

I've read through a number of questions on StackOverflow about undefined references but none seem to be specifically about an undefined reference to a constant that is defined in an included header. Apologies if I've missed a valid answer somewhere.

I am indirectly using MinGW 32bit (4.9.2) to compile C++ within Qt (5.5).

One of the included files defines a constant with #define but when the project is built the compiler complains of an undefined reference within the .cpp.

Weirdly I've tried testing if the constant exists on the line above its use and this has no problem.

Here's the compiler output:

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'

Earlier within the .cpp, there's

#include <audioclient.h>

which in turn has

#include <mmreg.h>
#include <ks.h>
#include <ksmedia.h>

Within mmreg.h the constant is defined

#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)

Maybe it's worth noting that within ksmedia.h it is also defined. By putting (and later removing) #error directives I can tell that this definition gets run, though it strangely doesn't throw a 'redefined' warning. i.e. there doesn't appear to be an #ifndef bypassing it.

#define KSDATAFORMAT_SUBTYPE_IEEE_FLOAT DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)

Within the .cpp file the constant is used

  if ( deviceFormat->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
       ( deviceFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
         ( ( WAVEFORMATEXTENSIBLE* ) deviceFormat )->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT ) )

On the line above this I have tested the constant by putting

#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
#pragma message __STR1__(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)

and this successfully outputs #pragma message: KSDATAFORMAT_SUBTYPE_IEEE_FLOAT right before failing. Here's the compiler fragment

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

This is probably a really stupid mistake but I've been headbanging for 2 days now. Any clues please?

EDIT: I've included a fuller reference to what's in mmreg.h

Paul Masri-Stone
  • 2,843
  • 3
  • 29
  • 51
  • 1
    It looks like you've only created the identifier but never defined anything by that name. You've also defined an expansion of the macro `KSDATAFORMAT_SUBTYPE_IEEE_FLOAT` to `KSDATAFORMAT_SUBTYPE_IEEE_FLOAT`, which doesn't seem very useful. – molbdnilo Feb 01 '16 at 12:18
  • #define is a preprocessor concept, which will replace one string with another. ...Subformat is being compared to that string, but that string does not name a type. Perhaps misspelled? – 2785528 Feb 01 '16 at 12:34
  • Thanks for the replies. The code I'm compiling is actually a third party library RtAudio that works and the #defines come from Windows libraries. FWIW I have compiled the exact same code in Qt 5.6 beta using the MSVC2015 compiler and it compiles and works perfectly. Although I'm hesitant to point the finger anywhere but my code or compiler settings, I'm wondering if there's an issue in MinGW 32bit 4.9.2. MSVC2015 tells me that KSDATAFORMAT_SUBTYPE_IEEE_FLOAT is being defined as a __uuidof(struct KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) and I believe the .cpp is comparing if the current system matches. – Paul Masri-Stone Feb 01 '16 at 13:15
  • Looking at some other MinGW threads, I'm beginning to wonder if the issue is related to this http://stackoverflow.com/questions/10419801/undefined-reference-to-unwind-resume-and-gxx-personality-v0#answer-22774664 Any suggestions how I could tell? And the solution (ideally without rebuilding Qt by hand myself)? I downloaded via the Qt online installer which provides prebuilt binaries. – Paul Masri-Stone Feb 01 '16 at 15:00

1 Answers1

1

It turns out that the issue was missing libraries in the compile statement. These libraries appear to be implicit when compiling with Microsoft Visual Studio but need to be linked explicitly when compiling with MinGW.

By adding -lwinmm -lksuser -luuid the problem was solved.

When compiling RtAudio for WASAPI control under Windows, these libraries are listed on the RtAudio page about compiling, so it was a silly error on my part not to have included them.

As a sidenote, the compiler error appears to be upon compiling RtAudio.cpp into RtAudio.o rather than at the linking stage, so I'm surprised that this apparent linking error showed up at that stage.

Thanks to everyone who contributed comments or answers.

Paul Masri-Stone
  • 2,843
  • 3
  • 29
  • 51