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.

Сборка DLL с помощью GCC

Порты 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, автоматически экспортирующий все символы