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
с __declspec(dllimport)
(см. Объяснение, связанное с выше), но, поскольку вы обычно будете использовать тот же заголовочный файл, у вас уже будет extern
потому что это необходимо при компиляции DLL.