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)" ([email protected]@[email protected]) 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 ;

}

时间: 2024-10-12 10:56:19

extern "C"的相关文章

extern 的使用

extern.h的头文件内 #pragma once extern int a; extern int b; int c;//这里会报错,因为是一个全局变量,被多次包含,相当于重定义. extern.cpp的文件内 #include"extern.h" int a = 3; int b = 4; int c = 5; main.cpp的文件内 #include"extern.h" #include<iostream> using namespace st

c/c++中static和extern使用

c/c++中static和extern使用 在C/C++中static和extern都能够用来修饰函数和变量,可是是有差别的. 内部函数和内部变量:仅仅能在文件内使用的函数和变量. 外部函数和外部变量:可以被其他文件使用的函数和变量. static 1 对函数 定义一个内部函数 static void test() { } 声明一个内部函数 static void test(); 2 对全局变量 定义一个内部变量 static int a; 3 对局部变量 定义一个生命周期较长的局部变量. vo

C语言extern的使用以及头文件*.h的内容格式注意

用VS2013 分开写多文件的程序,出现了许多重定义的问题,总结解决方法如下: 在*.h文件中使用以下的格式: #ifndef <标识> #define <标识> ...... ...... #endif <标识>在理论上来说可以是自由命名的,但每个头文件的这个"标识"都应该是唯一的.标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的"."也变成下划线,如:stdio.h #ifndef _STDIO_H_ #def

extern关键字

1.extern "C" void func(){...} extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定.告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的. 2.extern 变量 首先说一个错误的范例: 在一个源文件里定义了一个数组:char a[6]; 在另外一个文件里用下列语句进行了声明:extern char *a: 答案与分析:

关键字extern和static

extern有两个作用,第一个,当它与"C"一起连用时,如: extern "C" void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的,C++的规则在翻译这个函数名时会把fun这个名字变得面目全非,可能是[email protected]_int_int#%$也可能是别的,这要看编译器的"脾气"了(不同的编译器采用的方法不一样),因为C++支持函数的重载    第二,当e

static和extern使用 /static和const联合使用

static: 1.修饰局部变量,被static修饰局部变量,延长生命周期,跟整个应用程序有关 * 被static修饰局部变量,只会分配一次内存 * 被static修饰局部变量什么分配内存? 程序一运行就会给static修饰变量分配内存 2.修饰全局变量,被static修饰全局变量,作用域会修改,只能在当前文件下使用 extern:声明外部全局变量,注意:extern只能用于声明,不能用于定义 extern工作原理:先会去当前文件下查找有没有对应全局变量,如果没有,才回去其他文件查找 exter

C# 关键字extern用法

修饰符用于声明在外部实现的方法.extern 修饰符的常见用法是在使用 Interop 服务调入非 托管代码时与 DllImport 属性一起使用:在这种情况下,该方法还必须声明为 static,如下面的示例所示:[DllImport("avifil32.dll")]private static extern void AVIFileInit(); 注意 extern 关键字还可以定义外部程序集别名,使得可以从单个程序集中引用同一组件的不同版本. 将 abstract(C# 参考)和

c++多个源文件共用一个全局变量(extern 的用法)

例子: 头文件:state.h    源文件:state.cpp 其它源文件:t1.cpp   t2.cpp  t3.cpp,  这些源文件都包含头文件state.h. 需要定义一个全局变量供这些源文件中使用:方法如下 1.在 state.h声明全局变量: extern int a; 2.在state.cpp中定义该全局变量:int a = 10; 这样其它源文件就可以使用该变量啦 这里需要的是“声明”,不是“定义”!根据C++标准的规定,一个变量声明必须同时满足两个条件,否则就是定义:    

const/static/extern/self/super

一 .const 和 宏 的区别 const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. 编译时刻:宏是预编译(编译之前处理),const是编译阶段. 编译检查:宏不做检查,不会报编译错误,只是替换,const会编译检查,会报编译错误. 宏的好处:宏能定义一些函数,方法. const不能. 宏的坏处:使用大量宏,容易造成编译时间久,每次都需要重新替换. 注意: 有很多博客(Blog)描述宏时,说使用宏会消耗很多内存,这种说法并不正确.它并不会生

[C/CPP系列知识] C++中extern “C” name mangling -- Name Mangling and extern “C” in C++

http://www.geeksforgeeks.org/extern-c-in-c/ C++函数重载(function overloading),但是C++编译器是如何区分不同的函数的呢?----是通过在函数名是加些信息来区不同的函数,即所谓的Name Mangling.C++标准并没有对name mangling技术,各个编译器可以添加不同的信息. 考虑下面的函数 int f (void) { return 1; } int f (int) { return 0; } void g (voi