Опция -fvisibility в GCC 4.0
Последние версии GCC на некоторых платформах, включая Linux и Mac OS X, дают программистам возможность более тонкого управления экспортом символов из динамических библиотек: опция командной строки -fvisibility используется для указания видимости символов динамической библиотеки по умолчанию, а специальный атрибут, аналогичный __declspec(dllexport)в Windows, используется в исходном коде для изменения видимости символов по отдельности. Опция -fvisibilityимеет несколько различных значений, но два наиболее интересных — это default и hidden . Грубо говоря, видимость default означает, что символ доступен для кода других модулей, а видимость hidden означает, что не доступен. Чтобы включить выборочный экспорт символов, укажите в командной строке -fvisibility=hidden и используйте атрибут visibility (видимость) для пометки символов как видимых, как показано в примере 1.7.
Пример 1.7. Использование атрибута visibility с опцией командной строки -fvisibility=hidden
extern __attribute__((visibility("default"))) int m; // экспортируется
extern int n; // не экспортируется
__attribute__((visibility("default"))) void f(); // экспортируется
void g(); // не экспортируется
struct __attribute__((visibility("default"))) S { }; // экспортируется
struct T { }; //не экспортируется
В примере 1.7 атрибут __attribute__((visibility("default")))играет ту же роль, что и __declspec(dllexport)в коде Windows.
Использование атрибута visibilityпредставляет те же проблемы, что и использование __declspec(dllexport)и __declspec(dllimport), так как вам требуется, чтобы этот атрибут присутствовал при сборке общей библиотеки и отсутствовал при компиляции кода, использующего эту общую библиотеку, и чтобы он полностью отсутствовал на платформах, его не поддерживающих. Как и в случае с __declspec(dllexport)и __declspec(dllimport), эта проблема решается с помощью препроцессора. Например, вы можете изменить заголовочный файл georgeringo.hpp из примера 1.2 так, чтобы использовать атрибут видимости, следующим образом.
georgeringo/georgeringo.hpp
#ifndef GEORGERINGO_HPP_INCLUDED
#define GEORGERINGO_HPP_INCLUDED
// определите GEORGERINGO_DLL при сборке libgeorgeringo
#if defined(_WIN32) && !defined(__GNUC__)
#ifdef GEORGERINGO_DLL
#define GEORGERINGO_DECL __declspec(dllexport)
#else
#define GEORGERINGO_DECL __declspec(dllimport)
#endif
#else // Unix
# if defined(GEORGERINGO_DLL) && defined(HAS_GCC_VISIBILITY)
# define GEORGERINGO_DECL __attribute__((visibility("default")))
# else
#define GEORGERINGO_DECL
#endif
# endif
// Печатает "George, and Ringo\n"
GEORGERINGO_DECL void georgeringo();
#endif // GEORGERINGO_HPP_INCLUDED
Чтобы заставить это работать, вы должны при сборке в системах, поддерживающих опцию -fvisibility , определить макрос HAS_GCC_VISIBILITY.
Последние версии компилятора Intel для Linux также поддерживают опцию -fvisibility .
Видимость символов в Metrowerks для Mac OS X
Metrowerks для Mac OS X предоставляет несколько опций для экспорта символов из динамической библиотеки. При использовании IDE CodeWarrior вы можете использовать файл экспорта символов , который играет роль файла .def в Windows. Вы также можете экспортировать все символы с помощью опции -export all , что при сборке из командной строки является поведением по умолчанию. Я рекомендую метод, использующий для пометки в вашем исходном коде экспортируемых функций #pragma export, и указание в командной строке -export pragma при сборке динамической библиотеки. Использование #pragma exportиллюстрируется в примере 1.2: просто вызовите #pragma export onв ваших заголовочных файлах сразу перед группой функций, которые требуется экспортировать, а сразу после нее — #pragma export off. Если вы хотите, чтобы ваш код работал с инструментарием, отличным от Metrowerks, вы должны поместить обращения к #pragma exportмежду директивами #ifdef/ #endif, как показано в примере 1.2.
Опции командной строки
Давайте кратко посмотрим на опции, использованные в табл. 1.11. Каждая строка команды определяет:
• имя (имена) входного файла (файлов): george.obj , ringo.obj и georgeringo.obj ;
• имя создаваемой динамической библиотеки;
• в Windows имя библиотеки импорта.
Кроме того, компоновщик требует опции, которая говорит ему создать динамическую библиотеку, а не исполняемый файл. Большинство компоновщиков используют опцию -shared , но Visual C++ и Intel для Windows используют -dll , Borland и Digital Mars используют -WD , a GCC для Mac OS X использует -dynamiclib .
Читать дальше