我希望能够使用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
该未定义的符号来自run_tests.cpp的第29行:
return run_tests(tests);
run_tests()函数在cmockery.c中定义。
阅读“Linking C++ code with 'gcc' (without 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代码中找到符号?
答案 0 :(得分:7)
我认为您可以通过在cmockery.h文件的内容周围添加以下内容来使thinkgs从C ++链接:
在开头或附近:
#if defined(__cplusplus)
extern "C" {
#endif
在结束时或附近:
#if defined(__cplusplus)
}
#endif
这样,在C源代码中使用头文件将忽略声明的extern "C"
部分,但是当在C ++版本中包含头部时,编译器将被正确地告知其中的声明的链接header使用C语义。
对于快速肮脏的测试,或者如果您不想修改标题,可以尝试:
extern "C" {
#include "cmockery.h"
}
但我的偏好是将extern "C"
块放在标题中(并且只围绕所需的内容 - 可能需要进行一些分析)。
答案 1 :(得分:5)
在C ++代码包含的头文件中,您需要{C}编译的所有函数的extern "C"
声明。
答案 2 :(得分:2)
当您从C ++中包含C头文件时,是否已使用extern "C" { .... }
包装原型?如果不这样做,C ++函数名称将在链接时被“损坏”。
答案 3 :(得分:2)
正如卡尔所说,extern "C" { .. }
是必需的。
原因:C ++破坏名称(添加有趣的字符),以便链接是类型安全的。 C没有,因此将foo(int)
与foo(double)
联系起来的语言是可能的(但错误且令人尴尬)。
为了成功实现互操作性,您需要告诉C ++编译器一些函数名称不会被破坏,以便链接成功。