Ошибка LNK2001 при компиляции приложений, ссылающихся на STLport-5.1.4 с VC++ 2008

Заранее прошу прощения за длинный пост ...

Раньше у меня была возможность создавать наши решения 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   

Это происходит при связывании исполняемого проекта с зависимостями, которые являются проектами библиотеки. Любопытно, что этого не происходит при линковке самих библиотечных проектов. Есть идеи?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
3 011
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Это ошибка ссылки. Это не имеет отношения к вашим включаемым путям.

Вы либо забыли добавить MyClass.cpp в свой проект, либо забыли определить эти две функции.

Причина, по которой ошибка не возникает при «связывании» проектов библиотеки, заключается в том, что проекты библиотеки не связаны. Это просто набор OBJ, которые программа LIB объединяет в файл библиотеки.

Добавьте имя библиотеки в список дополнительных библиотек для связывания. Извините, я не знаком с последней версией VS, чтобы точно знать, куда она идет.

Да, я тоже пробовал. Но опять же, мне может потребоваться больше времени, чтобы все просмотреть, чтобы убедиться, что все это правильно связано. Как я уверен, вы все знаете, поддерживать старое программное обеспечение десятилетиями сложно. Специально для нас, новичков. XD

Jeremy 06.11.2008 07:15

Эти ошибки связи предполагают, что определенные классы в приложении ваш либо не были скомпилированы с использованием STLPort, либо были исключены из сборки. Они не предполагают, что вы не связываетесь с STLport.

Я предполагаю, что:

  • Параметры сборки для MyClass каким-то образом перезаписывают параметр для всего проекта для пути включения, и, таким образом, MyClass создается с использованием реализации STL C++ по умолчанию, а не STLport. Это должно быть легко проверить - запустите dumpbin для объектного файла и проверьте, что функции в нем ссылаются на стандартную библиотеку в пространстве имен stlp_ * или нет. Если нет, вероятно, компилятор не выбирает правильный путь включения. Я бы также посмотрел на командную строку, с которой IDE вызывает компилятор. Их также можно просмотреть в свойствах конфигурации C / C++.
  • Как также упоминалось в других плакатах, есть вероятность, что MyClass не создается, но это должно быть очень легко проверить.

Вам необходимо настроить порт STL для использования собственной реализации IOStreams.

Также есть какая-то конкретная причина, по которой вы используете STLPort? Реализация STL по умолчанию рекомендуется, если вы не пытаетесь создать кроссплатформенное приложение - даже в этом случае в большинстве случаев это действительно не нужно.

Это унаследованный код, который я не могу изменить, не причинив большой боли себе и другим. Я пробовал, но не уверен, правильно ли у меня все настройки. Не уверен, что мне тоже придется его перекомпилировать.

Jeremy 06.01.2009 13:38
Ответ принят как подходящий

Раймонд Чен недавно говорил об этом на Старая новая вещь - одна из причин этих проблем заключается в том, что библиотека была скомпилирована с одним набором переключателей, но ваше приложение использует другой набор. Что вам нужно сделать:

Получите точный символ, который ищет компоновщик. Это будет ужасное искалеченное имя. Используйте шестнадцатеричный редактор (IIRC, Visual Studio сделает это), чтобы просмотреть файл .lib, на который вы ссылаетесь. Найдите символ, который пытается найти компоновщик, но не совсем. Учитывая различия в символах, попробуйте выяснить, какие ключи командной строки помогут. Удачи - людям, которые не привыкли к подобным проблемам, решение может занять несколько дней (!)

Еще одна уловка - связать с помощью / VERBOSE, который будет печатать найденные вещи. Это помогло мне хотя бы найти проблему такого типа. СПАСИБО за этот пост, он действительно помог мне определить мою проблему. Теперь возникает вопрос, почему в одном .lib есть объявление функции _cdecl, а в другом - _this_call.

jakobengblom2 13.08.2009 16:56

Как упоминалось в других ответах, это ошибка компоновщика и, вероятно, результат компиляции библиотеки и приложения с разными параметрами. Уже есть несколько решений по отслеживанию этого (в настоящее время одно из них является выбранным ответом). Эти решения воля работают. Однако есть несколько инструментов, которые будут использовать сделать ваш поиск намного проще.

Для начала поможет понимание оформленных имен. Среди всего этого мусора вы узнаете некоторые вещи: название вашей функции, пространства имен, некоторые типы классов, которые вы используете. Все эти символы вокруг них что-то значат для компилятора, но вам не нужно, чтобы компилятор сообщал вам, что это такое.

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, чтобы заставить его скомпилировать. Я отследил эту проблему точно так, как я описал.

Надеюсь, это поможет кому-то решить эту проблему!

Спасибо! Звучит многообещающе, завтра я попробую первым делом.

Jeremy 29.03.2009 20:13

Другие вопросы по теме