Como evito a colisão do nome com macros definidos nos arquivos do cabeçalho do Windows?

StackOverflow https://stackoverflow.com/questions/2321713

  •  22-09-2019
  •  | 
  •  

Pergunta

Eu tenho algum código C ++ que inclui um método chamado CreateDirectory(). Anteriormente, o código usava apenas STL e Boost, mas recentemente tive que incluir <windows.h> Então eu poderia procurar CSIDL_LOCAL_APPDATA.

Agora, este código:

filesystem.CreateDirectory(p->Pathname()); // Actually create it...

Não é mais compilar:

error C2039: 'CreateDirectoryA' : is not a member of ...

Que corresponde a esta macro em winbase.h:

#ifdef UNICODE
#define CreateDirectory  CreateDirectoryW
#else
#define CreateDirectory  CreateDirectoryA
#endif // !UNICODE

O pré-processador está redefinindo minha chamada de método. Existe alguma maneira possível de evitar essa colisão de nomeação? Ou eu tenho que renomear meu CreateDirectory() método?

Foi útil?

Solução

Você ficará melhor se apenas renunciar ao seu método CreateRectory. Se você precisa usar APIs do Windows, lutar com o Windows.H é uma batalha perdida.

Incidentalmente, se você fosse consistente Ao incluir o Windows.h, isso ainda estará compilando. (Embora você possa ter problemas em outros lugares).

Outras dicas

Você pode criar um módulo cujo único objetivo é #include <windows.h> e procure csidl_local_appdata envolto em uma função.

int get_CSIDL_LOCAL_APPDATA(void)
{
    return CSIDL_LOCAL_APPDATA;
}

BTW, muito bem para descobrir o que aconteceu!

#undef Createdirectory

Como desenvolvedor que trabalha em uma base de código de plataforma cruzada, isso é um problema. A única maneira de lidar com isso é

  • Certifique -se de que o Windows.H esteja - no Windows, pelo menos - universalmente incluído. Em seguida, a macro Createdirectory é definida em todas as suas unidades de compilação e é universalmente substituída pelo CreateRectoryw. Os cabeçalhos pré -compilados são ideais para isso

Ou, se essa é uma proposta desagradável (e é para mim)

  • Isole o uso do Windows.h em arquivos de utilitário específicos do Windows. Crie arquivos que exportam a funcionalidade básica necessária. Os arquivos do cabeçalho devem usar tipos de dados compatíveis, mas não dependem da inclusão do Windows.h. O arquivo de implementação do CPP deve (obviamente) usar o Windows.h.

Se suas funções de utilização precisarem incluir arquivos de cabeçalho do projeto com símbolos conflitantes, o seguinte padrão é uma necessidade:

#include <windows.h>
#ifdef CreateDirectory
#undef CreateDirectory
#endif
// etc
#include "some_class_with_CreateDirectory_method.h"
// ...

Você precisará chamar explicitamente a versão não macro de quaisquer funções da API do Windows que você possui #Undef'd - CreatedIRectorya ou W etc.

push macro, undef isso e pop a macro novamente:

#pragma push_macro("CreateDirectory")
#undef CreateDirectory
void MyClass::CreateDirectory()
{
 // ...
}
#pragma pop_macro("CreateDirectory")

Observe que o conflito de nome geralmente vem de um determinado arquivo de cabeçalho que está sendo incluído. Até então, coisas como CreatedIrctory e GetMessage não são puxadas para visibilidade e compilados de código sem problemas.

Você pode isolar essa inclusão em um arquivo de cabeçalho do wrapper e "#undef for o que" no final. Então, qualquer que seja a colisão do nome que você tenha desaparecido. A menos que você precise usar essas macros em seu próprio código (sim, então muito provável...)

Você pode recuperar CreateDirectory, depois defina e defina novamente quando terminar seu trabalho com você personalizado.

#ifdef CreateDirectory
#define CreateDirectory_Backup CreateDirectory
#undef CreateDirectory
#endif

// ...
// Define and use your own CreateDirectory() here.
// ...

#ifdef CreateDirectory_Backup
#define CreateDirectory CreateDirectory_Backup
#undef CreateDirectory_Backup
#endif
#pragma push_macro("CreateDirectory")

Se nada funcionar, em vez de renomear, você pode usar seu próprio espaço para nome para suas funções.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top