Как мне скомпилировать и связать код C++ с скомпилированным кодом C?
Я хочу иметь возможность использовать 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 ответа
Я думаю, что вы можете получить 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"
блок в заголовке (и только вокруг того, что требуется - это может потребовать немного анализа).
В ваших заголовочных файлах, включенных в ваш код C++, вам нужно extern "C"
объявления для всех функций, которые скомпилированы в C.
Когда вы включаете заголовочные файлы C из C++, вы обернули прототипы extern "C" { .... }
? Если вы этого не сделаете, имя функции C++ будет "искажено" во время ссылки.
Как сказал Карл, extern "C" { .. }
нужно.
Причина: C++ искажает имена (добавляет забавные символы), так что ссылки безопасны для типов. С не так на этом языке ссылки foo(int)
в foo(double)
возможно (но неправильно и неловко).
Для успешной функциональной совместимости вы должны сообщить компилятору C++, что некоторые имена функций не должны быть искажены, для того, чтобы связывание было успешным.