extern "C" 的用意

跨语言编程

zz:http://blog.youkuaiyun.com/wujian53/archive/2006/05/03/706975.aspx

前些天,编程序是用到了很久以前写的C程序,想把里面的函数利用起来,连接发现出现了找不到具体函数的错误:

以下是假设旧的C程序库

C的头文件

/*-----------c.h--------------*/



#ifndef _C_H_
#define _C_H_

extern
 int
 add(


int
 x,


 int
 y);



#endif

C的源文件

/*-----------c.c--------------*/



int
 add(


int
 x,


 int
 y){



	return
 x+

y;
}



C++的调用

/*-----------cpp.cpp--------------*/



#include "c.h"

void
 main
()
{


	add(


1
,


 0
);
}



这样编译会产生错误cpp.obj : error LNK2001: unresolved external symbol "int __cdecl add(int,int)" (?add@@YAHHH@Z ),原因是找不到add的目标模块

这才令我想起C++重载的函数命名方式和C函数的命名方式,让我们回顾一下:C中函数编译后命名会在函数名前加以"_",比如add函数编译成obj文件时的实际命名为_add,而c++命名则不同,为了实现函数重载同样的函数名add因参数的不同会被编译成不同的名字

例如

int add(int , int)==> add@@YAHHH@Z,

float add(float , float )==> add@@YAMMM@Z ,

以上是VC6的命名方式,不同的编译器会不同,总之不同的参数同样的函数名将编译成不同目标名,以便于函数重载是调用具体的函数。

编译cpp.cpp中编译器在cpp文件中发现add( 1 , 0 ); 的调用而函数声明为 extern int add( int x, int y ); 编译器就决定去找 add@@YAHHH@Z ,可惜他找不到,因为C的源文件把extern int add( int x, int y); 编译成_add了;

为了解决这个问题C++采用了extern "C",这就是我们的主题,想要利用以前的C程序库,那么你就要学会它,我们可以看以下标准头文件你会发现,很多头文件都有以下的结构

#ifndef __H
#define __H
#ifdef __cplusplus

extern
 "C"
 {



#endif


extern
 int
 f1(


int
,


 int
);



extern
 int
 f2(


int
,


 int
);



extern
 int
 f3(


int
,


 int
);




	
#ifdef __cplusplus

}



#endif

#endif /*__H*/

如果我们仿制该头文件可以得到

#ifndef _C_H_
#define _C_H_
#ifdef __cplusplus

extern
 "C"
 {



#endif


extern
 int
 add(


int
,


 int
);




#ifdef __cplusplus

}



#endif

#endif /* _C_H_ */ 

这样编译

/*-----------c.c--------------*/
int
add ( int x , int y ){
return
x + y ;
}

这时源文件为*.c, __cplusplus没有被定义,extern "C" {} 这时没有生效对于C他看到只是extern int add( int , int );
add函数编译成_add(int, int);

而编译c++源文件

/*-----------cpp.cpp--------------*/
#include "c.h"
void main ()
{

add ( 1 , 0 );
}

这时源文件为*.cpp, __cplusplus被定义,对于C++他看到的是extern "C" { extern int add ( int , int ); } 编译器就会知道 add( 1 , 0 );调用的C风格的函数,就会知道去c.obj中找_add(int, int)而不是 add@@YAHHH@Z

这也就为什么DLL中常看见extern "C" {}, windows是采用C语言编制他首先要考虑到C可以正确调用这些DLL,而用户可能会使用C++而extern "C" {}就会发生作用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值