Como muitos já sabem, para se chamar uma função de um código em C por outro código em C++, é necessário colocar um extern “C” antes de sua declaração.
Por exemplo, suponha que você tem os seguintes arquivos:
//hello_world.h
#if !defined (HELLO_WORLD_H_)
#define (HELLO_WORLD_H_)
void imprime();
#endif
//hello_world.c
#include <stdio.h>
#include “hello_world.h”
void imprime()
{
printf(“Hello world!”);
}
}
//main.cpp
#include “hello_world.h”
int main()
{
{
imprime();
return 0;
}
}
Se tentar compilar assim, vai dar um erro do tipo “unresolved external symbol” ou coisa do tipo.
Para resolver o problema, é necessário alterar ou o hello_world.h para:
//hello_world.h
#if !defined (HELLO_WORLD_H_)
#define (HELLO_WORLD_H_)
#if defined (__cplusplus) //já explico o que é isso
extern “C”
{
#endif
void imprime();
#if defined (__cplusplus)
}
#endif
#endif
ou o main.cpp para
//main.cpp
extern “C”
{
#include “hello_world.h”
}
int main()
{
{
imprime();
return 0;
}
}
O que muita gente não entende é por que isso é necessário.
Bom, vamos lá.
Quando você compila um código em C++, o compilador substitui o nome de cada função do seu código por um nome único. Isso é necessário porque em C++ você pode ter mais de uma função com o mesmo nome. Isso é chamado de name mangling (não sei se existe alguma tradução aceita para isso).
Por exemplo, suponha o seguinte código:
void Funcao( char* p ){...};
void Funcao( char* p, int a ){...};
int main()
{
Funcao(“teste”);
Funcao(“teste”, 5 );
return 0;
}
}
Seu compilador transformará a declaração das funções em:
void __xxxy( char* p ){...};
void __txyz( char* p, int a ){...};
E as chamadas em:
__xxxy(“teste”);
__txyz(“teste”, 5 );
Note que em C isso não é necessário, pois em C não é permitido que duas funções possuam o mesmo nome.
Neste caso, no exemplo acima, o compilador de C manterá o nome “imprime” da função quando estiver compilando o “hello_world.c”, porém o compilador de C++ irá substituí-lo por alguma coisa do tipo “_xxacd” quando estiver compilando o main.cpp. Assim, quando o linker estiver linkando os objetos criados, não encontrará uma definição de “_xxacd” dentro do objeto compilado em C, e dará o erro citado.
O comando extern “C” diz para seu compilador de C++ que aquelas funções não devem sofrer o processo de mangling.
Agora, se você não entendeu o motivo do #if defined (__cplusplus) no exemplo acima, eu explico:
A macro __cplusplus é definida pelos compiladores de C++, porém não existe nos compiladores de C. Por isso, quando fizemos:
#if defined (__cplusplus)
extern “C”
{
#endif
O compilador de C que está compilando o hello_world.c irá ignorar o extern “C”, pois a macro __cplusplus não está definida.
Se não colocássemos isso, o compilador de C acusaria um erro no código, pois ele não conhece o comando extern “C”.
muito bom... bem explicado
ResponderExcluir