从Qt应用程序链接到C ++静态库

时间:2011-08-08 18:47:41

标签: c++ visual-studio qt linker-errors

我正在尝试将非Qt静态库链接到基于Qt的应用程序(它是Visual Studio项目)。
问题是静态库有一些API,它们将指向TCHAR字符串的指针作为输入之一。 当我尝试构建项目时,我收到链接错误,抱怨TCHAR。

标题

class Test
{
  public:
  static bool TestFunc( TCHAR *empty );
};

来源

bool Test::TestFunc( TCHAR *empty )
{
  return true;
}

错误:

error LNK2019: unresolved external symbol "public: static bool __cdecl Test::TestFunc(unsigned short *)" (?TestFunc@Test@@SA_NPAG@Z) referenced in function "public: __thiscall TestApp::TestApp(class QWidget *,class QFlags<enum Qt::WindowType>)" (??0TestApp@@QAE@PAVQWidget@@V?$QFlags@W4WindowType@Qt@@@@@Z)

有趣的是,如果我在头文件中有函数实现,它可以正常工作。或者,如果我将TCHAR更改为常规字符并保持声明/定义分离,它也可以工作(使用wchar_t直接失败并出现相同的链接错误)。

有谁知道可能导致该问题的原因,以及如何解决它? 提前谢谢,

4 个答案:

答案 0 :(得分:3)

使用的静态库是什么?视觉工作室?什么版本?

我会尝试解释你遇到的问题。

首先,当你将函数体放在标题中时它起作用的原因是因为这实际上导致你的应用程序重新编译函数体。链接器实际上不需要再解析静态库中的任何符号。因此,链接器问题就消失了。

问题在于,当编译静态库时,它导出Test::TestFunc的函数被编译器破坏了(它实质上是根据某些内部模式重命名)。函数名称修改是编译器的作用,用于简化链接器的符号解析。函数名称被修改的方式未根据c ++标准指定。因此,打开不同设置的不同编译器会以不同方式破坏函数名称。

当您尝试构建链接此库的应用程序时,Visual Studio现在会破坏名为的功能(可能在main()中)。如果定义函数的静态库的名称修改与调用函数的名称不匹配,则会收到您收到的错误。也就是说,链接器将在静态库中查找函数X,它可以找到的只是函数Y

现在,正如其他海报所指出的那样,名称修改也取决于函数作为输入所使用的参数。如果参数类型在两个地方(定义和用法)不同,编译器将以不同方式破坏函数名称。因此,链接器将再次无法解决匹配问题。

底线是,在符号存在的两个地方(图书馆和应用程序),符号必须会被严重损坏。执行此操作的最佳方法是使用完全相同的编译器进行编译,并使用完全相同的设置。

另一种可能性是,该符号实际上并不存在于您要链接的静态库中!

答案 1 :(得分:2)

确保两个项目的编译器设置相同。特别要看“字符集”属性,确保它们都是Unicode。这会更改TCHAR宏的定义。

答案 2 :(得分:1)

默认情况下,VS编译时启用“将wchar_t视为内置类型”(/Zc:wchar_t)。 Qt编译时禁用该选项(/Zc:wchar_t-)。如果在VS(在配置属性&gt; C / C ++&gt;语言下)中禁用“将wchar_t视为内置类型”,那么在构建静态库之前,是否可以解决此问题?

答案 3 :(得分:0)

TCHAR是char或wchar(即utf16),具体取决于应用程序的构建方式。

编辑:如果你想将Qt的strign类型与TCHAR组合 只需将您的QString转换为local8bitutf16(),然后将结果转换为TCHAR *

从TCHAR转换回QString

QString toQString(const char *str) { return QString::fromLocal8Bit(str); }
QString toQString(const wchar_t *str) { return QString::fromWCharArray(str); }