C与C++的相互调用

我们经常再写代码时会使用C与C++混合编程,但是在调用对方接口时我们为了避免出现问题会使用extern “C”。
1、出现的问题
在C++中,为了支持重载机制,在编译时,要对函数的名字进行一些处理,比如加入函数的返回类型等来加以区别;这也就是C++中的函数命名规则。如函数int sum(int a,int b)在编译过程中会生成 ?sum@@YAHHH@Z这样的符号,这也是C++可以实现重载的原因。
在 C中,只是简单的函数名字而已。C则把该函数编译成类似_sum的符号,C链接器只要找到该函数符号就可以链接成功,它假设参数类型信息是正确的。
所以,关键问题是,C和C++在编译时生成函数名字的方式是不同的。所以会出现调用不成功的现象。
2、方法
所以我们使用extern “C”。它是指在C++中告诉编译器按照C的规则来处理,直接使用函数名而不是重新生成。
3、C++调用C

 //Compare.c
    int Compare(int a,int b)
    {
    return a>b?1:-1;
    }
//main.cpp
extern "C"
{
extern int Compare(int int)//这样就会生成_Compare的符号和c语言符号保持一致。
}
int main()
{
Compare(10,20);
return 0;
}

这样就可以调用成功。
也就是大致规则是这样

extern "C"
{
//代码块;
}
//extern "C"中包含的代码块以C语言规则处理

4、C调用C++

//Compare.c
    int Compare(int a,int b)
   // {
   // return a > b ? 1 : -1;
   //}
    int main()
    {
    Compare(10,20);
    return 0;
}

我们现在在.c文件中给出主函数,而且只给出函数的声明。
在主函数中给出函数的声明,也就是在c语言中调用C++的代码。

//main.cpp
int Compare(int a,int b)
{
return a>b ? 1 : -1;
}

这样我们发现是无法调用成功的。也就是只能是后者调用前者无法前者调用后者。因为是C出现比C++早。所以我们只需要在C++中改。加入extern "C"以及整个函数的实现。具体如下:

//main.cpp
extern "C"
{
int Compare(int a,int b)
 {
return a>b ? 1 : -1;
 }
}

这样就可以调用成功。但是这种情况也是基于C++的文件可以被改动的情况下。
那么不能改动的情况下又是怎样的?
5、C调用C++的库函数(C++的文件不能被改动)
这时候我们加中间层,这个中间层使我们要调用函数时自己写的函数。

 int Mycompare(int a,int b)
 {
 return Compare(a,b);
}

然后只需要在.c中调用Mycompare函数即可。

//middle.cpp
int Mycompare(int a,int b);
int main()
{
Mycompare(10,20);
}

然后在我们自己写的函数中加extern “C”

//middle.cpp
int Compare(int a,int b);
extern "C"
{
 int Mycompare(int a,int b)
 {
 return Compare(a,b);
 }
}

这样就可以调用成功。
6、函数所在的文件不确定以怎样的编译器编译
我们使用C++特有的宏 __cplusplus来处理。

//sum.cpp
#ifdef __cplusplus
extern "C"
{
#endif
int Sum(int a,int b)
{
return a + b;
}
#ifdef __cplusplus
}
#end

a.c

#ifdef __cplusplus
extern "C"
{
#endif
int Sum(int a,int b)
{
return a + b;
}
#ifdef __cplusplus
}
#end
sum.c
int Sum(int,int)
int main()
{
sum(10,20);
rerurn 0;
}

我们在C和C++的文件中同时写成上述的代码,我们会发现在C语言中都能被调用成功。原因是:因为__cplusplus是C++特有的宏所以在C++中会命中第一行的extern "C"这样就会在C++中形成这样的代码:

extern "C"
{
int Sum(int a,int b)
{
return a + b;
}
}

这样在C++中有extern "C"会以C语言的规则来处理也就是会生成_sum的符号。这样就会调用成功。
但是在C中因为没有 __cplusplus这样的宏,它的第一行就不能命中也就是没有extern “C”,他就会形成这样的代码:

 int Sum(int a,int b)
  { 
  return a + b;
  }

这样生成的符号也是_sum所以他也能调动成功。
所以当我们不确定是以哪种编译器编译时,写成这样的代码,加入__cplusplus宏,在C和C++中都可以调用成功。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值