今天偶然注意了一下C++中malloc的源代码定义,发现有一点疑问,_cdecl 是什么,似曾相识啊,哦,知道了,这和C# 中P/Invoke 有一些关系
C#调用WINAPI时:[System.Runtime.InteropServices.DllImport("user32.dll")] 其中一个参数涉及到调用约定,即CallingConvention。
/*调用约定有以下三种: *_stdcall调用:_stdcall是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,被调函数自身在返回前清空堆栈。WIN32 Api都采用_stdcall调用方式,这样的宏定义说明了问题:#define WINAPI _stdcall ;按C编译方式,_stdcall调用约定在输出函数名前面加下划线,后面加“@”符号和参数的字节数,形如。 * _cdecl调用:_cdecl是C/C++的缺省调用方式,参数采用从右到左的压栈方式,传送参数的内存栈由调用者维护。_cedcl约定的函数只能被C/C++调用,每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。由于_cdecl调用方式的参数内存栈由调用者维护,所以变长参数的函数能(也只能)使用这种调用约定。关于C/C++中变长参数(…)的问题,笔者将另文详述。由于Visual C++默认采用_cdecl 调用方式,所以VC中中调用DLL时,用户应使用_stdcall调用约定。按C编译方式,_cdecl 条用约定仅在输出函数名前面加上下划线,形如_functionname。 *_fastcall调用:_fastcall调用较快,它通过CPU内部寄存器传递参数。按C编译方式,_fastcall调用约定在输出函数名前面加“@”符号,后面加“@”符号和参数的字节数,形如@functionname@number。 */
/*DllImport具有五个命名参数: *CharSet 参数指示用在入口点中的字符集。如果未指定 CharSet,则使用默认值 CharSet.Auto。 *CallingConvention 参数指示入口点的调用约定。如果未指定 CallingConvention,则使用默认值 CallingConvention.Winapi。 *EntryPoint 参数给出 dll 中入口点的名称。如果未指定 EntryPoint,则使用方法本身的名称。 *ExactSpelling 参数指示 EntryPoint 是否必须与指示的入口点的拼写完全匹配。如果未指定 ExactSpelling,则使用默认值 false。 *PreserveSig 参数指示方法的签名应当被保留还是被转换。当签名被转换时,它被转换为一个具有 HRESULT 返回值和该返回值的一个名为 retval 的附加输出参数的签名。如果未指定 PreserveSig,则使用默认值 true。 */
由此可以知道malloc是C++中标准库函数,如果调用某个函数显示是_stdcall function() 则说明调用的是winAPI。