Заранее прошу прощения за длинный пост ...
Раньше у меня была возможность создавать наши решения VC++ (мы на VS 2008), когда мы перечисляли каталоги включения и библиотеки STLPort в меню VS> Инструменты> Параметры> Каталоги VC++> Каталоги для файлов включения и библиотеки. Однако мы хотели перейти к процессу сборки, полностью основанному на файлах .vcproj и .sln. Их можно проверить в системе управления версиями, в отличие от VS Options, которые необходимо настраивать на каждом ПК разработки отдельно. Мы обработали переход для большинства библиотек, добавив каталоги Include на Страницы свойств каждого проекта> Свойства конфигурации> C / C++> Общие> Дополнительные каталоги включения и каталоги библиотек в Linker> Общие> Дополнительные каталоги библиотек.
К сожалению, этот подход не работает для 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
Это происходит при связывании исполняемого проекта с зависимостями, которые являются проектами библиотеки. Любопытно, что этого не происходит при линковке самих библиотечных проектов. Есть идеи?





Это ошибка ссылки. Это не имеет отношения к вашим включаемым путям.
Вы либо забыли добавить MyClass.cpp в свой проект, либо забыли определить эти две функции.
Причина, по которой ошибка не возникает при «связывании» проектов библиотеки, заключается в том, что проекты библиотеки не связаны. Это просто набор OBJ, которые программа LIB объединяет в файл библиотеки.
Добавьте имя библиотеки в список дополнительных библиотек для связывания. Извините, я не знаком с последней версией VS, чтобы точно знать, куда она идет.
Эти ошибки связи предполагают, что определенные классы в приложении ваш либо не были скомпилированы с использованием STLPort, либо были исключены из сборки. Они не предполагают, что вы не связываетесь с STLport.
Я предполагаю, что:
Вам необходимо настроить порт STL для использования собственной реализации IOStreams.
Также есть какая-то конкретная причина, по которой вы используете STLPort? Реализация STL по умолчанию рекомендуется, если вы не пытаетесь создать кроссплатформенное приложение - даже в этом случае в большинстве случаев это действительно не нужно.
Это унаследованный код, который я не могу изменить, не причинив большой боли себе и другим. Я пробовал, но не уверен, правильно ли у меня все настройки. Не уверен, что мне тоже придется его перекомпилировать.
Раймонд Чен недавно говорил об этом на Старая новая вещь - одна из причин этих проблем заключается в том, что библиотека была скомпилирована с одним набором переключателей, но ваше приложение использует другой набор. Что вам нужно сделать:
Получите точный символ, который ищет компоновщик. Это будет ужасное искалеченное имя. Используйте шестнадцатеричный редактор (IIRC, Visual Studio сделает это), чтобы просмотреть файл .lib, на который вы ссылаетесь. Найдите символ, который пытается найти компоновщик, но не совсем. Учитывая различия в символах, попробуйте выяснить, какие ключи командной строки помогут. Удачи - людям, которые не привыкли к подобным проблемам, решение может занять несколько дней (!)
Еще одна уловка - связать с помощью / VERBOSE, который будет печатать найденные вещи. Это помогло мне хотя бы найти проблему такого типа. СПАСИБО за этот пост, он действительно помог мне определить мою проблему. Теперь возникает вопрос, почему в одном .lib есть объявление функции _cdecl, а в другом - _this_call.
Как упоминалось в других ответах, это ошибка компоновщика и, вероятно, результат компиляции библиотеки и приложения с разными параметрами. Уже есть несколько решений по отслеживанию этого (в настоящее время одно из них является выбранным ответом). Эти решения воля работают. Однако есть несколько инструментов, которые будут использовать сделать ваш поиск намного проще.
Для начала поможет понимание оформленных имен. Среди всего этого мусора вы узнаете некоторые вещи: название вашей функции, пространства имен, некоторые типы классов, которые вы используете. Все эти символы вокруг них что-то значат для компилятора, но вам не нужно, чтобы компилятор сообщал вам, что это такое.
Enter undname.exe:
undname.exe <decoratedname>
- is a simple command line program that is in your VS bin directory.
- takes the decorated name as it's first argument.
- outputs a human readable format of the symbol.
Вооружившись этими знаниями, теперь вы можете перейти к поиску разумного кандидата на неправильно созданный символ.
Во-первых, вы можете редактировать свои библиотеки в шестнадцатеричном редакторе, как это предлагается в другом месте. Однако есть гораздо более простой способ найти символы.
Enter dumpbin.exe:
dumpbin.exe <switches> <library name>
- is a simple command line program that is in your VS bin directory.
- takes a set of switches and a library to apply them to.
- outputs information from the library
Переключатель, который вас заинтересует для вашего вопроса, - / 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. Мы могли бы дополнительно получить вывод для этого имени, если бы у нас было много совпадений (например, глядя на функцию размера в stl!), Но в этом случае мы можем выбрать его из списка. Вот где мы переходим к отмене имени:
>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 "
Итак, в этом примере наше приложение ищет функцию, которая возвращает беззнаковый символ, но в библиотеке есть функция, возвращающая bool.
Это надуманный пример, но он иллюстрирует технику, которую нужно использовать для отслеживания вашей проблемы. Вероятно, вы ищете тип typedef, который устанавливается по-разному в зависимости от ваших параметров.
Проблема, с которой я столкнулся, была связана с time_t. В некоторых библиотеках, которые я использовал, time_t использовал 32-битный тип как часть своего внутреннего представления. Эта библиотека была создана с помощью более старого компилятора, который использовался по умолчанию. В VS 2005 time_t по умолчанию использует 64-битный тип. Мне пришлось добавить определение препроцессора _USE_32BIT_TIME_T, чтобы заставить его скомпилировать. Я отследил эту проблему точно так, как я описал.
Надеюсь, это поможет кому-то решить эту проблему!
Спасибо! Звучит многообещающе, завтра я попробую первым делом.
Да, я тоже пробовал. Но опять же, мне может потребоваться больше времени, чтобы все просмотреть, чтобы убедиться, что все это правильно связано. Как я уверен, вы все знаете, поддерживать старое программное обеспечение десятилетиями сложно. Специально для нас, новичков. XD