Используя Visual Studio 2010, как можно связать библиотеку DLL сгенерированную Visual Studio 2008? - PullRequest
12 голосов
/ 13 ноября 2010

Мои вопросы:

  • Возможно ли связать с VS2008 сгенерированные библиотеки DLL с использованием VS2010?

  • Если нет, то почему можно ссылаться на статические библиотеки генерируется VS2008.

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

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

Подробности

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

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

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

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

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

Как связать с правильной библиотекой C Run-Time (CRT) говорит:

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

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

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

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

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

Leptonica использует fopen (), rewind (), fclose () и т. Д., Которые документация классифицирует как потоковый ввод-вывод, а не «низкоуровневый ввод-вывод», но они передают FILE ptrs. Я полагаю, что именно это имеет в виду Microsoft, когда они говорят «IIO низкого уровня stdio».

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

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

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

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

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

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


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


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

/ Z7

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

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

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

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

Ссылки

Leptonica - библиотека обработки изображений C с открытым исходным кодом от Dan Bloomberg, доступная по адресу 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.

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

Ответы [ 4 ]

7 голосов
/ 14 ноября 2010

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

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

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

  • Поставка версий leptonlib.dll для VS2008 и VS2010.

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

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


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


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

3 голосов
/ 13 ноября 2010

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

Возможны следующие решения:

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

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

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

1 голос
/ 19 ноября 2010

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

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

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

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

0 голосов
/ 17 февраля 2011

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

...