extern “C”的作用详解(2)

上面也提到过,由于C++支持函数重载,而C语言不支持,因此函数被C++编译后在符号库中的名字是与C语言不同的;C++编译后的函数需要加上参数的类型才能唯一标定重载后的函数,而加上extern "C"后,是为了向编译器指明这段代码按照C语言的方式进行编译

未加extern "C"声明时的链接方式:

//模块A头文件 moduleA.h

#idndef _MODULE_A_H

#define _MODULE_A_H

 

int foo(int x, int y);

#endif 

在模块B中调用该函数:

//模块B实现文件 moduleB.cpp

#include"moduleA.h"

foo(2,3); 

实际上,在链接阶段,链接器会从模块A生成的目标文件moduleA.obj中找_foo_int_int这样的符号,显然这是不可能找到的,因为foo()函数被编译成了_foo的符号,因此会出现链接错误。

常见的做法可以参考下面的一个实现(moduleA、moduleB两个模块,B调用A中的代码,其中A是用C语言实现的,而B是利用C++实现):

//moduleA头文件

#ifndef __MODULE_A_H //对于模块A来说,这个宏是为了防止头文件的重复引用

#define __MODULE_A_H

int fun(int, int);

#endif

 

//moduleA实现文件moduleA.C //模块A的实现部分并没有改变

#include"moduleA"

 

int fun(int a, int b)

{

    return a+b;

}

 

//moduleB头文件

#idndef __MODULE_B_H //很明显这一部分也是为了防止重复引用

#define __MODULE_B_H

 

#ifdef __cplusplus //而这一部分就是告诉编译器,如果定义了__cplusplus(即如果是cpp文件, extern "C"{ //因为cpp文件默认定义了该宏),则采用C语言方式进行编译

 

#include"moduleA.h"

#endif

 

… //其他代码

 

#ifdef __cplusplus

}

#endif

#endif

 

//moduleB实现文件 moduleB.cpp //B模块的实现也没有改变,只是头文件的设计变化了

#include"moduleB.h"

int main()

{

    cout<<fun(2,3)<<endl;

}

extern "C"的使用要点总结

可以是如下的单一语句

extern "C" double sqrt(double);

可以是复合语句, 相当于复合语句中的声明都加了extern "C"

extern "C"

{

      double sqrt(double);

      int min(int, int);

}

可以包含头文件,相当于头文件中的声明都加了extern "C"

extern "C"

{

    #i nclude <cmath>

} 

不可以将extern "C" 添加在函数内部

如果函数有多个声明,可以都加extern "C", 也可以只出现在第一次声明中,后面的声明会接受第一个链接指示符的规则。

除extern "C", 还有extern "FORTRAN" 等。

Linux公社的RSS地址https://www.linuxidc.com/rssFeed.aspx

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/d5cc098cc9ec995e8e50dbb7f3ba148d.html