¿Cómo funciona una statement externa “C”?

Estoy tomando un curso de lenguajes de progtwigción y estamos hablando de la statement extern "C" .

¿Cómo funciona esta statement a un nivel más profundo que no sea “interconecta C y C ++”? ¿Cómo afecta esto a las vinculaciones que tienen lugar en el progtwig también?

extern "C" se usa para asegurar que los símbolos que siguen no sean destruidos (decorados).


Ejemplo:

Digamos que tenemos el siguiente código en un archivo llamado test.cpp :

 extern "C" { int foo() { return 1; } } int bar() { return 1; } 

Si ejecuta gcc -c test.cpp -o test.o

Eche un vistazo a los nombres de símbolos:

00000010 T _Z3barv

00000000 T foo

foo() mantiene su nombre.

Veamos una función típica que se puede comstackr tanto en C como en C ++:

 int Add (int a, int b) { return a+b; } 

Ahora en C, la función se llama “_Add” internamente. Mientras que la función C ++ se llama algo completamente diferente internamente usando un sistema llamado mangle. Básicamente es una forma de nombrar una función para que la misma función con diferentes parámetros tenga un nombre interno diferente.

Entonces, si Add () se define en add.c, y tiene el prototipo en add.h, obtendrá un problema si intenta incluir add.h en un archivo C ++. Como el código de C ++ busca una función con un nombre diferente al de add.c, obtendrá un error de enlazador. Para evitar ese problema debe incluir add.c por este método:

 extern "C" { #include "add.h" } 

Ahora, el código de C ++ se vinculará con _Add en lugar de la versión de nombre C ++ destrozada.

Ese es uno de los usos de la expresión. En pocas palabras, si necesita comstackr un código que es estrictamente C en un progtwig C ++ (a través de una instrucción include u otro medio), debe envolverlo con una statement externa “C” {…}.

Cuando marca un bloque de código con la “C” externa, le está diciendo al sistema que use un enlace de estilo C.

Esto, principalmente, afecta la forma en que el enlazador destruye los nombres. En lugar de utilizar el mangling del nombre de estilo de C ++ (que es más complejo para soportar sobrecargas del operador), obtienes la nomenclatura del estilo C estándar del enlazador.

En C ++, el nombre / símbolo de las funciones se renombra en realidad a otra cosa, de modo que diferentes clases / espacios de nombres pueden tener funciones de las mismas firmas. En C, las funciones están definidas globalmente y no se necesita un proceso de cambio de nombre personalizado.

Para hacer que C ++ y C hablen entre sí, “C externo” indica al comstackdor que no use la convención C.

Debe tenerse en cuenta que la extern "C" también modifica los tipos de funciones. No solo modifica las cosas en niveles inferiores:

 extern "C" typedef void (*function_ptr_t)(); void foo(); int main() { function_ptr_t fptr = &foo; } // error! 

El tipo de &foo no es igual al tipo que designa typedef (aunque el código es aceptado por algunos, pero no todos los comstackdores).

extern C afecta el cambio de nombre por el comstackdor de C ++. Es una forma de hacer que el comstackdor de C ++ no destruya los nombres, o más bien que los manipule del mismo modo que un comstackdor de C. Esta es la forma en que las interfaces C y C ++.

Como ejemplo:

 extern "C" void foo(int i); 

permitirá que la función se implemente en un módulo C, pero permitirá que se llame desde un módulo C ++.

El problema surge cuando intentamos obtener un módulo C para llamar a una función C ++ (obviamente C no puede usar clases C ++) definida en un módulo C ++. Al comstackdor de C no le gusta la extern "C" .

Entonces necesitas usar esto:

 #ifdef __cplusplus extern "C" { #endif void foo(int i); #ifdef __cplusplus } #endif 

Ahora, cuando aparece en un archivo de cabecera, tanto los comstackdores C como C ++ estarán contentos con la statement y ahora se podría definir en un módulo C o C ++, y se puede invocar mediante código C y C ++.

Extern “C” denota que el código adjunto usa un estilo de enlace C y un cambio de nombre. C ++ usa un formato de creación de nombres más complejo. Aquí hay un ejemplo:

http://en.wikipedia.org/wiki/Name_mangling

 int example(int alpha, char beta); 

en C: _example

en C ++: __Z7exampleic

Actualización: Como notas de GManNickG en los comentarios, el patrón de manipulación de nombres depende del comstackdor.

extern “C”, es una palabra clave para declarar una función con enlaces C, porque el comstackdor C y el comstackdor C ++ traducirán el código fuente a una forma diferente en el archivo objeto:

Por ejemplo, un fragmento de código es el siguiente:

 int _cdecl func1(void) {return 0} int _stdcall func2(int) {return 0} int _fastcall func3(void) {return 1} 

Los comstackdores de C de 32 bits traducirán el código en el formulario de la siguiente manera:

 _func1 _func2@4 @func3@4 

en el cdecl, func1 se traducirá como ‘ _name

en stdcall, func2 se traducirá como ‘ _name @ X

en la llamada rápida, func2 se traducirá como ‘ @ nombre @ X

X ‘ significa la cantidad de bytes de los parámetros en la lista de parámetros.

La convención de 64 bits en Windows no tiene subrayado inicial

En C ++, se introducen clases, plantillas, espacios de nombres y sobrecarga del operador, ya que no se permiten dos funciones con el mismo nombre, el comstackdor de C ++ proporciona la información del tipo en el nombre del símbolo,

por ejemplo, un fragmento de código es el siguiente:

 int func(void) {return 1;} int func(int) {return 0;} int func_call(void) {int m=func(), n=func(0);} 

El comstackdor de C ++ traducirá el código de la siguiente manera:

 int func_v(void) {return 1;} int func_i(int) {return 0;} int func_call(void) {int m=_func_v(), n=_func_i(0);} 

‘_v’ y ‘_i’ son tipo de información de ‘void’ e ‘int’

Aquí hay una cita de msdn

“La palabra clave extern declara una variable o función y especifica que tiene una vinculación externa (su nombre es visible desde archivos distintos a aquel en el que está definida). Al modificar una variable, extern especifica que la variable tiene una duración estática (se asigna cuando el progtwig comienza y se desasigna cuando el progtwig finaliza). La variable o función puede definirse en otro archivo fuente, o más adelante en el mismo archivo. Las declaraciones de variables y funciones en el scope del archivo son externas por defecto. ”

http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx