Атрибут __dеclspec(dllexport) должен указываться в начале объявления экспортируемой функции или данных, вслед за какими-либо спецификаторами сборки, и сразу за ним должно следовать ключевое слово class или struct для экспортируемого класса. Это проиллюстрировано в примере 1.6. Заметьте, что __declspec(dllexport) не является частью языка С++; это расширение языка, реализованное для большинства компиляторов для Windows.
• Создание файла
__declspec(dllexport) int m = 3; // Экспортируемое определение данных
extern __declspec(dllexport) int n; // Экспортируемое объявление данных
__declspec(dllexport) void f(); // Экспортируемое объявление функции class
__declspec(dllexport) c { // Экспортируемое определение класса
/* ... */
};
Использование файла __declspec(dllexport). Чтобы изучить полный синтаксис файлов
Как есть два способа экспорта символов из DLL, так есть и два способа импорта символов.
• В заголовочных файлах, включенных в исходный код, использующий DLL, используйте атрибут __declspec(dllimport) и при сборке этого кода передайте библиотеку импорта компоновщику.
• При сборке кода, использующего DLL, укажите файл
Как и в случае с экспортом символов, я рекомендую вместо файлов __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