clang define extern c
extern "C" 在C/C++中的用法
- 无论是C++调用C api 还是C调用C++ API, 必须先在API所对应得头文件对API进行 extern "C"声明,并用#ifdef __cplusplus进行保护。
- extern "C" 的作用是告诉C++编译器,函数名在编译的时候按照C的格式来进行处理,不要添加冗余的字段。
#ifndef TEST_C
#define TEST_C
#ifdef __cplusplus
extern "C" {
#endif
int add(int a, int b);
#ifdef __cplusplus
}
#endif
#endif
前言
在重构sample sdk代码,并编译成静态或动态库来提供给上层调用的API时,不可避免会遇到c++调用c或c调用c++的问题。看我博客的网友也提到了这个问题,所以藉这个机会来把C和C++混合编程(即相互调用)的问题透彻的弄清楚。
问题背景
C和C++直接相互调用 之所以会出问题的原因是, C++里面有函数重载的概念,从而导致编译出来的函数名会带上参数类型,而C编译出来的函数名简单的就是其本身。
下面定义了两个简单的c、c++头文件和实现文件
/test_c.h/
#ifndef TEST_C
#define TEST_C
int add(int a, int b);
#endif
/test_c.c/
#include "test_c.h"
int add(int a, int b)
{
int c;
c = a + b;
return c;
}
/test_c++.h/
#ifndef TEST_C_PLUSPLUS
#define TEST_C_PLUSPLUS
int substract(int a, int b);
#endif
/test_c++.cpp/
#include "test_c++.h"
int substract(int a, int b)
{
int c;
c = a - b;
return c;
}
分别使用两个命令生成obj文件。
gcc -c test_c.c
gcc -c test_c++.cpp
然后使用命令: nm test_c.o | grep add 和 nm test_c++.o | grep substract 得到如下结果:
add 和 _Z9substractii。 这个结果进一步验证了前面所说的,即C和C++编译出来的函数名会不一样。
C调用C++
添加一个C测试文件main.c,并调用add和substract API。
/main.c/ int main(void) } gcc test_c.c test_c++.cpp main.c -o test_c 解决办法就是引入 extern "C"。 关于它有两个重要注意点: 1)extern "C"是c++语法,只能被c++编译器认识,其目的就是告诉C++编译器,其被extern "C"所包含的函数得以C方式(即简单函数名)去链接。 2) 为了避免C编译器来编译它来产生编译错误, 保险起见,会将 extern "C" {和}用#ifdef _cplusplus... #endif修饰起来。这里很容易犯得一个错误就是 cplusplus前面是两根下划线""。 回到上面得错误,我们得在test_c++.cpp编译时,得用c方式去来生成substract函数。所以test_cpp.h更新如下,并用__cplusplus保护起来,避免main.c编译时报错。 /test_c++.h/ #ifdef __cplusplus int substract(int a, int b); #ifdef __cplusplus #endif C++调用C /main.cpp/ int main(void) } 同样地,必须在test_c.h里面添加extern ”C“来告诉main.cpp编译链接时得以c方式来寻找add函数。同时使用__cplusplus修饰避免 test_c.c编译失败。 /test_c.h/ #ifdef __cplusplus int add(int a, int b); #ifdef __cplusplus 结论
#include
#include "test_c.h"
#include "test_c++.h"
{int x = 3;
int y = 5;
printf("add = %d \n", add(x, y));
printf("sub = %d \n", substract(x, y));
return 0;
使用命令如下来将它们编译成一个可执行文件test_c:
但这个时候会报链接错误: main.c:(.text+0x43): undefined reference to 'substract' 。明明我们在test_c++.cpp里面定义了substract(),但是main.c不识别。 这也说明了 c直接调用c++代码出现错误。
#ifndef TEST_C_PLUSPLUS
#define TEST_C_PLUSPLUS
extern "C" {
#endif
}
#endif
再次编译链接: gcc test_c.c test_c++.cpp main.c -o test_c没有问题,并执行./test_c 结果也完全正确。
添加一个C++测试文件main.cpp来调用add和substract。
#include
#include "test_c.h"
#include "test_c++.h"
{int x = 3;
int y = 5;
printf("add = %d \n", add(x, y));
printf("sub = %d \n", substract(x, y));
return 0;
使用类似命令来编译链接: gcc test_c.c test_c++.cpp main.cpp -o test_cpp,结果也出现main.cpp里面找不到定义在test_c.c里面得add函数。
#ifndef TEST_C
#define TEST_C
extern "C" {
#endif
}
#endif
#endif
使用编译链接命令:gcc test_c.c test_c++.cpp main.cpp -o test_cpp 没有问题,并执行./test_cpp 结果也完全正确。
无论是C++调用C api 还是C调用C++ API, 必须先在API所对应得头文件对API进行 extern "C"声明,并用#ifdef __cplusplus进行保护。
————————————————
版权声明:本文为CSDN博主「ltshan139」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/avideointerfaces/article/details/97765339