没有找到合适的产品?
联系客服协助选型:023-68661681
提供3000多款全球软件/控件产品
针对软件研发的各个阶段提供专业培训与技术咨询
根据客户需求提供定制化的软件开发服务
全球知名设计软件,显著提升设计质量
打造以经营为中心,实现生产过程透明化管理
帮助企业合理产能分配,提高资源利用率
快速打造数字化生产线,实现全流程追溯
生产过程精准追溯,满足企业合规要求
以六西格玛为理论基础,实现产品质量全数字化管理
通过大屏电子看板,实现车间透明化管理
对设备进行全生命周期管理,提高设备综合利用率
实现设备数据的实时采集与监控
利用数字化技术提升油气勘探的效率和成功率
钻井计划优化、实时监控和风险评估
提供业务洞察与决策支持实现数据驱动决策
转帖|其它|编辑:郝浩|2009-02-20 11:05:10.000|阅读 729 次
概述:本文是一篇关于调用约定的小教程,旨在解释调用约定如何运作,并且与C和C + +中书写动态链接库以及在C#利用他们相关联。这可能对理解骨架代码有用。
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
当您开始使用动态链接库,编写涉及其他语言中的函数代码时,你会遇到诸如stdcall,safecall,cdecl和winapi之类的词。这些调用约定定义了如何在运行时调用外部函数,即使是单独编译,甚至可能是和不同的编译器和连接器。
本文是一篇关于调用约定的小教程,旨在解释调用约定如何运作,并且与C和C + +中书写动态链接库以及在C#利用他们相关联。这可能对理解骨架代码有用。
备注:这无关链接,而是使用动态数据库并在运行时间调用它们。
一个调用约定定义了参数如何被传到堆栈,调用者或函数是否需要在结束调用后清理堆栈。
关于堆栈
堆栈追踪函数的调用来源。而这通常是硬件通过使用注册簿来完成的,注册簿是对记忆的指向标。按照惯例,一个堆栈开始是指向内存。随着每个项目都堆到堆栈上,堆栈指针就会减少。当你从堆栈上删除数据时。
一般来说,编译器具备一些设置可以指定堆栈可得的内存数量。堆栈可以保存以下三种类型的数据:
CPU会有一些针对堆栈记忆分配的特殊指令。编译器会计算出所有本地变量和参数所需要的内存量,并且相应地对其进行内存分配。在调用快结束时,准确的反面指令被调用来减少同样的量。基本上,这些指令通过登记的数额减少了堆栈指针,并且在最后又相应地增加了空间。
返回地址
当一个函数被调用的时候,CPU要做的第一件事是在调用的函数生成时,计算出下一个指令是什么。下表就是对该过程进行的一个小小的演示:
Address 101
Address 102 Call Function 201
Address 103...
...
Address 151 Call Function 201
Address 152...
Address 201.. First instruction of function
Address 202.. Allocate memory for local variables
...
Address 206.. Release the allocated memory
Address 207.. return from function
在上面的例子中,如果CPU刚刚在101处理完指令,那么其下一步操作就是处理102的指令并且调用201的函数。那之后的指令就是103。它会一直持续到151直到再次调用201的函数。这次,当它返回时,它会一直与152的指令持续。地址103和152是保存在堆栈的返回地址。
堆栈状态
如果堆栈以5000的指标开始,它就会像这样:
Stack Pointer= 5000
Address 5000
当函数201在202指令运行完后被调用,堆栈就会有数据。让我们想象一下这个函数没有参数但是有一个拥有本地变量总数,该总数是由10个整数组成的数组。
int totals[10]
如果每个地址保存一个整数,那么这个数组就有十个地点。在201,堆栈指数会减少10。
Stack Pointer= 4989
Address 5000 .. 103
Address 4999 .. total[9]
Address 4998 .. total[8]
...
Address 4990 .. total[0]
Address 4989 <- Current top of stack.
执行206时,堆栈指针将增加10个。207的指令会弹到堆栈的极限。这一情况正是一种警告。与推送一起,某个值也被存储在当前地址中,该地址由堆栈指针持有,然后堆栈指针递减。膨胀使堆栈指针增加了1,然后从堆栈指针所持有的地址处得到值。因此,从5000(地址)得到值,即103 ,而这就是下一个要执行的指令。
由数值审核还是由参考审核?
前者把整个的变量复制到堆栈上,这不但很慢而且如果变量很大,可能使堆栈无法承担。例如,10,000个数组会减少10,000个堆栈指数并且把这10,000个整数的值到复制到堆栈上。相比之下,使用参考审核则要快得多,因为它只会把变量的地址送到堆栈上。所以在C语言中是用指数(*),在c++中使用参考(&)来保持其简便。[SPAN]
调用约定
了解参数是很重要的,比方,a,b,c,它们是按照这个顺序送到堆栈的吗?还是按照c,b,a的顺序?返回地址会去到哪里呢?同样,被调用的函数从堆栈删除参数还是从主程序?为什么不从登记簿通过数值来加速呢?指定发生的事情就是调用约定所做的事。
约定列表
主要的约定如下所示。
function f(A, B, C)
除非你的dlls只被C或C++使用,否则的话,你就相信winapi。则会使默认情况,所以不需要指定。
C++中的名字改编
因为C + +语言是一种安全且相当严谨的语言类型,它提出了名字改编。这意味着,输出的函数,包括来自类型的参数类型的额外函数。这有助于防止函数被调用时出现参数错误,而这种错误可能会导致莫名的死机。然而,当非C + +代码调用C + +的函数时也可能会出现问题。例如,你有一个C #应用程序调用dll的C + =代码。由于dll中的函数名称毁坏,函数就无法被找到。操作系统可能会期望一个叫做GetValue(int a, float b)的函数,但在该dll中,名称错位后看起来就像GetValueif。
有一种简单的修复方法。任何C++ dll必须把代码在任何输出函数之前和之后的说明中。就像这样:
#define MYEXPORT __declspec(dllexport)
#ifdef __cplusplus
extern "C" {
#endif
MYEXPORT char * WINAPI GetBotName(void) ; // returns name of your Bot
...
#ifdef __cplusplus
}
#endif
这一行:#define MYEXPORT __declspec(dllexport),就告诉了编译器在任何由MYEXPORT定于的函数上添加_declspec。这使得该函数可见与使用dll的任何应用程序。
macro_cplusplus只定义在兼容C++编译器的Ansi 98中。所以macro会被所有包含在C文件夹的页眉文件忽视。
在你拥有C代码的反例中,你希望与C++链接,那样你就把说明用这个语句包装起来:
extern “C++” {
这一操作可迫使编译器粉碎函数名称。
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com
文章转载自:IT专家网面对“数字中国”建设和中国制造2025战略实施的机遇期,中车信息公司紧跟时代的步伐,以“集约化、专业化、标准化、精益化、一体化、平台化”为工作目标,大力推进信息服务、工业软件等核心产品及业务的发展。在慧都3D解决方案的实施下,清软英泰建成了多模型来源的综合轻量化显示平台、实现文件不失真的百倍压缩比、针对模型中的大模型文件,在展示平台上进行流畅展示,提升工作效率,优化了使用体验。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
服务电话
重庆/ 023-68661681
华东/ 13452821722
华南/ 18100878085
华北/ 17347785263
客户支持
技术支持咨询服务
服务热线:400-700-1020
邮箱:sales@evget.com
关注我们
地址 : 重庆市九龙坡区火炬大道69号6幢
慧都科技 版权所有 Copyright 2003-
2025 渝ICP备12000582号-13 渝公网安备
50010702500608号