C++和C混合编程

最近经常看到头文件中有


#ifdef __cplusplus
extern "C" {
#endif

.......



#ifdef __cplusplus
}
#endif

这样的语句,一直搞不清楚是什么意思,今天终于闹明白了。

 

1.这种写法的由来

C++比C晚出现,C++代码如果能够调用C语言的代码,那么会更好的利用现有的成果,但是事实上C++代码是无法直接调用C代码的,这是因为C++编译器在编译.cpp文件时生成的函数名与C编译器在编译.c文件时生成的函数名是不一样的。

C++为了支持重载,其编译器在编译完成后会对原有的函数名进行修改,比如

test(int i)和

test(int i, int j)

这两个函数在编译完成后可能就会被C++编译器修改成:

_ZDtesti

_ZDtestii

这种样式

但是C编译器却不会修改函数名, 这样问题就就来了,如果在一个C++代码中包含一个声明C函数的头文件时,那么很可能在编译完成后,头文件中声明的这个C函数名会被修改!这样在C++代 码中使用这个C函数的时候就会发生找不到函数名的问题,事实上这个函数在C代码中是存在的,只不过C++编译器一厢情愿的把函数名修改了。那么如何解决呢?

2.解决办法

很简单,显式的告诉C++编译器,这段代码是用C语言编译的函数,你就不要把函数名转化为C++的格式了。


extern "C" {

    int socket_send(); // 明确的告诉C++编译器,这是一个用C语言编译的函数
    
}

这样C++编译器在执行这段代码时,识别到extern "C"关键字,就会以C编译器的方式来编译括号内的代码。

3.由此引发的问题

这样虽然在C++编译下没有问题了,但是如果一个.c文件再去包含这个头文件时,又会发生问题,因为extern "C"不是C语言的关键字,这样.c文件又不能包含这个头文件了。如何能够既让.cpp文件能够包含这个头文件,又能让.c文件能够包含这个头文件呢,于 是下面的写法就产生了:

使用条件编译的方式,如果判断是C++的编译器,就带上extern "C",如果是C的编译器就不带extern "C",由此,问题得到妥善解决。需要注意的是:__cplusplus是C++编译器内置的宏


#ifdef __cplusplus
extern "C" {
#endif

.......



#ifdef __cplusplus
}
#endif

注:更细致的解释可以参考https://www.cnblogs.com/x_wukong/p/5630143.html

注:本文只是关于C++调用C函数的讲解,关于C调用C++函数,C++调用C的库,C调用C++的库,这三种方式可以参考:

https://blog.csdn.net/lincoln_2012/article/details/50801080

https://blog.csdn.net/shaosunrise/article/details/81176880

https://blog.csdn.net/shaosunrise/article/details/81161064

这三篇文章都是非常全面的,并且相互补充。

 

后记:

在编译整个工程时,有可能加上extern "C"反倒是不对。

例如,你在A.h中使用了extern "C",A.c中进行了函数定义,然后在B.cpp中引用了A.h,并且调用了这个函数,但是编译报错。

原因是在编译这堆文件的Makefie中只指定了.cpp文件进行编译,所以g++根本没去编译A.c,这样一来,B.cpp包含的头文件A.h展开之后,虽然不会更改这个函数的名字,但是在链接时候还是找不到这个函数,所以报错。

解决防范是把A.c重命名为A.cpp,把A.h中的extern "C"去掉。这样一来,大家都是.cpp,也不会出现函数名字被更改的问题。

不过,在编译整个工程的时候可能问题原因有很多,需要去排查,先去看Makefile,如果源文件和头文件确定没问题,那基本上就是Makefile的问题,gcc和g++的问题。

 

2019.3.25记:

一直以来都是用起来看下文章,今天按照四种不同情况写了小程序,以后以此为模板。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值