extern “C”总结

简介:

经常看到如下代码:

#ifdef _cplusplus

extern "C" {

#endif

#include "XXX.h"

#ifdef _cplusplus

}

#endif

解释:

extern "C"的作用是,告诉C++编译器,下面的代码按照C的方式进行编译,说白了,不要对这些函数进行名字重整(function name mangling)。通常在C++程序中使用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 ;

}

本文转自zdd博客园博客,原文链接:http://www.cnblogs.com/graphics/archive/2010/12/24/1916343.html ,如需转载请自行联系原作者
相关文章
|
2月前
|
存储 编译器 C语言
详解C/C++中的static和extern
本文详解了C/C++中`static`和`extern`关键字的用法和区别,通过具体代码示例说明了在不同情境下如何正确使用这两个关键字,以及`extern "C"`在C++中用于兼容C语言库的特殊作用。
详解C/C++中的static和extern
|
5月前
|
C语言
【C语言】:static和extern的详细介绍和使用
【C语言】:static和extern的详细介绍和使用
39 1
|
6月前
|
存储 C语言
static和extern
`static`和`extern`是C语言的关键字。`static`用于修饰局部变量、全局变量和函数,改变它们的生命周期和作用域。局部静态变量在函数结束后不会销毁,保持其值直到程序结束。全局静态变量限制为只在当前源文件可见,减少命名冲突。`extern`则用于声明外部已定义的符号,使得在其他文件中可以访问该全局变量或函数。总的来说,`static`和`extern`影响变量和函数的可见性和存储持续时间。
36 0
|
6月前
|
存储 C语言
static和extern详解
static和extern详解
51 0
|
编译器 C++
在 C++ 中命名 Mangling 和 extern “C”
C++ 支持函数重载,即可以有多个同名但不同参数的函数。C++ 编译器在生成目标代码时如何区分不同的函数——它通过添加有关参数的信息来更改名称。这种向函数名称添加附加信息的技术称为Name Mangling。C++ 标准没有指定任何特定的名称修改技术,因此不同的编译器可能会向函数名称附加不同的信息。 
101 0
|
存储 数据库 开发者
extern,const,#define
extern,const,#define
73 0
|
C#
都是用 DllImport?有没有考虑过自己写一个 extern 方法?
原文 都是用 DllImport?有没有考虑过自己写一个 extern 方法? 你做 .NET 开发的时候,一定用过 DllImport 这个特性吧,这货是用于 P/Invoke (Platform Invoke, 平台调用) 的。
945 0
|
C++ 编译器 C语言
|
移动开发 编译器 C语言