我为这篇长篇文章提前道歉......
当我们在VS Menu>下列出STLPort包含和库目录时,我曾经能够构建我们的VC ++解决方案(我们在VS 2008上)。工具>选项> VC ++目录>包含和库文件的目录。但是,我们希望转换到完全依赖.vcproj和.sln文件的构建过程。与VS选项不同,这些可以检查到源控制中,VS选项必须分别在每台开发PC上配置。我们通过将Include目录添加到每个项目的属性页面来处理大多数库的转换>配置属性> C / C ++>一般>附加包含目录,以及链接器的库目录>一般>其他图书馆目录。
不幸的是,这种方法对STLPort不起作用。我们在链接期间收到LNK2019和LNK2001错误:
Error 1 error LNK2019: unresolved external symbol "public: virtual bool __thiscall MyClass::myFunction(class stlp_std::basic_istream<char,class stlp_std::char_traits<char> > &,class MyOtherClass &,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > &)const " (?myFunction@MyClass@@UBE_NAAV?$basic_istream@DV?$char_traits@D@stlp_std@@@stlp_std@@AAVSbprobScenarioData@@AAV?$basic_string@DV?$char_traits@D@stlp_std@@V?$allocator@D@2@@3@@Z) referenced in function _main MyLibrary.obj
Error 5 error LNK2001: unresolved external symbol "public: static void __cdecl MyClass::myFunction(class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &,long,enum MyClass::MessageType,int,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &)" (?myFunction@MyClass@@SAXABV?$basic_string@DV?$char_traits@D@stlp_std@@V?$allocator@D@2@@stlp_std@@000JW4MessageType@1@H0@Z) MyLibrary.lib
将链接和可执行项目链接到作为库项目的依赖项时会发生这种情况。奇怪的是,在链接库项目本身时不会发生这种情况。有什么想法吗?
答案 0 :(得分:5)
正如其他答案中所提到的,这是一个链接器错误,可能是库和使用不同选项编译的应用程序的结果。有一些解决这个问题的解决方案(目前已选择其中一个作为选择的答案)。这些解决方案 将 有效。但是,有一些工具可以使您的搜索更容易。
首先,了解装饰名称会有所帮助。在所有垃圾中,你会发现一些事情:你正在使用的你的功能名称,命名空间,一些类类型。它们周围的所有字符对编译器来说都意味着什么,但是你不需要编译器来告诉你它们是什么。
输入undname.exe:
undname.exe&lt; decoratedname&gt;
- 是一个简单的命令行程序,位于VS bin目录中。
- 将装饰名称作为第一个参数。
- 输出符号的人类可读格式。
有了这些知识,你现在可以继续寻找错误创造符号的合理候选人。
首先,您可以在其他地方建议的十六进制编辑器中编辑库。但是,有一种更容易找到符号的方法。
输入dumpbin.exe:
dumpbin.exe&lt; switches&gt; &lt;库名称&gt;
- 是一个简单的命令行程序,位于VS bin目录中。
- 使用一组开关和一个库来应用它们。
- 从图书馆输出信息
您对问题感兴趣的开关是 / linkermember 。还有许多其他开关可以为您提供非常有趣的信息,但是这一个将列出库中的所有符号。
此时,一个精通命令行的人会很好地为你服务。像 grep 这样的工具可以真正缩短您的工作周期,但您可以通过重定向到文件并使用记事本等来实现。
由于我没有你的代码或库,我会设想一个TinyXML的例子。
假设您的错误消息是:
Error 1 error LNK2019: unresolved external symbol "public: unsigned char __cdecl TiXmlComment::Accept(bool,class TiXmlVisitor *) " (?Accept@TiXmlComment@@ZBE_NPAVTiXmlVisitor@@@Z) referenced in function _main MyLibrary.obj
确定这是TinyXML中的一个函数后,我可以开始寻找不匹配的符号。我将首先转储库的链接器。 (请注意,开关是单数的,当我从内存中输入时,这总是会得到我!)
>dumpbin /linkermember tinyxml.lib
Microsoft (R) COFF/PE Dumper Version 8.00.50727.762
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file tinyxml.lib
File Type: LIBRARY
Archive member name at 8: /
4992E7BC time/date Wed Feb 11 08:59:08 2009
uid
gid
0 mode
B402 size
correct header end
859 public symbols
16292 ??$_Allocate@D@std@@YAPADIPAD@Z
16292 ??$_Char_traits_cat@U?$char_traits@D@std@@@std@@YA?AU_Secure_char_traits_tag@0@XZ
16292 ??$copy_s@U?$char_traits@D@std@@@_Traits_helper@std@@YAPADPADIPBDI@Z
16292 ??$copy_s@U?$char_traits@D@std@@@_Traits_helper@std@@YAPADPADIPBDIU_Secure_char_traits_tag@1@@Z
16292 ??$move_s@U?$char_traits@D@std@@@_Traits_helper@std@@YAPADPADIPBDI@Z
16292 ??$move_s@U?$char_traits@D@std@@@_Traits_helper@std@@YAPADPADIPBDIU_Secure_char_traits_tag@1@@Z
16292 ??$use_facet@V?$ctype@D@std@@@std@@YAABV?$ctype@D@0@ABVlocale@0@@Z
16292 ??0?$_String_val@DV?$allocator@D@std@@@std@@IAE@V?$allocator@D@1@@Z
16292 ??0?$_String_val@DV?$allocator@D@std@@@std@@QAE@ABV01@@Z
这显然太多了,但我们没有必要,我们知道我们在寻找什么,所以我们只会寻找它。
>dumpbin /linkermember tinyxml.lib | grep Accept
529AE ?Accept@TiXmlComment@@UBE_NPAVTiXmlVisitor@@@Z
529AE ?Accept@TiXmlDeclaration@@UBE_NPAVTiXmlVisitor@@@Z
529AE ?Accept@TiXmlDocument@@UBE_NPAVTiXmlVisitor@@@Z
529AE ?Accept@TiXmlElement@@UBE_NPAVTiXmlVisitor@@@Z
529AE ?Accept@TiXmlText@@UBE_NPAVTiXmlVisitor@@@Z
529AE ?Accept@TiXmlUnknown@@UBE_NPAVTiXmlVisitor@@@Z
3 ?Accept@TiXmlComment@@UBE_NPAVTiXmlVisitor@@@Z
3 ?Accept@TiXmlDeclaration@@UBE_NPAVTiXmlVisitor@@@Z
3 ?Accept@TiXmlDocument@@UBE_NPAVTiXmlVisitor@@@Z
3 ?Accept@TiXmlElement@@UBE_NPAVTiXmlVisitor@@@Z
3 ?Accept@TiXmlText@@UBE_NPAVTiXmlVisitor@@@Z
3 ?Accept@TiXmlUnknown@@UBE_NPAVTiXmlVisitor@@@Z
这更容易阅读。看看我们的错误,我们正在寻找TiXmlComment的Accept函数。如果我们有很多匹配项(比如查看stl中的size函数),我们可以另外为该名称grep输出,但在这种情况下,我们可以从列表中选择它。这是我们转向undname的地方:
>undname ?Accept@TiXmlComment@@UBE_NPAVTiXmlVisitor@@@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.
Undecoration of :- "?Accept@TiXmlComment@@UBE_NPAVTiXmlVisitor@@@Z"
is :- "public: virtual bool __thiscall TiXmlComment::Accept(class TiXmlVisitor *)const "
所以,在这个例子中,我们的应用程序正在寻找一个返回 unsigned char 的函数,但该库有一个函数返回 bool 。
这是一个人为的例子,但它说明了用于追踪问题的技巧。您可能正在寻找一种typedef类型,根据您的选项设置不同。
我遇到的问题是 time_t 。在我使用的一些库中, time_t 使用32位类型作为其内部表示的一部分。该库是使用较旧的编译器生成的,这是默认的。在VS 2005中, time_t 默认使用64位类型。我必须添加预处理器定义 _USE_32BIT_TIME_T 才能进行编译。我正如我所描述的那样跟踪这个问题。
我希望这有助于某人解决这个问题!
答案 1 :(得分:3)
Raymond Chen最近在The Old New Thing谈到了这个问题 - 这些问题的一个原因是该库是使用一组开关编译的,但您的应用程序使用的是另一组。你要做的是:
获取链接器正在查找的确切符号。这将是一个可怕的错误名称。 使用十六进制编辑器(IIRC,Visual Studio将执行此操作)来查看要链接到的.lib文件。 找到几乎是链接器所寻找的符号,但并不完全。 鉴于符号的不同,尝试找出哪些命令行开关会有所帮助。 祝你好运 - 对于那些不习惯这类问题的人来说,解决方案可能需要数天才能搞清楚(!)
答案 2 :(得分:1)
这些链接错误表明您的应用程序中的某些类尚未使用STLPort编译或已从构建中省略。他们并不暗示您没有链接STLport。
我的猜测是:
答案 3 :(得分:1)
您必须配置STL端口才能使用本机IOStream实现。
您还有使用STLPort的具体原因吗?除非您尝试创建跨平台应用程序,否则建议使用默认的STL实现 - 即使在大多数情况下也不需要它。
答案 4 :(得分:0)
这是一个链接错误。它与您的包含路径无关。
您忘记将MyClass.cpp添加到项目中,或忘记定义这两个函数。
“链接”库项目时未发生错误的原因是库项目未链接。它们只是一堆由LIB程序放在一起存放到库文件中的OBJ。
答案 5 :(得分:0)
将库名添加到要链接的其他库列表中。对不起,我不是在VS的最新版本面前知道确切的位置。