现在的位置: 首页 > 综合 > 正文

extern C实现C与C++函数的相互调用

2018年03月21日 ⁄ 综合 ⁄ 共 2105字 ⁄ 字号 评论关闭

http://www.cnblogs.com/graphics/archive/2010/12/24/1916343.html

 

经常看到如下代码:

#ifdef
_cplusplus

extern
"C" {

#endif

#include
"XXX.h"

#ifdef
_cplusplus

}

#endif

解释:

这段代码的含义是,如果当前的程序是C++程序,那么下面引用的头文件是C文件, 那如果当前程序不是C++呢?难道包含的就不是C文件了么?当然不是,不管当前程序是什么,这个XXX.h都是一个C文件

那为什么还要多此一举呢?

原因:

C++为了支持函数重载,将编译后的函数名做了重整(mangled name),比如下面的函数

int add(int
a, int b) ;

C中编译完的名字就是add,而在C++中,编译完就变成了add_int_int(举例而已,实际因编译器而异),这样在函数名字后面加上参数的类型,就可以区分不同的重载函数了,比如还有另一个函数

float
add(float a, float b) ;

C++中,它会被编译成add_float_float,这就是C++区分重载函数的机制

可是问题也随之而来

C++进行名字重整,而C不进行重整。当C++程序引用C的函数时,它会按照重整后的名字去目标文件(.obj)中去寻找对应的函数,而目标文件中存放的却是C版本的函数,名字对不上,所以根本找不到!

怎么办呢?

这就是extern
C 存在的一个原因了

它告诉C++,包含在extern C{ //}块中的东西是C版本的,你编译的时候不要进行名字重整,否则你链接的时候就无法找到我!

于是上面的代码也就不难理解了,光说不练是扯淡,上代码

我们简单的定义一个C头文件和实现文件,只包含一个add函数

CClass.h 内容如下

#ifndef
__CClass_H__

#define
__CClass_H__

extern int
add(int a, int b) ;

#endif //
end __CClass_H__

CClass.c 内容如下

#include
"CClass.h"

int add(int
a, int b)

{

return a + b
;

}

下面我们用一个C++程序来引用这个C文件

main.cpp 内容如下

#define
_cplusplus //
为了测试,强加一句

#ifdef
_cplusplus

extern
"C" {

#endif

#include
"CClass.h"

#ifdef
_cplusplus

}

#endif

#include
<iostream>

using
namespace std ;

int
main(void)

{

int result =
add(1, 2) ;

cout
<< result << endl ;

system("pause")
;

return 0 ;

}

如果没有#include
<iostream>
之前那些代码而只是仅仅包含

#include
"CClass.h"
一句

你就会得到下面的错误

error
LNK2019:unresolved external symbol "int __cdecl add(int,int)"
(?add@@YAHHH@Z) referenced in function _main

显然这是一个链接错误,因为找不到对应的函数定义

当然你也可以简写成下面的形式,直接在extern C”块中包含你想调用的函数

extern
"C"

{

int add(int
a, int b) ;

};

#include
<iostream>

using
namespace std ;

int
main(void)

{

int result =
add(1, 2) ;

cout
<< result << endl ;

system("pause")
;

return 0 ;

}

这在C++程序中是没有问题的,但是如果是在C程序中,则会出现编译错误,因为C中不允许extern C”出现

另一个需要extern C”的场合是当C程序调用C++的东西时

按照如下步骤做即可

1.
C++.h文件中用extern C{}声明将被C程序使用的函数

2.
C++.cpp文件中实现上面的函数

3.
.c文件中用extern声明要使用的C++函数

4.
使用即可

注意:切不可在.c文件中包含C++.h文件,那样编译无法通过

上代码:

 

CPPClass.h中声明add函数

#ifndef
__CPPClass_H__

#define
__CPPClass_H__

extern
"C"

{

int add(int
a, int b) ;

};

#endif //
end __CPPClass_H__

 

CPPClass.cpp实现add函数

#include
"CPPClass.h"

int add(int
a, int b)

{

return a + b
;

}

 

main.c
内容如下

#include
<stdio.h>

//#include
"CPPClass.h" //
不要包含头文件,否则编译不过

extern int
add(int a, int b) ; //
只需显示声明要调用的函数即可

int
main(void)

{

         int result = add(1, 2) ; //使用函数

         printf("%d", result) ;

         return 0 ;

}

 

 

【上篇】
【下篇】

抱歉!评论已关闭.