dllimport / dllexport и компиляция статических библиотек под Visual C ++ - PullRequest
3 голосов
/ 30 января 2011

Мне отчаянно нужна твоя помощь.

Я пытаюсь статически скомпилировать библиотеку poppler (специально для qt4) в Windows с помощью компилятора Visual C ++ 2008.Чтобы решить эту задачу, мне нужно было статически скомпилировать кучу других библиотек в качестве зависимостей для poppler.Когда я наконец-то сгенерировал статическую версию poppler, я получил ошибку компоновки при сборке приложения:

error LNK2019: unresolved external symbol "__declspec(dllimport)...

Я уже добавил новый путь включения и связал poppler-qt4.lib, но я все равно получаю ошибку.В поисках решения я нашел это обсуждение здесь в stackoverflow

Как связать статическую библиотеку в Visual C ++ 2008?

, с этой информацией я просматривал включаемые файлыбиблиотеки (зависимости от poppler, такие как zlib, libpng, cairo, ...) и я обнаружили, что в разных случаях у них нет директивы препроцессора для определения статической версии библиотеки.Пример статической директивы (openjpeg.h):

#if defined(OPJ_STATIC) || !(defined(_WIN32) || defined(WIN32) || defined(__WIN32__))
# define OPJ_API
# define OPJ_CALLCONV
#else
# define OPJ_CALLCONV __stdcall
# ifdef OPJ_EXPORTS
#  define OPJ_API __declspec(dllexport)
# else
#  define OPJ_API __declspec(dllimport)
# endif /* OPJ_EXPORTS */
#endif /* !OPJ_STATIC || !WIN32 */

Пример без статической директивы (jconfig.h из jpeg lib):

#if defined(_WIN32)
    #if defined(libjpeg_EXPORTS)
        #define JPEG_EXPORT __declspec(dllexport)
    #else
        #define JPEG_EXPORT __declspec(dllimport)
    #endif
#else
    #define JPEG_EXPORT 
#endif

Мой вопрос: недостаточно изменитьсвойства проекта от динамического до статического, поэтому мне тоже нужно изменить эти заголовки? и, если это правда, где я могу определить эти новые директивы для различия между статической и динамической компиляцией?

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 30 января 2011

Если вы изменяете свойства проекта с динамического на статическое связывание, как указано в openjpeg.h, вы должны указать препроцессор, который может использовать статическое связывание. Кроме того, чтобы изменить свойство с динамического на статическое, добавьте препроцессорOPJ_STATIC ...

Например:

#if defined(_WIN32)
    #if defined(OPJ_STATIC)
         # define OPJ_CALLCONV __stdcall
    #el if defined(libjpeg_EXPORTS)
        #define JPEG_EXPORT __declspec(dllexport)
    #else
        #define JPEG_EXPORT __declspec(dllimport)
    #endif
#else
    #define JPEG_EXPORT 
#endif
0 голосов
/ 12 сентября 2015

Во-первых, обратите внимание, что в Windows вообще нет динамической связи.Сюрприз!Вместо этого он использует thunks.Итак, что происходит: если вы создаете символ dllexport, он имеет его фактическое имя, такое же имя, как если бы это был не dllexport.Однако он отмечен в объектном файле для экспорта.

Если вы говорите, что dllimport, с другой стороны, имя изменяется, в C примерно, добавляя __imp_ к имени, более неприятный в C ++.

Теперь, когда вы связываете DLL, вы получаете DLL (конечно), но вы также получаете LIB-файл.Это статическая библиотека ссылок.Который является единственным видом, с которым может работать компоновщик.Для каждого символа, экспортируемого из DLL, в этом файле LIB есть символ dllimport, в частности с префиксом __imp_ или любым другим для C ++.

Так что теперь в программе или DLL вы хотите связать эту DLL, которую вы сделаливместо ссылки на импорт LIB.Процедуры импорта LIB - это блоки, которые исправляют до фактических адресов времени загрузки из DLL.

Итак, теперь, если вы попытаетесь выполнить обычную статическую связь с файлом LIB, созданным LIB.EXE, просто объединяя файлы OBJкоторый содержал некоторый dllexport, он потерпит неудачу, если ссылка является dllimport.Поскольку вы ссылаетесь на __imp_function (), когда библиотека на самом деле содержит обычную функцию ().

Так что со статической связью вы должны отбросить dllimport.AFAIK dllexport не имеет значения.Обратите внимание, что это относится к клиенту библиотеки, а не к самой библиотеке.

Что это значит?Ну, это прекрасно для статической ссылки на библиотеку, которая в свою очередь динамически связывается с другой библиотекой.Фактически по умолчанию статические ссылки в Windows динамически связываются с библиотеками времени выполнения C и ОС DLL.Таким образом, правило таково: клиент должен выбрать метод связи с библиотекой, провайдер должен предоставить обе версии.Но позаботьтесь, чтобы у них были разные имена !!(В противном случае LINK, создающий DLL, создаст fred.LIB, а LIB также создаст fred.LIB)

...