Чтение онлайн

на главную - закладки

Жанры

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:

Файл определения модуля, или файл .def — это текстовый файл, который описывает функции и данные, экспортируемые из DLL. Файл .def может быть написан вручную или автоматически сгенерирован каким-либо инструментом. Пример файла .def для библиотеки libgeorgeringo.dll показан в примере 1.5.

Пример 1.5. Файл определения модуля для libgeorgeringo.dll

LIBRARY LIBGEORGERINGO.DLL

EXPORTS

 Georgeringo @1

Экспорт символов из DLL

Имеется

два стандартных метода экспорта символов из Windows DLL.

• Использование атрибута

__declspec(dllexport)
в заголовочных файлах DLL и сборка библиотеки импорта, предназначенной для применения при сборке кода, использующего эту DLL.

Атрибут

__dеclspec(dllexport)
должен указываться в начале объявления экспортируемой функции или данных, вслед за какими-либо спецификаторами сборки, и сразу за ним должно следовать ключевое слово
class
или
struct
для экспортируемого класса. Это проиллюстрировано в примере 1.6. Заметьте, что
__declspec(dllexport)
не является частью языка С++; это расширение языка, реализованное для большинства компиляторов для Windows.

• Создание файла .def, описывающего функции и данные, экспортируемые из динамической библиотеки.

Пример 1.6. Использование атрибута __declspec(dllexport)

__declspec(dllexport) int m = 3; // Экспортируемое определение данных

extern __declspec(dllexport) int n; // Экспортируемое объявление данных

__declspec(dllexport) void f; // Экспортируемое объявление функции class

__declspec(dllexport) c { // Экспортируемое определение класса

 /* ... */

};

Использование файла .def имеет несколько преимуществ — например, он может позволить осуществлять доступ к функциям в DLL по номеру, а не по имени, что сокращает размер DLL. Он также устраняет необходимость запутанных директив препроцессора, таких как показанные в примере 1.2 в заголовочном файле georgeringo.hpp. Однако он также имеет и несколько серьезных недостатков. Например, файл .def не может использоваться для экспорта классов. Более того, можно забыть обновить свой файл .def при добавлении, удалении или изменении функций в вашей DLL. Таким образом, я рекомендую вам всегда использовать

__declspec(dllexport)
. Чтобы изучить полный синтаксис файлов .def, а также научиться их использовать, обратитесь к документации по своему инструментарию.

Импорт символов из DLL

Как есть два способа экспорта символов из DLL, так есть и два способа импорта символов.

• В заголовочных файлах, включенных в исходный код, использующий DLL, используйте атрибут

__declspec(dllimport)
и при сборке этого кода передайте библиотеку импорта компоновщику.

• При сборке кода, использующего 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, автоматически экспортирующий все символы [1] . В примере 1.2 и табл. 1.11 я использовал последний метод. Если вы выберете этот метод, вы должны в целях предосторожности использовать опцию – -export-all-symbols — на тот случай, если у вас окажутся заголовки, содержащие
__declspec(dllexport)
.

1

Экспорт символов с помощью

__declspec(dllexport)
иногда неправильно называют неявным экспортом

GCC отличается от других инструментов для Windows и еще в одном: вместо того чтобы передавать компоновщику библиотеку импорта, связанную с DLL, вы можете передать саму DLL. Это обычно быстрее, чем использование библиотеки импорта. Однако это может привести к проблемам, так как в одной и той же системе может существовать несколько версий одной DLL, и вы должны быть уверены, что компоновщик выберет правильную версию. В табл. 1.11 при демонстрации того, как создавать библиотеки импорта с помощью GCC, я решил не использовать эту возможность.

Поделиться:
Популярные книги

Начальник милиции. Книга 5

Дамиров Рафаэль
5. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции. Книга 5

Папина дочка

Рам Янка
4. Самбисты
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Папина дочка

Возвышение Меркурия. Книга 8

Кронос Александр
8. Меркурий
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 8

АллатРа

Новых Анастасия
Научно-образовательная:
психология
история
философия
обществознание
физика
6.25
рейтинг книги
АллатРа

Золушка вне правил

Шах Ольга
Любовные романы:
любовно-фантастические романы
6.83
рейтинг книги
Золушка вне правил

Возвышение Меркурия. Книга 5

Кронос Александр
5. Меркурий
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 5

На Ларэде

Кронос Александр
3. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
На Ларэде

Барон Дубов 6

Карелин Сергей Витальевич
6. Его Дубейшество
Фантастика:
юмористическое фэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Барон Дубов 6

Ротмистр Гордеев

Дашко Дмитрий Николаевич
1. Ротмистр Гордеев
Фантастика:
фэнтези
попаданцы
альтернативная история
5.00
рейтинг книги
Ротмистр Гордеев

Кодекс Крови. Книга VI

Борзых М.
6. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга VI

Лучше подавать холодным

Аберкромби Джо
4. Земной круг. Первый Закон
Фантастика:
фэнтези
8.45
рейтинг книги
Лучше подавать холодным

Звездная Кровь. Изгой

Елисеев Алексей Станиславович
1. Звездная Кровь. Изгой
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Звездная Кровь. Изгой

Крестоносец

Ланцов Михаил Алексеевич
7. Помещик
Фантастика:
героическая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Крестоносец

Сердце Дракона. Том 12

Клеванский Кирилл Сергеевич
12. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.29
рейтинг книги
Сердце Дракона. Том 12