Общие правила и ограничения
Блок, относящийся только к системам Майкрософт
Если вы объявляете функцию или объект без
dllimport
атрибутаdllexport
, функция или объект не считаются частью интерфейса DLL. Поэтому объявление функции или объекта должно находиться в том же самом модуле или в другом модуле той же программы. Чтобы сделать функцию или объект частью интерфейса DLL, необходимо объявить определение функции или объекта в другом модуле какdllexport
. В противном случае возникает ошибка компоновщика.Если вы объявляете функцию или объект с атрибутом
dllexport
, его определение должно отображаться в определенном модуле той же программы. В противном случае возникает ошибка компоновщика.Если один модуль в программе содержит оба
dllimport
иdllexport
объявления для одной функции или объекта,dllexport
атрибут имеет приоритет над атрибутомdllimport
. Однако компилятор создает предупреждение. Например:__declspec( dllimport ) int i; __declspec( dllexport ) int i; // Warning; inconsistent; // dllexport takes precedence.
В C++можно инициализировать глобально объявленный или статический локальный указатель данных или адрес объекта данных, объявленного атрибутом
dllimport
, который создает ошибку в C. Кроме того, можно инициализировать указатель статической локальной функции с адресом функции, объявленной атрибутомdllimport
. В C такое присваивание задает указатель на адрес преобразователя импорта библиотеки DLL (заглушки кода, передающей контроль функции), а не адрес функции. В C++ оно задает указатель на адрес функции. Например:__declspec( dllimport ) void func1( void ); __declspec( dllimport ) int i; int *pi = &i; // Error in C static void ( *pf )( void ) = &func1; // Address of thunk in C, // function in C++ void func2() { static int *pi = &i; // Error in C static void ( *pf )( void ) = &func1; // Address of thunk in C, // function in C++ }
Однако, поскольку программа, содержащая
dllexport
атрибут в объявлении объекта, должна предоставить определение этого объекта где-то в программе, можно инициализировать глобальный или локальный статический указатель функции с адресомdllexport
функции. Аналогичным образом указатель на глобальные или локальные статические данные можно инициализировать с адресом объекта данных с атрибутомdllexport
. Например, следующий код не создает ошибки в C или C++:__declspec( dllexport ) void func1( void ); __declspec( dllexport ) int i; int *pi = &i; // Okay static void ( *pf )( void ) = &func1; // Okay void func2() { static int *pi = &i; // Okay static void ( *pf )( void ) = &func1; // Okay }
При применении
dllexport
к обычному классу с базовым классом, который не помечен какdllexport
, компилятор создаст C4275.Компилятор создает то же самое предупреждение, если базовый класс является специализацией шаблона классов. Чтобы обойти эту проблему, пометьте базовый класс с
dllexport
помощью . Проблема с специализацией шаблона класса заключается в том, где разместить__declspec(dllexport)
шаблон класса; вы не можете пометить шаблон класса. Вместо этого явно создайте экземпляр шаблона класса и пометьте этот явный экземплярdllexport
. Например:template class __declspec(dllexport) B<int>; class __declspec(dllexport) D : public B<int> { // ...
Этот обходной путь завершается сбоем, если аргумент шаблона — это производный класс. Например:
class __declspec(dllexport) D : public B<D> { // ...
Так как это распространенный шаблон с шаблонами
dllexport
, компилятор изменил семантику при применении к классу с одним или несколькими базовыми классами и когда один или несколько базовых классов является специализацией шаблона класса. В этом случае компилятор неявно применяетсяdllexport
к специализациям шаблонов классов. Вы можете сделать следующее и не получить предупреждение:class __declspec(dllexport) D : public B<D> { // ...
Завершение блока, относящегося только к системам Майкрософт
См. также
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по