__stdcall in c++ builder

简介: VC默认为__stdcall, BCB默认为__cdecl, Delphi默认为__fastcall。 由于BCB使用Delphi的VCL库, 所以也必须使用__fastcall。   关键字 调用规则 参数传递方向 返回 参数寄存器 堆栈的清除__cdecl C调用规则 从右向左 E...

VC默认为__stdcall,
BCB默认为__cdecl,
Delphi默认为__fastcall。
由于BCB使用Delphi的VCL库,
所以也必须使用__fastcall。

 

关键字 调用规则 参数传递方向 返回 参数寄存器 堆栈的清除
__cdecl C调用规则 从右向左 EAX 调用者
__fastcall 寄存器 从左向右 EAX EAX、EBX、ECX 被调用者
__stdcall Win32标准 从右向左 EAX 被调用者
__pascal Pascal 从左向右 EAX 被调用者
__msfastcall Ms寄存器 从右向左 EAX/EDX ECX、EDX 被调用者

 

 

摘自《面向状态的程序设计与C++   Builder》第四章第一节       Lewolf著
1.4.1 __cdecl、_cdecl、cdecl关键字
这是在C++   Builder中特有的关键字,__cdecl、_cdecl、cdecl可以用来修饰变量或者函数,其含义是指定的变量或者函数使用C语言的调用规则和命名规则。在C++   Builder中C调用规则是缺省的设置,可以通过Project的Option菜单在Advanced   Compiler标签中来改变缺省设置。
对于C命名规则的变量或函数,具有大小些敏感、编译后变量名称前下划线前导符,这与Pascal语言是不一样的。对于函数,C调用规则要求使用堆栈传递参数,参数传递的顺序为自右向左依次压入堆栈,由调用者自行清除堆栈,C调用规则允许向函数传递不定参数,但这种调用方式系统需要更多的开销来完成参数的匹配,除非特殊用途一般尽量不要使用,这种调用方式最典型的例子是控制台程序中的main函数,程序运行时可以不带参数,也可以带多个参数。
在一个独立的程序中,采用那种调用规则或者命名规则影响并不十分大,但是在多种语言混合编程,或者编写带有数据输出或函数输出的可执行模块(可执行文件和动态链接库)时,命名规则和调用规则显得尤为重要,使用不当则可能导致程序无法正常运行,甚至使系统崩溃。
__cdecl、_cdecl、cdecl的使用语法如下:
cdecl   <data/function   definition> ;
_cdecl   <data/function   definition> ;
__cdecl   <data/function   definition> ;
例如:
int   cdecl   I;                     //编译后标识符为“_I”
void   __cdecl   Fun();   //编译后函数名为“_Fun”
1.4.2 __fastcall、_fastcall关键字
__fastcall和_fastcall也是C++   Builder中特有的关键字,只能用于修饰函数,其作用是指定函数使用“寄存器”调用规则,使用语法如下:
return-type   _fastcall   function-name(parm-list)
return-type   __fastcall   function-name(parm-list)
例如:
void   __fastcall   GetName(int   Index);
使用“寄存器”调用规则的函数,其参数传递顺序为自左向右依次传递,并且将前三个参数尽可能的使用EAX、EBX、ECX这三个寄存器传递,对于前三个参数中浮点类型、结构类型等超过四个字节的变量,和第四个及以后的参数则采用堆栈来传递,因此采用“寄存器”调用规则的函数只能传递固定数量的参数。
在C++   Builder中,所有属于VCL的成员函数,必须是__fastcall类型,编译器将“寄存器”调用规则和C调用规则、Pascal调用规则以及Win32的标准等其它调用规则是同等对待的,因此__fastcall关键字不能和__cdecl、__pascal、__stdcall等关键字联合使用,也不能和__export关键字同时使用(实际上使用__fastcall规则的函数是允许输出的,只是这种调用规则编写的dll或可执行模块只能被C++   Builder或者Delphi开发的程序载入并调用输出的函数)。
被指定为“寄存器”调用的函数会在编译时被冠以前导符@,这将使得C及C++的函数命名过于混乱,但是这种调用规则有很高的执行效率,因此在C++   Builder中几乎所有VCL的成员函数都使用这种调用规则。
但是__fastcall和_fastcall是C++   Builder之前的C++编译器所没有的调用规则,为了保证兼容性,可以使程序连接以前版本的编译器生成的库文件,C++   Builder提供了-VC命令行选项,缺省状态下,该选项是关闭的,当需要时,可以通过命令行编译并选择-VC选项。
1.4.3 __msfastcall、__msreturn关键字
__msfastcall和__msreturn也是C++   Builder中特有的关键字,使用这两个关键字可以为程序提供和Microsoft兼容的“寄存器调用”规则以及和Microsoft兼容的函数返回的规则。
被__msfastcall修饰的函数,其参数传递顺序为前两个参数如果长度小于4字节,则分别使用ECX和EDX寄存器传递,其余的参数和前两个不能使用寄存器传递的参数则按照从右向左的顺序通过堆栈来传递,堆栈由被调用函数负责清除。
__msreturn是使用Microsoft兼容的“寄存器调用”返回规则,在这种返回规则中,返回值的长度在4~8个字节时,将采用EAX/EDX寄存器返回函数值。
1.4.4 __pascal、_pascal、pascal关键字
__pascal、_pascal、pascal关键字表示一个变量或者函数遵循Pascal的调用和命名规则。
在Pascal的命名规则中,对大小写并不敏感,而且不象C调用规则,会在变量和函数明成前面加前导符。Pascal调用规则中,参数的传递是按照从左到右的顺序依次压入堆栈,并且由被调用函数自行清除堆栈。
Pascal调用规则破坏了C语言的本身的调用体系,同时也带来了更多的灵活性,被表示为__pascal调用规则的函数,编译后的目标文件中,名称会被全部转换为大写字母,在Pascal语言中,过程和函数的书写是对大小些不敏感的,但是在C++   Builder中采用Pascal调用规则的函数,在C++源文件中仍然需要遵循C语言中对大小些必须严格一致的要求,Pascal调用规则的大小写不敏感性只能体现在动态链接库、或者输出、输入函数以及数据的时侯。也正是这样的原因,对一些采用Object   Pascal编写的第三方控件或者书写不是很规范的Pascal程序代码,使用C++   Builder编译的时候,会出现找不到函数原型的错误,实际上可能只是程序中函数名称的大小些不一致造成的。
1.4.5 __stdcall、_stdcall关键字
在Windows程序设计中,有一种Win32的标准调用规则,基本上所有的Windows   API函数都采用了这种Win32的标准调用规则,在讲__declspec(nothrow)关键字时的例子,其中宏定义就是C++   Builder中winuser.h宏定义。Win32标准调用在C++   Builder中以__stdcall、_stdcall关键字来标识。
在__stdcall、_stdcall调用规则中,函数的参数是按照从右向左的顺序依次压入堆栈,所有的参数均采用堆栈传递,而且是被调用函数负责清除堆栈。在参数的传递顺序上,Win32标准调用规则和C调用规则一样,从右向左,但和C调用规则不同的是,Win32的标准调用要求调用者必须严格按照被调用函数的参数数量及类型进行参数传递。
关于C++   Builder中函数调用规则以及命名规则的详细内容,读者参考相关书籍,这里不做过多讲解,下表给出了C++   Builder中几种调用规则的一个简单比较,具有汇编语言基础的读者可以参考本书光盘中相关代码自行分析区别。
关键字   调用规则 参数传递方向 返回 参数寄存器 堆栈的清除
__cdecl   C调用规则 从右向左 EAX 无 调用者
__fastcall 寄存器 从左向右 EAX EAX、EBX、ECX 被调用者
__stdcall Win32标准 从右向左 EAX 无 被调用者
__pascal Pascal 从左向右 EAX 无 被调用者
__msfastcall Ms寄存器 从右向左 EAX/EDX ECX、EDX 被调用者

相关文章
|
3天前
|
搜索推荐 编译器 Linux
一个可用于企业开发及通用跨平台的Makefile文件
一款适用于企业级开发的通用跨平台Makefile,支持C/C++混合编译、多目标输出(可执行文件、静态/动态库)、Release/Debug版本管理。配置简洁,仅需修改带`MF_CONFIGURE_`前缀的变量,支持脚本化配置与子Makefile管理,具备完善日志、错误提示和跨平台兼容性,附详细文档与示例,便于学习与集成。
278 116
|
18天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
6天前
|
数据采集 人工智能 自然语言处理
Meta SAM3开源:让图像分割,听懂你的话
Meta发布并开源SAM 3,首个支持文本或视觉提示的统一图像视频分割模型,可精准分割“红色条纹伞”等开放词汇概念,覆盖400万独特概念,性能达人类水平75%–80%,推动视觉分割新突破。
391 38
Meta SAM3开源:让图像分割,听懂你的话
|
13天前
|
安全 Java Android开发
深度解析 Android 崩溃捕获原理及从崩溃到归因的闭环实践
崩溃堆栈全是 a.b.c?Native 错误查不到行号?本文详解 Android 崩溃采集全链路原理,教你如何把“天书”变“说明书”。RUM SDK 已支持一键接入。
669 220
|
1天前
|
Windows
dll错误修复 ,可指定下载dll,regsvr32等
dll错误修复 ,可指定下载dll,regsvr32等
129 95
|
11天前
|
人工智能 移动开发 自然语言处理
2025最新HTML静态网页制作工具推荐:10款免费在线生成器小白也能5分钟上手
晓猛团队精选2025年10款真正免费、无需编程的在线HTML建站工具,涵盖AI生成、拖拽编辑、设计稿转代码等多种类型,均支持浏览器直接使用、快速出图与文件导出,特别适合零基础用户快速搭建个人网站、落地页或企业官网。
1633 157
|
存储 人工智能 监控
从代码生成到自主决策:打造一个Coding驱动的“自我编程”Agent
本文介绍了一种基于LLM的“自我编程”Agent系统,通过代码驱动实现复杂逻辑。该Agent以Python为执行引擎,结合Py4j实现Java与Python交互,支持多工具调用、记忆分层与上下文工程,具备感知、认知、表达、自我评估等能力模块,目标是打造可进化的“1.5线”智能助手。
906 61