2011-01-04 35 views
6

Quiero ser capaz de usar Cmockery para simular funciones C llamadas desde el código C++ que estoy probando. Como paso previo a eso, he cambiado el nombre del ejemplo Cmockery run_tests.c a run_tests.cpp, y estoy tratando de compilar y enlazar con cmockery.c:¿Cómo puedo compilar y vincular código C++ con código C compilado?

g++ -m32 -DHAVE_CONFIG_H -DPIC -I ../cmockery-0.1.2 -I /usr/include/malloc -c run_tests.cpp -o obj/run_tests.o 
gcc -m32 -DHAVE_CONFIG_H -DPIC -Wno-format -I ../cmockery-0.1.2 -I /usr/include/malloc -c ../cmockery-0.1.2/cmockery.c -o obj/cmockery.o 
g++ -m32 -o run_tests obj/run_tests.o obj/cmockery.o 

Las dos primeras líneas de comando (compilar) tienen éxito , pero después de la última consigo:

Undefined symbols: 
    "_run_tests(UnitTest const*, unsigned long)", referenced from: 
     _main in run_tests.o 
ld: symbol(s) not found 
collect2: ld returned 1 exit status 

Ese símbolo no definido es de la línea 29 de run_tests.cpp:

return run_tests(tests); 

los run_tests() se define en cmocker y.c.

Después de leer "Linking C++ code with 'gcc' (without g++)", he intentado:

gcc -lstdc++ -m32 -o run_tests obj/run_tests.o obj/cmockery.o 

pero no obtuvo el mismo resultado:

Undefined symbols: 
    "_run_tests(UnitTest const*, unsigned long)", referenced from: 
     _main in run_tests.o 
ld: symbol(s) not found 
collect2: ld returned 1 exit status 

¿Cómo compilar y enlazar código C++ por lo que encuentra los símbolos en el código C?

+0

Ninguna de las respuestas (en el momento de escribir este comentario) deja en claro que no es necesario modificar cmockery.h. Puedo poner la declaración de '' extern "C '' alrededor del' #include 'en run_tests.cpp. Aceptaré la primera respuesta para dejar esto en claro. –

Respuesta

7

creo que se puede obtener thinkgs a enlazar desde C++ añadiendo lo siguiente en torno a los contenidos del archivo cmockery.h:

en o cerca del comienzo:

#if defined(__cplusplus) 
extern "C" { 
#endif 

En o cerca del final:

#if defined(__cplusplus) 
} 
#endif 

de esta manera, el uso de la cabecera en las fuentes de C ignorará la parte extern "C" de la declaración, pero cuando la cabecera es incluir en C++ construye, la al compilador se le dirá correctamente que el enlace para las declaraciones en ese encabezado usa la semántica C.

Para una prueba rápida-n-sucia o si usted prefiere no modificar la cabecera, puede intentar:

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

pero mi preferencia sería poner el bloque extern "C" en la cabecera (y sólo todo lo que se requiere, que podría necesitar un poco de análisis).

+0

¿Por qué consideras poner el 'extern" C "' alrededor de '# include'" quick-n-dirty "? –

+0

En el caso general, porque podría aplicar el modificador 'extern 'C" 'a cosas que no lo esperan (en particular si el encabezado incluye otros encabezados que son conscientes de C++). Los encabezados pueden manejar esto usando la especificación de declaración 'extern 'C++" ', pero solo he visto que se usó una vez para manejar este caso (probablemente porque es poco conocido, y no es tan necesario como el' extern 'C" 'versión). –

5

En los archivos de cabecera incluida por el código C++, es necesario extern "C" declaraciones para todas las funciones que se compilan en C.

2

cuando se incluyen los archivos de cabecera de C de C++, ¿ha envuelto los prototipos con extern "C" { .... }? Si no lo hace, el nombre de la función C++ será 'destrozado' en el momento del enlace.

2

Como dijo Karl, se necesita extern "C" { .. }.

Motivo: C++ transforma los nombres (agrega caracteres divertidos) para que el enlace sea seguro. C no, por lo que en ese idioma es posible vincular foo(int) a foo(double) (pero es incorrecto y embarazoso).

Para una interoperabilidad exitosa, necesita decirle al compilador de C++ que no se deben destruir algunos nombres de funciones para que los enlaces funcionen correctamente.

Cuestiones relacionadas