Ответ 1
extern
означает, что сущность имеет внешнюю связь, то есть видна вне ее единицы перевода (файл C или CPP). Следствием этого является то, что соответствующий символ будет помещен в объектный файл, и, следовательно, он будет также виден, если этот объектный файл является частью статической библиотеки. Однако extern
сам по себе не означает, что этот символ также будет виден после того, как объектный файл станет частью библиотеки DLL.
__declspec(dllexport)
означает, что символ должен быть экспортирован из DLL (если он действительно является частью DLL). Он используется при компиляции кода, который входит в DLL.
__declspec(dllimport)
означает, что символ будет импортирован из DLL. Он используется при компиляции кода, который использует DLL.
Поскольку тот же заголовочный файл обычно используется как при компиляции самой DLL, так и в клиентском коде, который будет использовать DLL, обычно можно определить макрос, который разрешает __declspec(dllexport)
при компиляции DLL и __declspec(dllimport)
при компиляции своего клиента, например:
#if COMPILING_THE_DLL
#define DLLEXTERN __declspec(dllexport)
#else
#define DLLEXTERN __declspec(dllimport)
#endif
Чтобы ответить на ваши конкретные вопросы:
- Да, для статических библиотек достаточно только
extern
. - Да - и декларация также нуждается в
extern
(см. объяснение здесь). - Не совсем - см. выше.
- Вам не нужно
extern
extern
с__declspec(dllimport)
(см. объяснение, приведенное выше), но поскольку вы обычно используете тот же заголовочный файл, у вас уже будетextern
потому что это необходимо при компиляции DLL.