Linking to a C++ Static Library from a Qt Application
I am trying to link a non-Qt static library, to a Qt-based application (its a Visual Studio project).
The issue is that the static library has some APIs which take a pointer to a TCHAR string as one of the inputs. When I try building the project, I get a linking error, complaining about the TCHAR.Header
class Test
{
public:
static bool TestFunc( TCHAR *empty );
};
Source
bool Test::TestFunc( TCHAR *empty )
{
return true;
}
Error:
error LNK2019: unresolved external symbol "public: static bool __cdecl Test::TestFunc(unsigned short *)" (?TestFunc@Test@@SA_NPAG@Z) referenced in functio开发者_JAVA技巧n "public: __thiscall TestApp::TestApp(class QWidget *,class QFlags<enum Qt::WindowType>)" (??0TestApp@@QAE@PAVQWidget@@V?$QFlags@W4WindowType@Qt@@@@@Z)
The interesting thing is that if I have the function implementation in the header file, it works fine. Or if I change the TCHAR to a regular char and keep the declaration/definition separate, it also works (using wchar_t directly fails with the same linking error).
Does anyone know what could be causing that issue, and how to resolve it?
Thanks in advance,What was the static library compiled using? Visual studio? What version?
I'll try to explain the problem you are having.
First of all, the reason it works when you put the function body in the header, is because this essentially causes the function body to be recompiled by your app. The linker doesn't actually need to resolve any symbols from the static library any more. Ergo, the linker problem goes away.
The problem is that when the static library was compiled, a function that it exports Test::TestFunc
was mangled by the compiler (it essentially renames it according to some internal schema). Function name mangling is what a compiler does, to simplify symbol resolution for the linker. The way a function name is mangled, is not specified according to the c++ standard. Therefore, different compilers, with different settings turned on, will mangle the function names differently.
When you try to build your app that links this library, Visual Studio now mangles the function where it is called (probably in main()
). If the name mangling of the static library, where the function is defined, doesn't match the name mangling from where the function is called, then you get the error you received. That is, the linker will be looking for function X
in the static library, and all it can find is function Y
.
Now, as other posters have pointed out, the name mangling also depends on the parameters the function takes as input. If the parameter types are different in the two places (definition and usage), the compiler will mangle the functions names differently. Ergo, once again, the linker will not be able to resolve a match.
Bottom line is that, in both places where the symbol exists (library and app), the symbol MUST be mangled identically. The best way to do this, is to compile using the exact same compiler, with exact same settings.
The other possibility of course, is that the symbol doesn't actually exist in the static library you are linking against!
Make sure that the compiler settings are the same for both projects. In particular look at the "Character Set" property, make sure they're both Unicode. This changes the definition of the TCHAR
macro.
By default, VS compiles with "Treat wchar_t as Built-in Type" enabled (/Zc:wchar_t
). Qt compiles with that option disabled (/Zc:wchar_t-
). If you disable the "Treat wchar_t as Built-in Type" in VS (under Configuration Properties > C/C++ > Language), before building the static library, does that fix it?
TCHAR is either a char or a wchar (ie utf16) depending on how the app is built.
edit: if you want to mix Qt's strign type with TCHAR
Simply convert your QString to local8bit or utf16() and then cast the result to TCHAR*
And to convert back from TCHAR to QString
QString toQString(const char *str) { return QString::fromLocal8Bit(str); }
QString toQString(const wchar_t *str) { return QString::fromWCharArray(str); }
精彩评论