[solved] Using a function in .obj library
-
wrote on 25 Sept 2012, 10:25 last edited by
Hello
I need to use a third party function inside a precompiled OBJ library, and I am new to C++ programming.
In my project file.pro I wrote:@win32:LIBS += c:/UTILLIB.OBJ@
and I have added the relative .H file:
@#include <windows.h>
#include <qglobal.h>extern "C" {
VOID FAR PASCAL UTIL(char char1,
qint16 int1,
qint16 int2,
qint16 int3,
qint16 int4,
qint16 int5,
qint16 int6,
qint16 int7);
}@I'm trying to use the function in my project as follow:
@char char1;
qint16 int1 = 1;
qint16 int2 = 0;
qint16 int3 = 0;
qint16 int4 = 0;
qint16 int5 = 0;
qint16 int6 = 0;
qint16 int7 = 0;
UTIL(char1, int1, int2, int3, int4, int5, int6, int7);@But I have this error:
@mainwindow.cpp:64: error: undefined reference to `UTIL@32'@
Where I am wrong?
-
wrote on 25 Sept 2012, 10:31 last edited by
try without extern "C"
-
wrote on 25 Sept 2012, 10:44 last edited by
Is the symbolic name of the function in the .obj file really "...@32" ???
AFAIK the MSVC compiler (not sure about MinGW) will add such suffix to the function's symbolic name when certain calling conventions are used. Even when "Name mangling" is avoided by using "extern C". There is a workaround for this when create DLL files: Use an .def file instead of "__declspec(dllexport)". But in this case, I think, only re-compiling the .obj file with the same compiler could help...
-
wrote on 25 Sept 2012, 12:51 last edited by
[quote author="AcerExtensa" date="1348569073"]try without extern "C"[/quote]
Doesn't solve, little change of displayed error:
@mainwindow.cpp:64: error: undefined reference to `UTIL(char, short, short, short, short, short, short, short)@32'@
-
wrote on 25 Sept 2012, 12:55 last edited by
[quote author="MuldeR" date="1348569883"]Is the symbolic name of the function in the .obj file really "...@32" ???
AFAIK the MSVC compiler (not sure about MinGW) will add such suffix to the function's symbolic name when certain calling conventions are used. Even when "Name mangling" is avoided by using "extern C". There is a workaround for this when create DLL files: Use an .def file instead of "__declspec(dllexport)". But in this case, I think, only re-compiling the .obj file with the same compiler could help...[/quote]
I have not sources, I can't recompile :-(
I have a doubt, does QT accept .OBJ as library? If I right-click on project name and I choose "Add library..." it accepts only .lib files. I am on Win XP32 SP3.
-
wrote on 25 Sept 2012, 13:17 last edited by
can you post this .obj file? Have no idea about mingw and .obj files, but MS VS does!
-
wrote on 25 Sept 2012, 13:55 last edited by
[quote author="Fodox" date="1348577758"]I have a doubt, does QT accept .OBJ as library? If I right-click on project name and I choose "Add library..." it accepts only .lib files. I am on Win XP32 SP3.[/quote]
That has nothing to do with Qt. It has to do with your C++ compiler/linker and maybe with the IDE you use! Qt has support for loading dynamic libraries (DLL files, on the Windows) at runtime, the QLibrary class. But static libraries (or single Object code files) are something completely different. They are not loaded at runtime. They are linked into the EXE file by your Linker at the moment when your application is built. Qt cannot help there...
-
wrote on 25 Sept 2012, 14:24 last edited by
[quote author="AcerExtensa" date="1348579021"]can you post this .obj file? Have no idea about mingw and .obj files, but MS VS does![/quote]
Well, I don't know. The library is used to check, read and write the hardware keys for software protection. I have to ask. Thank you anyway!
-
wrote on 25 Sept 2012, 14:27 last edited by
[quote author="MuldeR" date="1348581302"]That has nothing to do with Qt. It has to do with your C++ compiler/linker and maybe with the IDE you use! Qt has support for loading dynamic libraries (DLL files, on the Windows) at runtime, the QLibrary class. But static libraries (or single Object code files) are something completely different. They are not loaded at runtime. They are linked into the EXE file by your Linker at the moment when your application is built. Qt cannot help there...[/quote]
Thank you for explaination. I am a Delphi developer, I am doing my best to learn about C++ world as quick as possible.
-
wrote on 25 Sept 2012, 15:11 last edited by
Well, it's not much different with Delphi. You source code (.pas) files are compiled to object code (.dcu) files and finally linked together to an executable (.exe) file. With C++ you have .cpp and .obj files instead, but the idea is the same. I'm not sure Delphi has an equivalent for C++ static libraries though. But static libraries in C++ really are just archives (similar to a TAR or ZIP file) containing object code (.obj) files. You may think of a .lib (Windows) or .a (Linux) file as a collection of .obj files that have been bundled for convenience. Linking against dynamic libraries .dll (Windows) or .so (Linux) is a bit different: While in Delphi you simply declare the function as "external" and write down the DLL's name, in C++ the header file (.h) is not sufficient. You also need an import library! Those have a .lib (Windows) or .a (Linux) extension, just like static libraries, but in fact they are only "stubs" for the actual DLL call. And of course in both worlds, C++ and Delphi, you may load dynamic libraries at runtime using LoadLibrary(). The QLibrary class basically is wrapper around LoadLibrary, at least on Windows.
Back to your original topic: You have declared a function "UTIL". The C++ compiler will generate a "symbolic" name for that function, which in this case is "UTIL@32". The suffix "@32" is added because of the selected calling convention ("stdcall"). Thus the linker will look in all .obj (or .lib) files for an actual implementation of the function. And it will look for a function of the name "UTIL@32". Obviously there is no such function and so the linker throws an error. Therefore you have to find out what the symbolic name of the function in your existing .lib file is.
The problem is, if the function's symbolic name, in the existing .lib file, is actually "UTIL" instead of "UTIL@32", you'd have to somehow convince the MSVC compiler (you are using MSVC, right?) to assign the declared "UTIL" function a symbolic name of "UTIL" instead of "UTIL@32". But I'm not aware of a way to do this! Changing the calling convention of the function's declaration (e.g. to "cdecl") might remove the "@32" suffix, but then the function is declared wrongly and won't match the implementation - assuming the current declaration does match the implementation. So you would get a crash (or unexpected behavior) at runtime...
-
wrote on 26 Sept 2012, 07:55 last edited by
[quote author="MuldeR" date="1348585901"][cut]
Back to your original topic: You have declared a function "UTIL". The C++ compiler will generate a "symbolic" name for that function, which in this case is "UTIL@32". The suffix "@32" is added because of the selected calling convention ("stdcall"). Thus the linker will look in all .obj (or .lib) files for an actual implementation of the function. And it will look for a function of the name "UTIL@32". Obviously there is no such function and so the linker throws an error. Therefore you have to find out what the symbolic name of the function in your existing .lib file is.The problem is, if the function's symbolic name, in the existing .lib file, is actually "UTIL" instead of "UTIL@32", you'd have to somehow convince the MSVC compiler (you are using MSVC, right?) to assign the declared "UTIL" function a symbolic name of "UTIL" instead of "UTIL@32". But I'm not aware of a way to do this! Changing the calling convention of the function's declaration (e.g. to "cdecl") might remove the "@32" suffix, but then the function is declared wrongly and won't match the implementation - assuming the current declaration does match the implementation. So you would get a crash (or unexpected behavior) at runtime...[/quote]
You are definitely my master. You illuminated me.
The problem was the name of the function, as you wrote.I made a clean installation of QT sdk with mingw compiler included. Inside mingw folder there's an utility, "nm.exe", that I used to see the symbols list of my obj. "nm.exe" show the correct name of my function with a "_" (underscore) in front, but I have to omit it.
The question about the "@32" can be solved removing "FAR PASCAL" in "external" block.Thank you very much!
-
wrote on 26 Sept 2012, 10:14 last edited by
Yup, as said before, changing the calling convention from "stdcall" (as used, not only, by the Win32 API) to "cdecl" (the standard for C/C++) will remove the "@N" postfix. The PASCAL macro is nothing but the "__stdcall" keyword. Removing it, will default to "cdecl" calling convention. BUT: If your function, as implemented in the existing .obj file, does use (or expect) the "stdcall" calling convention, you must not remove it! Calling a function with "wrong" calling convention can cause all kind of strange problems, like stack corruption and random crashes...
For details see:
1/12