它们之间的连接问题主要是因为c\c++编绎器对函数名译码的方式不能所引起的,考虑下面两个函数
/* c*/
int strlen(char* string)
{ ... }
//c++
int strlen(char* string)
{ ... }
两个函数完全一样。在c在函数是通过函数名来识别的,而在C++中,由于存在函数的重载问题,函数的识别方式通函数名,函数的返回类型,函数参数列表三者组合来完成的。因此上面两个相同的函数,经过C,C++编绎后会产生完全不同的名字。所以,如果把一个用c编绎器编绎的目标代码和一个用C++编绎器编绎的目标代码进行连接,就会出现连接失败的错误。
解决的方法是使用extern C,避免C++编绎器按照C++的方式去编绎C函数 在头文件中定义: extern "C" int strlen(char* string) 或 extern "C" { int strlen(char* string) } 当C编绎器遇到extern "C"的时候就用传统的C函数编译方法对该函数进行编译。由于C编绎器不认识extern "C"这个编绎指令,而程序员又希望C,C++程序能共用这个头文件,因此通常在头文件中使用_cplusplus宏进行区分:
#if define _cplusplus
extern "C"{
#endif
int strlen(char* string)
#ifdefine _cplusplus
}
#endif
#define CALLBACK __stdcall
#define WINAPI __stdcall
那么,除了__stdcall,还有别的调用类型吗?究竟什么是调用类型呢?我的理解是:调用类型就是如何使用函数参数的一种规则。有三种调用类型:__fastcall、__cdecl、__stdcall。
1、__cdecl调用类型:
这是C的调用规则。对于所有非C++成员函数或未标有__stdcall或__fastcall的函数来说,这是默认调用规则。
2、__fastcall调用类型:
从字面意思可知,这是一种快速调用。因为CPU的寄存器会被使用来存放函数参数列表中的头几个参数。而剩下参数将被从右至左地推倒堆栈上。被调用函数将从 寄存器和堆栈获得函数参数。在x86中,ECX和EDX一般被用来存放开始的参数。在.NET中,为了性能上的快速,就是使用ecx和edx来实现 __fastcall的。
3、 __stdcall调用类型:
该调用只是通过堆栈来push和pop参数。push参数时,顺序是从右到左。
现在,你应该明白了吧。最后,我带一句。三种调用类型在VC编译器中对应/Gd、/Gr、/Gz三个编译选项
调用C/C++制做的DLL文件中导出函数的几点说明
用某种语言调用C/C++制做的DLL文件中导出函数时,有几点注意:一、“_stdcall”的作用
在C/C++中函数默认Calling Conventions(调用约定)是:
参数由右向左压入栈,由调用者清空栈。,
在FORTRAN、PASCAL、VisualBASIC等语言中,函数的Calling Conventions是:
参数由右向左压入栈,由被调函数清空栈。
那么在C/C++中使用_stdcall声明导出函数,就可以指定C/C++按照FORTRAN等的调用约定申明该函数,这时FORTRAN等其它语言中再调用这些函数就不会出现报错:run-time '49':Bad
DLL call conventions.
二、加“extern "C"”的作用
extern "C" int _stdcall
Extest();
如上的原型,函数名符号会被VC编译器处理为 _Extest@0
int _stdcall Extest();
如上的原型,函数名符号会被VC编译器处理为 ?Extest@@YGXXZ
C语言的编译链接环境不能处理第二种方式的修饰名,所以如果你的DLL要在C和C++的环境下都适用,那么应该使用第一种命名方式。
例如:在MFC的类中调用自己写的C函数,有时出现错误说无法找到函数的定义,原因是由于C 和C++的编译器对函数的修饰名不同,C++的修饰名中包括了各参数类型,因此通常情况下,C++程序无法找到C库中的函数,需要在声明C函数时加上 extern
"C"的说明:
extern "C" void foo();
C++编译器就会用C的修饰名方式来进行连接调用。同样,当C需要调用C++函数时,该C++函数也必须声明为extern "C"。通常可以在C的头文件里这样定义:
#ifdef __cplusplus extern "C" { #endif
... #ifdef __cplusplus } #endif
就可兼容C和C++程序。
原文链接:http://hi.baidu.com/yebihaigsino/blog/item/8efd3bd8ca21c8ee39012f0f.html