Undefined reference to _imp__, but the right header is included
I'm rather new to Qt and do not have a lot of experience with C++. I'm trying to process data from a HID device (a joystick/gamepad) using Qt and Raw Input like described "here":http://www.codeproject.com/Articles/185522/Using-the-Raw-Input-API-to-Process-Joystick-Input (it uses Visual C++ in the example, but the idea should be the same).
When re-writing the example to Qt and trying to compile, I get an "undefined reference to `imp_'" error for each of the functions from the windows HID library.
I have included the right header (hidsdi.h).
Here I have reduced the code to almost the minimum required to tget this error:
int main(int argc, char *argv)
PHIDP_PREPARSED_DATA pPreparsedData = NULL;
QCoreApplication a(argc, argv); return a.exec();
When trying to compile this will output:
"undefined reference to `_imp__HidP_GetCaps@8'" - main.cpp:9
"error: Id returned 1 exit status" - collect2.exe
I've tried looking for a solution, but haven't found one yet. It's possible I'm missing something basic and/or obvious here.
Thank you for your time.
It's not a compiler error, but a linker error.
The header file (.h) usually only contains the function declaration, while the actual implementation is in the corresponding library (.a or .lib) or source file (.cpp). In other words: Including the header file in the source file where you call the function is one thing, but you will also need to link against the corresponding library or compile+link the corresponding source file ;-)
Thank you for the quick reply.
Does Qt only support .a (on Windows I assume) and .so (on Linux I assume)?
I have found the hid.dll and hid.lib files in the Windows Driver Development Kit. Can I link the .lib file?
I tried linking the .lib statically it to the project (using the GUI), but got an "No rule to make target [path to library]. Needed by [nameOfExe.exe]. Stop." error.
What other options do I have that I can look into? Dynamically loading the .dll?
This is nothing that concerns Qt! It concerns whatever C++ compiler/linker (MSVC, MinGW, GCC, etc) and what build system (Makefiles, Visual Studio, QtCreator, etc) you are using to create your software! Anyway, on the Windows platform "static" libraries have a .lib extension, but "import libraries":http://en.wikipedia.org/wiki/Dynamic-link_library#Import_libraries for "shared" libraries (DLL files) also have a .lib extension. You never link against DLL files directly, only against the corresponding import library (.lib) - DLL's are used at runtime! Under Linux, however, "static" libraries have a .a extension and "shared" libraries have a .so extension. Also, Linux doesn't have anything like import libraries. You link against the .so file.
Note confused yet?
MinGW also uses .a library files on the Windows platform, but that does not mean you can use Linux .a files on Windows with MinGW. You can't! ;-)
Anyway, how you link your binary against an additional library totally depends on what build system or IDE you are using. So which one you are using?
I'm using QtCreator and MinGW. How would I link the binary against the .lib? If I can't, what should I change? Compile the code with Visual Studio? Or do I reconfigure QtCreator to use a different compiler/linker?
Could I also work around it by loading the .dll using LoadLibrary? So for what I've looked into it seems it would make the code more messy.
Static linking is only possible if both pieces are compiled with the same compiler. The compile makes up names for your functions and variables etc. When two pieces of code are not compiled with the same compiler they do not find each other definitions. So, yes, compile with MS might do the trick. If you have a dll you could also use QLibrary for dynamic linking. The the compile issue is not relevant.
[quote author="Grey Fox" date="1398836084"]I'm using QtCreator and MinGW. How would I link the binary against the .lib?[/quote]
For MinGW/GCC, you are using the "-l" linker option to link against some library. So, in order to link against "libfoo.a", simply add "-lfoo" to the linker flags (LDFLAGS). Note that the "lib..." and ".a" are added automatically.
It seems Qt Creator has a wizard for this purpose:
[quote author="Grey Fox" date="1398836084"]Could I also work around it by loading the .dll using LoadLibrary?[/quote]
Maybe you could. But then you would not only load the library via LoadLibrary(), at Runtime, you'd also have to look up and call the function via GetProcAddress(), at Runtime. And most important: Using this method, you still can not call the function directly, by using the declarations from the Header file, because that would still give you the linker error! Instead, you'll now have to define the function prototype (function pointer type) yourself and call the function via the pointer that was returned by GetProcAddress().
BTW: Using the LoadLibrary+GetProcAddress is usually required only for optional dependencies, e.g. for functions that were not available on older OS versions. By using LoadLibrary+GetProcAddress you can use those functions on the newer OS versions but still make your application work on older OS. If, instead, you link against the DLL's import library, your application won't even start, if the required DLL (or the required function in that DLL) is missing.
BTW2: Qt provides the QLibrary class, which can make things a bit easier.
Thanks for the replies.
I'll try to set up Qt Creator to use MSVC compiled QT and the MSVC compiler, as I only have a hidsdi.lib, not a hidsdi.a. If that fails, I'll use QLibrary, I guess.
In any case, I'll post here on how it went or more question related to this if I get some.
If "hidsdi.lib" is the import library for your DLL file, you can probably just rename it to "libhidsdi.a" and link it with "-lhidsdi" with MinGW/GCC.
[quote author="MuldeR" date="1398883017"]If "hidsdi.lib" is the import library for your DLL file, you can probably just rename it to "libhidsdi.a" and link it with "-lhidsdi" with MinGW/GCC.[/quote]
I misspoke before, it's "hid.lib", not "hidsdi.lib", but that's not important.
I got the same "undefined reference" error when renamed the file to "libhid.a". Since the lib was compiled with MSVC, I guess I should try to set up the MSVC compiler next.
Renaming the file alone doesn't help, of course. You need to make sure that it's actually linked in! If the import library is “hid.lib”, then try renaming it to "libhid.a" and add "-lhid" to the linker options, as described above. Furthermore, you'll have to make sure that "libhid.a" is in the library search path. You can add more library directories using the "-L" linker option.
[quote author="MuldeR" date="1398885791"]Renaming the file alone doesn't help, of course. You need to make sure that it's actually linked in! If the import library is “hid.lib”, then try renaming it to "libhid.a" and add "-lhid" to the linker options, as described above.[/quote]
I did that, I apologize I did not mention that. I added the lib via the wizard in QT creator.
[quote author="Grey Fox" date="1398885881"]I added the lib via the wizard in QT creator.[/quote]
Just to be sure:
And did you make sure “-lhid” has actually been added to the linker options? It should now appear as an additional option in the final linker command...
[quote author="MuldeR" date="1398886337"][quote author="Grey Fox" date="1398885881"]I added the lib via the wizard in QT creator.[/quote]
Just to be sure:
And did you make sure “-lhid” has actually been added to the linker options? It should now appear as an additional option in the final linker command...[/quote]
The .pro file did have: @LIBS += -L$$PWD/ -lhid@
I had copied the lib to the project folder, which seems was my mistake. When I made copy of the lib and renamed it to libhid.a in it's native directory (in WindowsKit folder, where it is together with many other libs), it worked!
Thank you for pointing me the right direction.
Good it worked for you. As a final note, the option "-L$$PWD/" means it will look for libraries in the current working directory - whatever that may happen to be. So it probably found the lib file after you placed it in the Windows SDK directory, not because of the "-L$$PWD/" command, but because the Windows SDK directory already was in your library search path anyway.