Compartilhar via


Importações mútuas

Exportar ou importar em outro arquivo executável tabela complicações quando as importações são mútuas circular (ou). Por exemplo, dois DLL importam símbolos de se, semelhante às funções mutuamente recursivos.

O problema com mutuamente importar arquivos executáveis (DLL) que é geralmente nenhum podem ser criados sem criar outro primeiro. Cada processo de compilação necessário, como entrada, uma biblioteca de importação gerada por outro processo de compilação.

A solução é usar o utilitário de LIB com a opção /DEF, que gerencia uma biblioteca de importação sem criar o arquivo executável. Está usando esse utilitário, você pode criar todas as bibliotecas de importação que precisa, não importando quantos DLL são envolvidos ou como complicado dependências.

A solução geral para tratar importa mútuas é:

  1. Coloque cada DLL por sua vez. (Qualquer ordem é viável, embora alguns pedidos são ótimos mais). Se todas as bibliotecas necessários da importação existem e são atuais, LINK executado para criar o arquivo executável (DLL). Isso permite gerenciar uma biblioteca de importação. Caso contrário, LIB de execução para gerar uma biblioteca de importação.

    O LIB em execução com a opção /DEF gerencie um arquivo adicional com uma extensão de .EXP. O arquivo de .EXP deve ser usado posteriormente para criar o arquivo executável.

  2. Após usar o LINK ou o LIB para criar todas as bibliotecas de importação, volte e LINK executado para construir todos os arquivos executáveis que não sejam criadas na etapa anterior. Observe que o arquivo de .exp correspondente deve ser especificado na linha de LINK.

    Se você tiver executado o anterior do utilitário LIB para gerar uma biblioteca de importação para DLL1, o LIB geraria o arquivo DLL1.exp também. Você deve usar DLL1.exp como entrada COMO VINCULAR ao criar DLL1.dlll.

A ilustração a seguir mostra uma solução para dois DLL mutuamente importando, DLL1 e DLL2. A etapa 1 for, execute o LIB com a opção definida de /DEF, em DLL1. Etapa 1 DLL1.lib gerencia, uma biblioteca de importação, e DLL1.exp. Na etapa 2, a biblioteca de importação é usada para criar DLL2, que gerencia por sua vez uma biblioteca de importação para símbolos de DLL2. Etapa 3 DLL1 cria, usando DLL1.exp e DLL2.lib como entrada. Observe que um arquivo de .exp para DLL2 não é necessário porque o LIB não foi usado para criar a biblioteca de importação de DLL2.

Ao vincular dois DLL com importa mútuas

Usando Importações mútuas vincular duas DLLs

Limitações de _AFXEXT

Você pode usar o símbolo de pré-processador de _AFXEXT para seus dlls da extensão conforme você não tiver várias camadas de DLL da extensão. Se você tiver as dlls de extensão que chamam ou derivam das classes em seus próprios DLL de extensão, que deriva das classes em MFC, você deve usar seu próprio símbolo de pré-processador para evitar a ambiguidade.

O problema é aquela no Win32, você deve declarar explicitamente todos os dados como __declspec(dllexport) se deve ser exportado de uma DLL, e __declspec(dllimport) se deve ser importado de uma DLL. Quando você define _AFXEXT, os cabeçalhos de MFC ter certeza de que AFX_EXT_CLASS está definida corretamente.

Quando você tiver várias camadas, um símbolo como AFX_EXT_CLASS não é suficiente, como uma DLL de extensão pode exportar novas classes bem como importar outras classes de outro DLL da extensão. Para resolver esse problema, use um símbolo de pré-processador especial que indica que você está criando a DLL próprio em relação à utilização da DLL. Por exemplo, imagine dois DLL de extensão, A.dll e B.dll. Eles cada exportação algumas classes em A.h e em B.h, respectivamente. B.dll usa as classes de A.dll. Os arquivos de cabeçalho olhariam aparência:

/* A.H */
#ifdef A_IMPL
   #define CLASS_DECL_A   __declspec(dllexport)
#else
   #define CLASS_DECL_A   __declspec(dllimport)
#endif

class CLASS_DECL_A CExampleA : public CObject
{ ... class definition ... };

// B.H
#ifdef B_IMPL
   #define CLASS_DECL_B   __declspec(dllexport)
#else
   #define CLASS_DECL_B   __declspec(dllimport)
#endif

class CLASS_DECL_B CExampleB : public CExampleA
{ ... class definition ... };
...

Quando A.dll é criado, ele é compilado com /D A_IMPL e quando B.dll é criado, é criado com /D B_IMPL. Usando símbolos separados para cada DLL, CExampleB é exportado e CExampleA é importado para criar B.dll. CExampleA é exportado para criar A.dll e importado quando usado por B.dll (ou por outro cliente).

Esse tipo de estratificação não pode ser feito ao usar AFX_EXT_CLASS e símbolos internos de pré-processador de _AFXEXT . A técnica descrita acima resolve o problema de um modo não diferentemente dos usos MFC do próprio mecanismo para criar seus dlls ativas das tecnologias, a extensão da base de dados, e de rede.

Não exportando a classe inteira

Quando você não estiver exportando uma classe inteira, você precisa garantir que os itens de dados necessários criados por macros de MFC são exportados corretamente. Isso pode ser feito redefinindo AFX_DATA a macro da sua classe específica. Isso deve ser feito quando você não estiver exportando a classe inteira.

Por exemplo:

/* A.H */
#ifdef A_IMPL
   #define CLASS_DECL_A  _declspec(dllexport)
#else
   #define CLASS_DECL_A  _declspec(dllimport)
#endif

#undef  AFX_DATA
#define AFX_DATA CLASS_DECL_A

class CExampleA : public CObject
{
   DECLARE_DYNAMIC()
   CLASS_DECL_A int SomeFunction();
   //... class definition ...
};

#undef AFX_DATA
#define AFX_DATA

O que você deseja fazer?

Que você deseja saber mais?

Consulte também

Conceitos

Importando e exportando