from example ejemplo c++ c extern extern-c

c++ - example - ¿Se requiere extern "C" solo en la declaración de función?



extern function c (6)

Acabo de encontrar esta situación ... No es una experiencia agradable.

Lo siguiente fue declarado en uno de mis archivos c :

void unused_isr(void) {} void ADC_IRQHandler(void) __attribute__ ((weak, alias("unused_isr")));

A continuación en algún lugar en un archivo cpp que he definido:

void ADC_IRQHandler(void) { ... }

Y me olvidé de cambiar la declaración hacia adelante para:

void ADC_IRQHandler(void);

Me tomó un tiempo antes de darme cuenta de que estaba haciendo todo bien con respecto a la conversión de AD, ¡pero no pude agregar "extern C" a la definición!

extern "C" void ADC_IRQHandler(void) { ... }

Solo mis dos centavos por qué podría ser útil en ciertas circunstancias tener el hábito de agregarlo a la definición también.

Escribí una función de C ++ a la que necesito llamar desde un programa en C. Para hacerlo llamable desde C, especificé extern "C" en la declaración de función. Luego compilé el código C ++, pero el compilador (Dignus Systems / C ++) generó un nombre mutilado para la función. Por lo tanto, al parecer no cumplió con el extern "C" .

Para resolver esto, agregué extern "C" a la definición de la función. Después de esto, el compilador generó un nombre de función que se puede llamar desde C.

Técnicamente, la extern "C" solo debe especificarse en la declaración de función. ¿Es esto correcto? (El C ++ FAQ Lite tiene un buen ejemplo de esto). ¿También debería especificarlo en la definición de la función?

Aquí hay un ejemplo para demostrar esto:

/* ---------- */ /* "foo.h" */ /* ---------- */ #ifdef __cplusplus extern "C" { #endif /* Function declaration */ void foo(int); #ifdef __cplusplus } #endif /* ---------- */ /* "foo.cpp" */ /* ---------- */ #include "foo.h" /* Function definition */ extern "C" // <---- Is this needed? void foo(int i) { // do something... }

Mi problema puede ser el resultado de codificar incorrectamente algo, o puede que haya encontrado un error en el compilador. En cualquier caso, quería consultar stackoverflow para asegurarme de saber cuál es técnicamente la forma "correcta".


Creo que es necesario aclarar esto aquí, ya que tuve un problema similar y me tomó un tiempo aclararlo, solo Brooks Moses lo mencionó correctamente, y creo que es necesario explicarlo con mayor claridad ... .

En resumen, el encabezado puede descartarlo, todo lo que el compilador ve es el archivo cpp y si el encabezado no se incluye con la "C" externa en su cpp (que generalmente veo), entonces la "C" externa deberá Estar en el archivo cpp en alguna parte (ya sea en la definición o en otra declaración) para que el compilador CXX sepa cómo hacerlo con el enlace C, al compilador no le importa el encabezado, solo el enlazador.


Debería estar alrededor de ambos. El compilador debe saber usar el nombre del símbolo C y las convenciones de llamada al compilar los sitios de llamada (que solo pueden ver una declaración), y el compilador también debe saber para generar el nombre del símbolo C y usar las convenciones de llamada C al compilar Definición de la función en sí misma (que puede no ver ninguna otra declaración).

Ahora, si tiene una declaración extern-C que es visible desde la unidad de traducción en la que existe la definición, es posible que pueda dejar de lado la definición de extern-C, pero no lo sé con seguridad. .


La extern "C" no debe ser requerida en la definición de la función siempre que la declaración lo tenga y ya se vea en la compilación de la definición. La norma establece específicamente (7.5 / 5 especificaciones de vinculación):

Se puede declarar una función sin una especificación de vinculación después de haber visto una especificación de vinculación explícita; el enlace explícitamente especificado en la declaración anterior no se ve afectado por dicha declaración de función.

Sin embargo, generalmente también pongo el '' extern "C" en la definición, porque de hecho es una función con enlace externo "C". Mucha gente odia cuando es innecesario, las cosas redundantes están en las declaraciones (como poner anulaciones virtual en el método), pero yo no soy uno de ellos.


No se requiere la extern "C" alrededor de la definición. Puedes salirte con solo ponerlo alrededor de la declaración. Una nota en tu ejemplo ...

#ifdef __cplusplus extern "C" { #endif /* Function declaration */ void foo(int); #ifdef __cplusplus } #endif

Su código está buscando la macro del preprocesador " __cplusplus ".

Si bien se implementa comúnmente, dependiendo de su compilador, esto puede o no definirse. En su ejemplo, también usa extern "C" la declaración, pero no está comprobando la macro " __cplusplus ", por lo que sospecho que funcionó una vez que lo hizo.

Vea los comentarios a continuación: C ++ estándar requiere que la macro __cplusplus sea ​​definida por el preprocesador.


Editar:
Parece que había entendido mal la pregunta. De todos modos, lo intenté:

// foo.cpp /* Function definition */ #include "foo.h" void foo(int i) { //do stuff } void test(int i) { // do stuff } // foo.h #ifdef __cplusplus extern "C" { #endif /* Function declaration */ void foo(int); #ifdef __cplusplus } #endif void test(int);

Usando el comando nm para ver los símbolos del archivo compilado:

linuxuser$ nm foo.o 00000006 T _Z4testi U __gxx_personality_v0 00000000 T foo

Esto sugiere claramente que el nombre de la función declarada como "C" externa no está alterado y la palabra clave "C" externa no se requiere en la definición.
Si hubiera requerido que cada código de la biblioteca C escrito sin extern "C" hubiera sido inutilizable en los programas de C ++.