Как мне скомпилировать и связать код C ++ с скомпилированным кодом C? - PullRequest
6 голосов
/ 04 января 2011

Я хочу иметь возможность использовать Cmockery для имитации функций C, вызываемых из кода C ++, который я тестирую.В качестве шага к этому я переименовал пример Cmockery run_tests.c в run_tests.cpp, и пытаюсь скомпилировать и связать его с помощью cmockery.c:

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

.первые две командные строки (для компиляции) успешны, но после последней я получаю:

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

Этот неопределенный символ из строки 29 run_tests.cpp:

return run_tests(tests);

Run_testsФункция () определена в cmockery.c.

После прочтения « Связывание кода C ++ с« gcc »(без g ++) » я попытался:

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

Но получил тот же результат:

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 ++, чтобы он находил символы в коде C?

Ответы [ 4 ]

7 голосов
/ 05 января 2011

Я думаю, что вы можете получить thinkgs для ссылки из C ++, добавив следующее вокруг содержимого файла cmockery.h:

В начале или около этого:

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

Вили ближе к концу:

#if defined(__cplusplus)
}
#endif

Таким образом, использование заголовка в источниках C будет игнорировать часть объявления extern "C", но когда заголовок включен в сборки C ++, компилятор будет правильносказал, что связывание для объявлений в этом заголовке использует семантику C.

Для теста quick-n-dirty или если вы не хотите изменять заголовок, вы можете попробовать:

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

но я бы предпочел поместить в заголовок блок extern "C" (и только вокруг того, что требуется - это может потребовать небольшого анализа).

5 голосов
/ 04 января 2011

В ваших заголовочных файлах, включенных в ваш код C ++, вам нужны объявления extern "C" для всех функций, скомпилированных в C.

2 голосов
/ 05 января 2011

Как сказал Карл, extern "C" { .. } необходимо.

Причина: C ++ искажает имена (добавляет забавные символы), так что ссылки безопасны для типов.C не делает, поэтому на этом языке возможна ссылка foo(int) на foo(double) (но это неправильно и неловко).

Для успешного взаимодействия вы должны сообщить компилятору C ++, что некоторые имена функций не должны быть искажены, для того, чтобы ссылки были успешными.

2 голосов
/ 04 января 2011

когда вы включаете заголовочные файлы C из C ++, вы обернули прототипы extern "C" { .... }?Если вы этого не сделаете, имя функции C ++ будет «искажено» во время ссылки.

...