Compartilhar via


Limitações e regras gerais

Específicos do Microsoft

  • Se você declarar uma função ou um objeto sem a dllimport ou dllexport atributo, a função ou o objeto não é considerado parte da interface do DLL.Portanto, a definição da função ou objeto deve estar presente neste módulo, ou em outro módulo do mesmo programa.Para tornar a parte da função ou objeto da interface da DLL, você deve declarar a definição da função ou objeto no módulo como dllexport.Caso contrário, será gerado um erro de vinculador.

    Se você declarar uma função ou objeto com o dllexport de atributo, sua definição deve aparecer em algum módulo do mesmo programa.Caso contrário, será gerado um erro de vinculador.

  • Se um único módulo no seu programa contém ambos dllimport e dllexport declarações para a mesma função ou objeto, o dllexport atributo tem precedência sobre o dllimport atributo.No entanto, um aviso do compilador é gerado.Por exemplo:

    __declspec( dllimport ) int i;
    __declspec( dllexport ) int i;   // Warning; inconsistent;
                                     // dllexport takes precedence.
    
  • No C++, você pode inicializar um ponteiro de dados local estático ou declarados globalmente ou com o endereço de um objeto de dados declarado com o dllimport atributo, o que gera um erro em c.Além disso, você pode inicializar um ponteiro de função estática de local com o endereço de uma função declarada com o dllimport atributo.Em C, como uma atribuição define o ponteiro para o endereço da conversão de importação de DLL (um stub de código que transfere o controle para a função) em vez do endereço da função.No C++, ele define o ponteiro para o endereço da função.Por exemplo:

    __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++
    }
    

    No entanto, como um programa que inclui o dllexport atributo na declaração de um objeto deve fornecer a definição desse objeto em algum lugar no programa, você pode inicializar um ponteiro de função estática global ou local com o endereço de um dllexport função.Da mesma forma, você pode inicializar um ponteiro de dados estáticos global ou local com o endereço de um dllexport o objeto de dados.Por exemplo, o código a seguir não gera erros em c ou 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
    }
    
  • Devido a uma alteração no comportamento de apresentar no Visual C++.NET para tornar o aplicativo de dllexport mais consistente entre classes normais e especializações dos modelos de classe, se você aplicar dllexport a uma classe regular que tem uma classe base que não está marcada como dllexport, o compilador irá gerar C4275.

    O compilador gera o mesmo aviso se a classe base é uma especialização de um modelo de classe.Para contornar isso, marcar a classe base com dllexport.O problema com uma especialização de um modelo de classe é onde colocar a __declspec(dllexport); Você não tem permissão para marcar o modelo de classe.Em vez disso, explicitamente instanciar o modelo de classe e marcar esta instanciação explícita com dllexport.Por exemplo:

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

    Essa solução alternativa falhará se o argumento de modelo é a classe derivada.Por exemplo:

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

    Como esse é um padrão comum com modelos, o compilador alterado a semântica do dllexport quando ele é aplicado a uma classe que tenha uma ou mais classes de base e quando uma ou mais das classes base são uma especialização de um modelo de classe.Nesse caso, o compilador aplica implicitamente dllexport para as especializações de modelos de classe.No Visual C++.NET, um usuário pode fazer o seguinte e não receber um aviso:

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

Consulte também

Referência

dllexport, dllimport