Подтвердить что ты не робот

Использование Visual Studio 2010, как можно связать DLL, сгенерированную Visual Studio 2008

Мои вопросы:

  • Можно ли ссылаться на VS2008 сгенерированных DLL файлов с использованием VS2010?

  • Если нет, почему это кажется можно связать со статическими библиотеками созданный VS2008.

  • Я вижу, что VS2010 теперь имеет платформу Опция набора инструментов. Но это позволит люди устанавливают его на v90 вместо v100 даже если у них нет VS2008 установлен?

  • Хотя я использую компилятор /Z 7 переключатель, почему мне все еще нужно иметь .pdb для отладки DLL.

Детали

Я могу использовать Visual Studio 2010 для ссылки на мои статические библиотеки Leptonica C, созданные Visual Studio 2008, без каких-либо проблем. (См. Раздел Ссылки ниже для получения подробной информации о том, как я создаю Leptonica и ссылаюсь на него.)

Однако, когда я пытаюсь связать одну и ту же программу (leptonlib-1.67\prog\ioformats_reg.c) с моей версией DLL версии DLL, выпущенной VS2008, программа выйдет из строя. Отладка, я вижу, что проблема в том, что ioformats_reg.c делает это:

fp = fopen(filename, "rb"); /* in ioformats_reg.c */

и вскоре после этого в файле leptonlib.dll выполняется следующее:

rewind(fp);                 /* in leptonlib.dll */

Как установить связь с правильной библиотекой времени выполнения (CRT) в режиме реального времени:

Библиотека многократного использования и все ее пользователи должны использовать одну и ту же библиотеку CRT типов и, следовательно, одного и того же компилятора переключатель...

Если вы решили смешивать библиотеки CRT, помните, что у вас есть два отдельных копии ЭЛТ, с отдельными и отдельных государств, поэтому вы должны быть осторожно о том, что вы пытаетесь сделать через границу CRT. Здесь очень много способы попасть в неприятности с двумя Кинескопы. Вот лишь несколько:

  • Есть две отдельные кучи. Вы не можете выделять (явно с новыми, malloc или так далее - или неявно с strdup, strstreambuf:: str или так далее), а затем передать указатель через CRT-граница должна быть освобождена.
  • Вы не можете передать дескриптор FILE * или файла через CRT-границу и ожидайте, что "низкоуровневый уровень ввода-вывода STDIO" работа.
  • Вы не можете установить языковой стандарт в одном и ожидать, что будет установлен другой языковой стандарт.

Начиная с Visual С++ 4.0, компоновщик выдаст предупреждение (LNK4098) если результирующий модуль пытается объединить более одной копии ЭЛТ библиотека. Для получения дополнительной информации, поиск файл справки для LNK4098.

Но я не получаю сообщения об ошибках LNK4098 от компоновщика VS2010.

Leptonica использует функции fopen(), rewind(), fclose() и т.д., которые документация классифицирует как Stream I/O, а не "низкоуровневый IO", но они проходят через FILE ptrs. Полагаю, это то, что Microsoft означает, когда говорят "stdio low-level IO".

/MD,/MT,/LD (Использовать библиотеку времени выполнения):

Все модули, переданные данному вызову компоновщик должен быть скомпилирован с одинаковым временем выполнения (/MD,/MT,/LD).

В нем нет говорится, что все модули должны быть скомпилированы одной и той же версией компилятора. Я использую /MD (или/MDd) последовательно и правильно для всех моих модулей.

При использовании DLL, похоже, что DLL не только должны использовать один и тот же ключ /MD, но они также должны быть скомпилированы VS2010?

Мой тестовый пример, похоже, указывает на то, что ссылка на статические библиотеки, созданные VS2008, работает, но, может быть, мне просто повезло? Почему связь с VS2008 сгенерирована статическими библиотеками, в то время как ссылка на VS2008 сгенерированную DLL не используется при использовании VS2010?

Означает ли это, что мне нужно отправлять отдельные библиотеки DLL для использования пользователями VS2008 и VS2010?


А как насчет новой опции Platform Toolset? Могут ли пользователи VS2010 изменить это на v900, даже если у них нет VS2008? Если это так, то я могу просто сказать людям изменить эту настройку для моего проекта Leptonlib-1.67.


Наконец, я использую переключатель /Z 7 при создании моих библиотек. Документация на /Z7,/Zi,/ZI (формат отладочной информации):

/Z7

Производит файл .obj, содержащий полный символический отладочная информация для использования с отладчиком. Символьная отладочная информация включает имена и типы переменных, а также функции и линии номера. Файл .pdb не создается.

Для дистрибьюторов сторонних библиотек существует преимущество в отсутствии файла .pdb. Однако Необходимы файлы .obj для предварительно скомпилированных заголовков во время фазы связи и отладки. Если есть (и никакого кода) в объектных файлах .pch, вам также придется скомпилировать /Yl (Inject PCH Reference для библиотеки отладки).

Я не использую предварительно скомпилированные заголовки. Однако, только когда у меня есть доступный .pdb, я могу отлаживать свои DLL файлы Leptonica. Также, несмотря на то, что он говорит: "Файл .pdb создается". Фактически, файл .pdb создается с моими текущими настройками проекта. Имеет ли /PDB в моих настройках компоновщика каким-то образом переопределить, указав /Z 7 во время компиляции?

Изменить: Также следует упомянуть, что я am способен отлаживать статическую библиотечную версию Leptonica даже без PDB.

Ссылки

Лептоника - это библиотека изображений C с открытым исходным кодом, написанная Дэн Блумбергом, доступная по адресу http://www.leptonica.com. Я предоставляю инструкции по созданию Leptonica с использованием VS2008/VS2010, а также предоставляет двоичные файлы Windows.

Смотрите http://leptonica.com/vs2008doc/building-leptonlib.html и http://leptonica.com/vs2008doc/building-image-libraries.html для подробности о том, как я создаю библиотеки Leptonica. http://www.leptonica.org/vs2008doc/building-prog-dir.html обсуждает, как я связываю ioformats_reg.

My Leptonica VS2008 Solution можно найти на http://www.leptonica.com/source/vs2008-1.67.zip. Мои двоичные библиотеки находятся в zip файле в http://leptonica.com/source/leptonica-1.67-win32-lib-include-dirs.zip. Источники Лептоники находятся в http://www.leptonica.com/source/leptonlib-1.67.tar.gz

4b9b3361

Ответ 1

Бит, который мне не хватало, заключается в том, что при использовании DLL существует два вызова компоновщика, один раз для DLL и один раз для приложения, которое связано с DLL. Когда вы используете статические библиотеки, существует только один вызов компоновщика (создание статических библиотек использует LIB).

Таким образом, DLL связывается с библиотекой времени выполнения C отдельно от любого приложения, которое ссылается на эту DLL. И возникают проблемы, если эти два C Runtimes отличаются.

Я могу использовать отладчик VS2010, чтобы посмотреть, какие модули загружаются через окно Debug → Windows → Modules. Когда я связываюсь с статическими библиотеками Leptonica, я вижу msvcrt.dll и msvcr100d.dll. Однако, когда я связываюсь с Leptonica leptonlibd.dll, я вижу msvcrt.dll, msvcr90d.dll и msvcr100d.dll.

Запуск "dumpbin/import leptonlibd.dll" также показывает ссылку на msvcr90d.dll.

Я бы сказал, что есть 3 решения проблемы:

  • Люди могут статически связываться с Leptonica, чтобы полностью избежать проблемы.

  • Поставьте VS2008 и VS2010 версии leptonlib.dll.

  • Измените API-интерфейс leptonica, чтобы все FILE обрабатывали или выделяли память create может обрабатываться/освобождаться только с помощью API. Я опубликовал вопрос об этом по адресу: http://code.google.com/p/leptonica/issues/detail?id=45

Теперь, когда я понимаю причину проблемы, я также, вероятно, поставлю версию DLL версии VS2010 в следующем бинарном выпуске.


Я решил не беспокоиться о невозможности отладки DLL без PDB. Люди, которым нужно отлаживать Leptonica, будут иметь источники и могут создавать свои собственные отладочные версии библиотеки (и, таким образом, будут создавать PDB).


Мне все равно будет интересно узнать, может ли владелец VS2010 использовать опцию V90 Platform Toolset, даже если у них нет VS2008. (Но чем больше я думаю об этом, тем больше сомневаюсь, что они могут.)

Ответ 2

Вы можете ссылаться на код 2008 с использованием 2010. Однако, как вы сами ответили, если вы создаете объект (например, память или дескриптор файла) с использованием одной среды выполнения (2008) и передаете ее в другую среду выполнения (2010) на уничтожьте его, у вас будут проблемы - эти системы представляют собой разные экземпляры (например, управление собственной кучей), поэтому не будут работать, если вы попытаетесь использовать два из них взаимозаменяемо, поскольку вы будете передавать указатели блоков памяти в систему, которая имеет не знаю, что это такое или откуда они пришли.

Решения также:

  • убедитесь, что все эти вызовы происходят с одной стороны или другой (поэтому, если ваша dll выделяет память, она должна правильно инкапсулировать этот процесс и предоставить API для его освобождения). В любом случае эта интернализация является хорошим дизайном библиотеки.

  • предоставить сборку 2010 вашей DLL для пользователей 2010, на которые нужно ссылаться. Это самое простое решение для всех, так как обманщик с вариантами компоновщика просто не забавна. Заставляя людей ориентировать свой код на старую рабочую среду, чтобы они могли использовать вашу библиотеку, вы можете сделать жизнь невозможной (как только они захотят использовать другую библиотеку, которая делает то же самое, они застряли). Хорошие библиотеки совместимы и просты в использовании, а не предписывающие и сложные.

Что касается pdb's: Компиляция и связывание - это два разных процесса, которые конвейерно соединены вместе. Если вы измените настройки для компиляции, вам может потребоваться изменить настройки для компоновки совместимым образом, прежде чем весь конвейер будет настроен правильно.

Ответ 3

Извините за отправку вопроса в качестве ответа, но...

У меня та же проблема, кроме всего, что в Visual Studio 2010!

Я использую библиотеку OCR tesseract, которая использует leptonica. Чтобы избежать зависимостей DLL, я связал все статически со статическим CRT. Он заканчивается как DLL, из которого я выставляю несколько функций.

Когда я связываю и создаю тестовую программу, я могу пройти через код и увидеть, что часть, где tesseract вызывает fopen(), работает, но когда ее вызвал из кода leptonica, он сработает!

Ответ 4

Я думаю, что было бы легко использовать DLL. Если они имеют одинаковое время выполнения .Net. Если у вас нет возможности перекомпилировать .dll, это еще одна история.