C++技术之一:C++类 _stdcall
一切从一个C++ 类库头文件开始,现在在做一个C++的项目,期间用到一个开源的界面库DUILib(类似MFC),这个东西还不错能很容易的写出漂亮的界面,比如QQ的界面,可以去下载下来研究研究,地址:http://code.google.com/p/duilib/
废话不多说,我比较困扰的是UIWebBrowser.h这个头文件,虽然是C++写的,但里面包含太多大学C++课本以外的东西,第一遍看下来跟看天书一样,里面有很多的不惑,接下来我们一个一个解开。
首先看一下这个函数定义:
virtual HERSULT STDMETHODCALLTYPE GetTypeInfoCount( __RPC__out UINT *pctinfo);
这一篇详细介绍 __stdcall
上篇文章我们知道#define STDMETHODCALLTYPE __stdcall ,那__stdcall又是个什么东东呢,有什么作用呢?下面来完全的了解一下.
1. _cdecl
(1). 是C Declaration的缩写,表示C语言默认的函数调用方法,实际上也是C++的默认的函
数调用方法。
(2). 所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。具体所示:调用
方的函数调用->被调用函数的执行->被调用函数的结果返回->调用方清除调整堆栈。 (3). 被调用函数无需要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全
不同的参数都不会产生编译阶段的错误。总的来说函数的参数个数可变的(就像printf函数一样),因为只有调用者才知道它传给被调用函数几个参数,才能在调用结束时适当地调整堆栈。
(4). 因为每个调用的地方都需要生成一段调整堆栈的代码,所以最后生成的文件较大。
2. _stdcall(CALLBACK/WINAPI)
(1). 是Standard Call的缩写,要想函数按照此调用方式必须在函数名加入_stdcall,通常_
win32 api 应该是_stdcall调用规则。通过VC++编写的DLL欲被其他语言编写的程序调用,应将函数的调用方式声明为_stdcall 方式,WINAPI都采用这种方式。
(2). 所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。具体所示:调用方的函数调用->被调用函数的执行-> 被调用方清除调整堆栈->被调用函数的结果返回。
(3). 这些堆栈中的参数由被调用的函数在返回后清除,使用的指令是 retn X,X表示参数占用的字节数,CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。 (4). 函数在编译的时候就必须确定参数个数,并且调用者必须严格的控制参数的生成,不能
多,不能少,否则返回后会出错。总的来说,就是函数的参数个数不能是可变的。是从 _cdecl 修改而来, _stdcall 不支持可变参数,并且清栈由被调用者负责,其他的都一样 (5). 因为只需在被调用函数的地方生成一段调整堆栈的代码,所以最后生成的文件较小。
3. PASCAL 是Pascal语言的函数调用方式,也可以在C/C++中使用,参数压栈顺序与前两者相反。返回时的清栈方式忘记了。。。
4. _fastcall 是编译器指定的快速调用方式。由于大多数的函数参数个数很少,使用堆栈传
递比较费时。因此_fastcall通常规定将前两个(或若干个)参数由寄存器传递,其余参数还是通过堆栈传递。不同编译器编译的程序规定的寄存器不同。返回方式和_stdcall相当。
5. _thiscall 是为了解决类成员调用中this指针传递而规定的。_thiscall要求把this指针放
在特定寄存器中,该寄存器由编译器决定。VC使用ecx,Borland的C++编译器使用eax。返回方式和_stdcall相当。
6. _fastcall 和 _thiscall涉及的寄存器由编译器决定,因此不能用作跨编译器的接口。所以
Windows上的COM对象接口都定义为_stdcall调用方式。
7. C中不加说明默认函数为_cdecl方式(C中也只能用这种方式),C++也一样,但是默认
的调用方式可以在IDE环境中设置。
8. 带有可变参数的函数必须且只能使用_cdecl方式,例如下面的函数:
int printf(char * fmtStr, ...);
int scanf(char * fmtStr, ...); 9. 函数名修饰
(1). _cdecl :对于_cdecl而言,如果对于定义在C程序文件(编译器会通过后缀名为.C判断)
的输出函数,函数名会保持原样;对于定义在C++程序文件中的输出函数,函数名会被修饰(见10)。为使函数名不被修饰,有两种方法:A.可通过在前面加上extern “c”以去除函数名修饰;B. 可通过.def文件去除函数名修饰。 (2). _stdcall:无论是C程序文件中的输出函数还是C++程序文件中的输出函数,函数名都会
被修饰。对于定义在C++程序文件中的输出函数,好像更复杂,和_cdecl的情况类似。去除函数名修饰方法:只能通过.def文件去除函数名修饰。 10. 函数名修饰规则: (1). 为什么要函数名修饰:
函数名修饰就是编译器在编译期间创建的一个字符串,用来指明函数的定义和原型。
LINK程序或其他工具有时需要指定函数的名字修饰来定位函数的正确位置。多少情况下程序员并不需要知道函数的名字修饰,LINK程序或其他工具会自动区分他们。当然,在某些情况下需要指定函数名修饰,例如在c++程序中,为了让LINK程序或其他工具能够匹配到正确的函数名字,就必须为重载函数后一些特殊函数(如构造函数和析构函数)指定名字修饰。另一种需要指定函数名修饰的情况是在汇编程序中调用C或C++函数。 (2). C语言:
对于_stdcall调用约定,编译器和链接器会在输出函数名前加上一个下划线前缀,函数
名后面加上一个“@”符号和其参数的字节数,例如_functionname@number。_cdecl调用约定仅在输出函数名前加上一个下划线前缀,例如_functionname。_fastcall调用约定在输出函数名前加上一个 “@“符号,后面也是一个”@“符号和其参数的字节数,例如@functionname@number。 (3). C++语言:
C++的函数名修饰规则有些复杂,但是信息更充分,通过分析修饰名不仅能够知道函数的调用方式,返回值类型,参数个数甚至参数类型。不管__cdecl,__fastcall还是__stdcall调用方式,函数修饰都是以一个“?”开始,后面紧跟函数的名字,再后面是参数表的开始标识和按照参数类型代号拼出的参数表。对于__stdcall方式,参数表的开始标识是“@@YG”,对于__cdecl方式则是“@@YA”,对于__fastcall方式则是“@@YI”。参数表的拼写代号如下所示: X--void D--char
E--unsigned char F--short H--int
I--unsigned int J--long
K--unsigned long(DWORD) M--float N--double _N—bool U—struct ....
指针的方式有些特别,用PA表示指针,用PB表示const类型的指针。后面的代号表明指针类型,如果相同类型的指针连续出现,以“0”代替,一个“0”代表一次重复。U表示结构类型,通常后跟结构体的类型名,用“@@”表示结构类型名的结束。函数的返回值不作特殊处理,它的描述方式和函数参数一样,紧跟着参数表的开始标志,也就是说,函数参数表的第一项实际上是表示函数的返回值类型。参数表后以“@Z”标识整个名字的结束,如果该函数无参数,则以“Z”标识结束。下面举两个例子,假如有以下函数声明:
int Function1(char *var1,unsigned long);
其函数修饰名为“?Function1@@YGHPADK@Z”,而对于函数声明: oid Function2();
其函数修饰名则为“?Function2@@YGXXZ” 。
对于C++的类成员函数(其调用方式是thiscall),函数的名字修饰与非成员的C++函数稍有不同,首先就是在函数名字和参数表之间插入以“@”字符引导的类名;其次是参数表的开始标识不同,公有(public)成员函数的标识是“@@QAE”,保护(protected)成员函数的标识是“@@IAE”,私有(private)成员函数的标识是“@@AAE”,如果函数声明使用了const关键字,则相应的标识应分别为“@@QBE”,“@@IBE”和“@@ABE”。如果参数类型是类实例的引用,则使用“AAV1”,对于const类型的引用,则使用“ABV1”。 11. 查看函数的名字修饰
有两种方式可以检查你的程序中的函数的名字修饰:使用编译输出列表或使用Dumpbin工具。使用/FAc,/FAs或/FAcs命令行参数可以让编译器输出函数或变量名字列表。使用dumpbin.exe /SYMBOLS命令也可以获得obj文件或lib文件中的函数或变量名字列表。此外,还可以使用 undname.exe 将修饰名转换为未修饰形式。
12. _beginthread需要_cdecl的线程函数地址,_beginthreadex和_CreateThread需要_stdcall
的线程函数地址。
13. #define CALLBACK __stdcall //这就是传说中的回调函数
#define WINAPI __stdcall //这就是传说中的WINAPI #define WINAPIV __cdecl
#define APIENTRY WINAPI //DllMain的入口就在这里 #define APIPRIVATE __stdcall #define PASCAL __stdcall
C++技术之一:C++类 _stdcall相关推荐
- 一起谈.NET技术,C#类类型
类类型是由字段数据(成员变量)和操作字段数据的成员(属性.方法.构造函数.事件等)所构成的自定义类型.其中字段数据表示类实例(对象)的状态. 在C#中,类使用class关键字定义,例如: public ...
- 在电视中使用计算机动画最多的是,计算机动画技术在科教类电视节目中的应用探究...
[摘要]目前,计算机动画技术给科教类电视节目增添了新的表现力.在计算机动画创作过程中构思与创意是关键,技术是保障,要有正确的动画创作理念,才能发挥计算机动画在科教节目中的巨大潜能. [关键词]计算机动 ...
- 在电视中使用计算机动画最多的是,计算机动画技术在科教类电视节目中的应用探究.doc...
计算机动画技术在科教类电视节目中的应用探究 [摘要]目前,计算机动画技术给科教类电视节目增添了新的表现力.在计算机动画创作过程中构思与创意是关键,技术是保障,要有正确的动画创作理念,才能发挥计算机动画 ...
- 智能科学与技术是不是属于计算机专业,智能科学与技术属于什么类专业
智能科学与技术属于工科类专业.智能科学与技术专业的培养目标是培养具备基于智能系统方法.自动控制技术.计算机技术.以及传感信息处理技术,能够进行信息获取.传输.处理.优化.控制.组织等并完成系统集成的的 ...
- AI技术在音乐类产品中的应用场景!
自动标注.平滑过渡.音乐鉴权.AI创作,当AI技术应用于音乐行业为人类的精神文化与娱乐生活带来便利和更多选择时,也是一件让人激动不已的事情. 随着深度学习算法的出现.大数据和5G技术的成熟,AI人工智 ...
- 非师范类计算机科学与技术可以做老师吗,计算机科学与技术(师范类)出来能不能做数学老师 数学与数学应用(师范类)出来除了做老师还可以做什么?...
计算机科学与技术(师范类)出来能不能做数学老师 数学与数学应用(师范类)出来除了做老师还可以做什么?以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容, ...
- IO流技术【Properties类介绍、文件切割与合并】
IO流技术[Properties类介绍.文件切割与合并] 1.Properties类介绍 1.1.Properties的基本功能 Properties特点: 1.Hashtable的子类,map集合中 ...
- 做销售与做技术的哪类人更适合创业?肯定是做技术的,你觉得呢?
做销售与做技术的,接触的环境不一样. 一般来说,做销售的,如果想创业,那么在创业之前就会有意识地积累人脉.积累客户,寻找合适的产品方向或项目方向.做技术的,往往只注重自身技术,在客户方面是弱项. 身边 ...
- 成都理工大学工程技术学院计算机专业收分线,2019年成都理工大学工程技术学院美术类专业录取分数线...
四川:艺术本科省控线文化分370专业分200(单科成绩均不低于60分),录取最低专业分224:艺专省控线文化分140专业分160,录取最低专业分181. 内蒙古:艺术本科省控线文化分279专业分199 ...
- 详解自然语言处理5大语义分析技术及14类应用(建议收藏)
导读:自然语言处理(Natural Language Processing,NLP)技术是与自然语言的计算机处理有关的所有技术的统称,其目的是使计算机能够理解和接受人类用自然语言输入的指令,完成从一种 ...
最新文章
- pytorch.forward()方法
- Ajax[Mount]
- C++细节系列(零):零散记录
- C++ puts函数 打印字符串很方便
- (转)uml 静态视图关系和关联
- 腾讯云北京技术沙龙邀请函:AI技术全面场景化落地实践
- Idea之配置GitLab ssh key
- 企业网站开发需要注意什么事项?
- 简易的安卓天气app(四)——搜索城市、完善页面
- 浅读《图解密码技术》--学习笔记
- GIS空间分析 缓冲区分析与叠加分析1 选址分析(市区择房)
- 组块(chunking)-nltkspacy
- chrome-调试按钮详解
- 北漂9年了,37岁的我跳槽进了国企,开启了一段新的人生旅程
- 小木虫内蒙古科技大学计算机,2019年内蒙古科技大学招收考研调剂(二)
- 费率与利率的差别_费率是什么(利率和费率有啥区别?)
- 12563 劲歌金曲
- CMMI特定目标(SG)和特定实践(SP)汇总
- WordArt怎样生成中文词云?
- java毕业设计校园内推系统mybatis+源码+调试部署+系统+数据库+lw