2011-01-04 5 views
6

Voglio essere in grado di utilizzare Cmockery per simulare le funzioni C chiamate dal codice C++ che sto testando. Come un passo verso questo, ho rinominato l'esempio Cmockery run_tests.c a run_tests.cpp, e sto cercando di compilare e collegare con cmockery.c:Come posso compilare e collegare il codice C++ con il codice C compilato?

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 

Le prime due righe di comando (per la compilazione) hanno successo , ma dopo l'ultimo ottengo:

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 

Quel simbolo non definito è dalla linea 29 di run_tests.cpp:

return run_tests(tests); 

I run_tests() funzione è definita in cmocker y.c.

Dopo aver letto "Linking C++ code with 'gcc' (without g++)", ho provato:

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

ma ho ottenuto lo stesso risultato:

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 

Come compilo e codice di collegamento C++ in modo che trova i simboli in codice C?

+0

Nessuna delle risposte (al momento della scrittura di questo commento) chiarisce che non è necessario modificare cmockery.h. Posso inserire la dichiarazione "extern" C "' attorno a '#include ' in run_tests.cpp. Accetterò la prima risposta per chiarire questo punto. –

risposta

7

penso che si può ottenere thinkgs di collegare da C++ aggiungendo il seguente intorno alle contenuto del file cmockery.h:

o vicino all'inizio:

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

o in prossimità della end:

#if defined(__cplusplus) 
} 
#endif 

in questo modo, l'uso dell'intestazione in sorgenti C ignorerà la parte extern "C" della dichiarazione, ma quando l'intestazione è include in C++ costruisce, la al compilatore verrà detto correttamente che il collegamento per le dichiarazioni in quell'intestazione usa la semantica C.

un rapido test-n-sporco o se si preferisce non modificare l'intestazione, si può provare:

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

ma la mia preferenza sarebbe quella di mettere il blocco extern "C" nell'intestazione (e solo intorno alle cose che sono richieste - potrebbe essere necessario un po 'di analisi).

+0

Perché pensi di mettere il 'extern" C "' attorno a '# include'" quick-n-dirty "? –

+0

Nel caso generale perché potrebbe applicare il modificatore 'extern 'C" 'a cose che non se lo aspettano (in particolare se l'intestazione include altre intestazioni che sono a conoscenza di C++). Le intestazioni potrebbero gestirlo usando la specifica di dichiarazione 'extern 'C++" ', ma ho visto solo quella usata una volta per gestire questo caso (probabilmente perché è poco conosciuto, e non è necessario quasi quanto l'extern" C " 'versione). –

5

nei file di intestazione incluso dal codice C++, è necessario extern "C" dichiarazioni per tutte le funzioni che vengono compilati in C.

2

quando si includono i file header C da C++, avete avvolto i prototipi con extern "C" { .... }? Se non si specifica il nome della funzione C++, sarà "storpiato" al momento del collegamento.

2

Come ha detto Karl, è necessario extern "C" { .. }.

Il motivo: C++ maneggia i nomi (aggiunge caratteri divertenti) in modo che il collegamento sia sicuro. C non lo è, quindi in quella lingua il collegamento da foo(int) a foo(double) è possibile (ma sbagliato e imbarazzante).

Per un'interoperabilità di successo, è necessario comunicare al compilatore C++ che alcuni nomi di funzioni non devono essere alterati, in modo che il collegamento abbia esito positivo.