Общие правила и ограничения

Только для систем Microsoft

  • При объявлении функции или объект без dllimport OR 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 атрибут в объявлении объекта должен предоставить определение для этого объекта в программе можно инициализировать global или local статический указатель функции с адресом a dllexport функция.Аналогично можно инициализировать global или local указатель статических данных с адресом a 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
    }
    
  • Из-за изменений в расширениях функциональности вставьте в Visual C++ .NET для создания приложения dllexport обычный последовательный между классами и специализациями шаблонов класса, если необходимо применить dllexport в обычный класс, имеющий базовый класс, который не помечен как dllexportкомпилятор создаст C4275.

    Компилятор выдает предупреждение, если один и тот же базовый класс специализация шаблона класса.Чтобы избежать этого, следует помечать базовый класс с dllexport.Проблема с специализацией шаблона класса, в котором установки __declspec(dllexport); не допускаются для пометки шаблона класса.Вместо этого необходимо явно создать экземпляр шаблона класса и помечает данный экземпляр с explicit dllexport.Примеры.

    template class __declspec(dllexport) B<int>;
    class __declspec(dllexport) D : public B<int> {
    // ...
    

    Это решение не выполняется, если аргумент шаблона производный класс.Примеры.

    class __declspec(dllexport) D : public B<D> {
    // ...
    

    Поскольку это общий шаблон с шаблонами, компилятор был изменен семантика dllexport при применении к классу, который содержит один или более базовых классов и, если один или несколько из базовых классов специализация шаблона класса.В этом случае компилятор неявно применяется dllexport в специализациям шаблонов класса.В Visual C++ .NET, пользователь может выполнить следующие действия и получать предупреждение:

    class __declspec(dllexport) D : public B<D> {
    // ...
    

См. также

Ссылки

dllexport, dllimport