关于链接指示符的问题

extern “XX”可以告诉编译器,该函数是用其它语言来编写的,但强制这些函数采用XX语言的方式进行编译。
举个例子说吧!
C接口的方法:
C中调用C++函数:
生成一个工程叫demo,加入一个demo.c 内容如下:
int add(int a,int b );//有无都可
int main()
{
int i=add(3,2);
printf("i=%d",i);
return 0;
}
再加入一个add.cpp,(注意扩展名,强制控制台生成两种文件类型)内容如下:
int add(int a,int b)
{
return a+b;
}

如果这样编译的话,会产生下面的错误:Linking...
demo.obj : error LNK2001: unresolved external symbol _add
Debug/demo.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe

根据提示说是没有找到-add,可是我明明定义了!.
为了搞清这个这个问题,就要搞清楚到底C的函数和CPP的函数在编译之后,会变成什么样子!
C++支持重载,C中不支持,而C++怎么区分这些重载函数呢,究竟调用那个函数呢?C++能通过不同的参数区分具有相同名称的、不同实现的函数。C++函数被编译以后,函数会附带一些参数信息!
我们以实事说话:
在add.cpp中再加入一个同名函数实现重载

float add(float fa,float fb)
{ return fa+fb;
}

int add(int a,int b)
{ return a+b;
}

单独编译此文件没有问题!

输出一个map文件,找到add函数:

Address Publics by Value Rva+Base Lib:Object
0001:00000030 _main 00401030 f demo.obj
0001:00000080 ?add@@YAMMM@Z 00401080 f add.OBJ
0001:000000b0 ?add@@YAHHH@Z 004010b0 f add.OBJ

明白了吧!
精华都在这里了!

提示说找不到_add,原来是在C语言被编译过程中,自动加上了下画线了!
看看main就知道了!

而在C++中,函数被扩展了,?add@@YAMMM@Z,前面两个@相当于左括号,后面一个相当于右括号,中间的就是用来表示参数的了!简单吧!

两个重载函数使用了不同的参数,一个是整数,一个是浮点数。在执行连接的过程中,c++链接器会到对应的OBJ文件中查找函数。在本例中,如果某函数的名称为"add@@YAMMM@Z 00401080",那么则可以找到函数定义。在C++编译中,会把参数的类型,名字和函数的名字组合成为一个新的函数,这样就和程序定义的函数名这相一致!

现在在看看错误提示,我们的输出文件中也找不到这个_add,所以程序不可能连接上。知道原因就解决吧!
最直接的方法就是修改C++文件的编译结果,让它产生一个对应C的函数名字,也就是按C的方法来生成对应的函数。

在C++的头文件中加入:
extern "C" int add(int a,int b);
extern “C” 语句的作用就是把C++函数按C约定编译!
运行,OK!

Address Publics by Value Rva+Base Lib:Object
0001:00000030 _main 00401030 f demo.obj
0001:00000080 ?add@@YAMMM@Z 00401080 f add.obj
0001:000000b0 _add 004010b0 f add.obj

变了吧!

那么C++中调用C呢!
由于两者之间的关系,C++中可以说是直接调用就可以了!不过这是有条件的!
把demo.c改成:

int substract(int a,int b)
{
return a-b;
}

void hello()

{ printf("hello");
}

add.cpp改为:
void hello();
int substract(int a,int b);

int main()
{
hello();
int c=substract(4,1);
printf("c=%d",c);
return 0;
}

编译运行,出现了上次一样的错误:
加上
extern "C"

{ void hello();
int substract(int a,int b);
}

就OK了!

这是两者的map 比较:
0001:00000030 _substract 00401030 f demo.obj
0001:00000060 _hello 00401060 f demo.obj
0001:00000030 _substract 00401030 f demo.obj
0001:00000060 _hello 00401060 f demo.obj

发现是一样的!

问题在于你在add.cpp前面加入了:
void hello();
int substract(int a,int b);

这样就把两个函数编译成了C++方式,去找它的实现代码的时候,肯定出错了!

而在C调用C++的时候, int add(int a,int b );加与不加,系统只是会给出一个提示,这或许就是C++强的地方吧!
把错误消灭在初期!
Extern “C”是唯一被保证由所有的C++实现都支持的。
以上代码在VC6。0+WINXP(盗版)下调试通过

一句话:无论是C调用C++函数,还是C++调用C函数,只需要在C++文件中加入extern "C"语句即可。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值