C++语言在编译的时候为了解决函数的多态问题,建立了与C语言编译器不同的函数名修饰规则,C++语言在编译的时候会将函数名和参数联合起来生成一个中间的函数名称,而C语言则不会,因此会造成链接阶段无法找到对应函数的情况。因此,C函数就需要用extern “C”进行链接指定,通知编译器以下函数或文件中函数是C语言函数,编译时按照C语言编译器的函数名修饰规则,保持函数的名称,不回生成用于链接的中间函数名。
C语言编译器的函数名修饰规则
对于__stdcall调用约定,编译器和链接器会在输出函数名前加上一个下划线前缀,函数名后面加上一个“@”符号和其參数的字节数。比如 :_functionname@number。
int add(char a,char b);
C语言编译器修饰后的名称为
_add@2
C++语言编译器的函数名修饰规则
C语言编译器的函数名修饰规则仅仅使用函数名对不同函数进行区分,不同重载函数会出现修饰输出名称一致的情况,为了解决函数的多态问题,C++语言编译器建立了一套更加复杂的函数名修饰规则,但信息更充分,通过分析修饰名不仅可以知道函数的调用方式。返回值类型,參数个数甚至參数类型。
对于__stdcall方式,参数表的开始标识是“@@YG”,参数表的拼写代号如下表所示:
X--void | D--char |
E--unsigned char | F--short |
H--int | I--unsigned int |
J--long | K--unsigned long |
M--float | N--double |
_N--bool | U--struct |
PA--指针 | PB--const 指针... |
int show(char *var1,unsigned long);
C++语言编译器修饰后的名称为
?show@@YGHPADK@Z
此外,extern"C"是C++的语法,通常我们写一个头文件时,并不确定是在C或C++编译器环境下使用,如果在C语言编译器下使用extern"C"时,编译器会报错。因此,使用extern"C"需要进行编译器进行检查:
#ifdef __cpluscplus
extern "C" {
#endif
//some code
#ifdef __cplusplus
}
#endif