¿Cuál es el efecto de la "C" externa en C++?
¿ Qué hace exactamente poner extern "C"
en código C++?
Por ejemplo:
extern "C" {
void foo();
}
extern "C"
hace que un nombre de función en C++ tenga un enlace C (el compilador no modifica el nombre) para que el código C del cliente pueda vincularse (usar) su función utilizando un archivo de encabezado compatible con C que contenga solo la declaración de su función. La definición de su función está contenida en un formato binario (que fue compilado por su compilador de C++) al que luego se vinculará el vinculador de C del cliente utilizando el nombre de C.
Dado que C++ tiene una sobrecarga de nombres de funciones y C no, el compilador de C++ no puede simplemente usar el nombre de la función como una identificación única para vincular, por lo que modifica el nombre agregando información sobre los argumentos. El compilador de AC no necesita alterar el nombre ya que no puede sobrecargar los nombres de funciones en C. Cuando indica que una función tiene extern "C"
vinculación en C++, el compilador de C++ no agrega información de tipo de argumento/parámetro al nombre utilizado para la vinculación.
Para que lo sepas, puedes especificar extern "C"
un vínculo a cada declaración/definición individual explícitamente o usar un bloque para agrupar una secuencia de declaraciones/definiciones para tener un vínculo determinado:
extern "C" void foo(int);
extern "C"
{
void g(char);
int i;
}
Si le interesan los detalles técnicos, se enumeran en la sección 7.5 del estándar C++03, aquí hay un breve resumen (con énfasis en extern "C"
):
extern "C"
es una especificación de enlace- Cada compilador debe proporcionar un enlace "C"
- Una especificación de enlace deberá ocurrir solo en el alcance del espacio de nombres.
Todos los tipos de funciones, nombres de funciones y nombres de variables tienen un enlace de idioma.Consulte el comentario de Richard: Sólo los nombres de funciones y nombres de variables con enlace externo tienen un enlace de idioma.- Dos tipos de funciones con vínculos lingüísticos distintos son tipos distintos incluso si son idénticos
- Las especificaciones de enlace se anidan, la interna determina el enlace final
extern "C"
se ignora para los miembros de la clase- Como máximo, una función con un nombre particular puede tener un enlace "C" (independientemente del espacio de nombres)
Vea el comentario de Richard: el interior es válido; una entidad así declarada tiene un vínculo interno y, por lo tanto, no tiene un vínculo lingüísticoextern "C"
obliga a una función a tener un enlace externo (no se puede hacer estática)static
extern "C"
- La vinculación de C++ a objetos definidos en otros lenguajes y a objetos definidos en C++ de otros lenguajes está definida por la implementación y depende del lenguaje. Sólo cuando las estrategias de diseño de objetos de dos implementaciones de lenguaje sean lo suficientemente similares se podrá lograr dicha vinculación.
Sólo quería añadir un poco de información, ya que aún no lo he visto publicado.
Muy a menudo verás código en encabezados C como este:
#ifdef __cplusplus
extern "C" {
#endif
// all of your legacy C code here
#ifdef __cplusplus
}
#endif
Lo que esto logra es que le permite usar ese archivo de encabezado C con su código C++, porque la macro __cplusplus
estará definida. Pero también puedes usarlo con tu código C heredado, donde la macro NO está definida, por lo que no verá la construcción exclusiva de C++.
Aunque también he visto código C++ como:
extern "C" {
#include "legacy_C_header.h"
}
que imagino que logra más o menos lo mismo.
No estoy seguro de cuál es mejor, pero he visto ambas.