Порты GCC Cygwin и MinGW, обсуждавшиеся в рецепте 1.1, работают с DLL по-другому, нежели остальные инструменты для Windows. При сборке DLL с помощью GCC по умолчанию экспортируются все функции, классы и данные. Это поведение можно изменить, использовав опцию компоновщика __declspec(dllexport)
или используя файл __declspec(dllexport)
или указаны в файле
Таким образом, инструментарий GCC можно использовать для сборки DLL двумя способами: как обычный инструментарий Windows, экспортирующий символы явно с помощью __declspec
, или как инструментарий Unix, автоматически экспортирующий все символы[1]. В примере 1.2 и табл. 1.11 я использовал последний метод. Если вы выберете этот метод, вы должны в целях предосторожности использовать опцию __declspec(dllexport)
.
GCC отличается от других инструментов для Windows и еще в одном: вместо того чтобы передавать компоновщику библиотеку импорта, связанную с DLL, вы можете передать саму DLL. Это обычно быстрее, чем использование библиотеки импорта. Однако это может привести к проблемам, так как в одной и той же системе может существовать несколько версий одной DLL, и вы должны быть уверены, что компоновщик выберет правильную версию. В табл. 1.11 при демонстрации того, как создавать библиотеки импорта с помощью GCC, я решил не использовать эту возможность.
Последние версии GCC на некоторых платформах, включая Linux и Mac OS X, дают программистам возможность более тонкого управления экспортом символов из динамических библиотек: опция командной строки __declspec(dllexport)
в Windows, используется в исходном коде для изменения видимости символов по отдельности. Опция -fvisibility
имеет несколько различных значений, но два наиболее интересных — это
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)
, эта проблема решается с помощью препроцессора. Например, вы можете изменить заголовочный файл
#ifndef GEORGERINGO_HPP_INCLUDED
#define GEORGERINGO_HPP_INCLUDED