C++. Сборник рецептов | страница 30
• При сборке кода, использующего DLL, укажите файл .def.
Как и в случае с экспортом символов, я рекомендую вместо файлов .def использовать в вашем исходном коде атрибут >__declspec(dllimport)
. Атрибут >__declspec(dllimport)
используется точно так же, как и атрибут >__declspec(dllexport)
, обсуждавшийся ранее. Аналогично >__declspec(dllexport)
атрибут >__declspec(dllimport)
не является частью языка С++, а является расширением языка, реализованным для большинства компиляторов для Windows.
Если вы выбрали использование >__declspec(dllexport)
и >__declspec(dllimport)
, вы должны убедиться, что при сборке DLL использовали >__declspec(dllexport)
, а при компиляции кода, использующего эту DLL, использовали >__declspec(dllimport)
. Одним из подходов является использование двух наборов заголовочных файлов: одного для сборки DLL, а другого для компиляции кода, использующего эту DLL. Однако это неудобно, так как сложно одновременно сопровождать две отдельные версии одних и тех же заголовочных файлов.
Вместо этого обычно используют определение макроса, который при сборке DLL расширяется как >__declspec(dllexport)
, а в противном случае — как >__declspec(dllimport)
. В примере 1.2 я использовал для этой цели макроопределение >GEORGERINGO_DECL
. В Windows, если определен символ >GEORGERINGO_SOURCE
, то >GEORGERINGO_DECL
раскрывается как >__declspec(dllexport)
, а в противном случае — как >__declspec(dllimport)
. Описанный результат вы получите, определив >GEORGERINGO_SOURCE
при сборке DLL libgeorgeringo.dll, но не определяя его при компиляции кода, использующего libgeorgeringo.dll.
Порты GCC Cygwin и MinGW, обсуждавшиеся в рецепте 1.1, работают с DLL по-другому, нежели остальные инструменты для Windows. При сборке DLL с помощью GCC по умолчанию экспортируются все функции, классы и данные. Это поведение можно изменить, использовав опцию компоновщика --no-export-all-symbols, применив в исходных файлах атрибут >__declspec(dllexport)
или используя файл .def. В каждом из этих трех случаев, если вы не используете опцию --export-all-symbols, чтобы заставить компоновщик экспортировать все символы, экспортируются только те функции, классы и данные, которые помечены атрибутом >__declspec(dllexport)
или указаны в файле .def.
Таким образом, инструментарий GCC можно использовать для сборки DLL двумя способами: как обычный инструментарий Windows, экспортирующий символы явно с помощью >__declspec
, или как инструментарий Unix, автоматически экспортирующий все символы