原文:http://blog.sina.com.cn/s/blog_3f27dee60100qi4j.html

一直搞不懂为什么在函数前面加上WINAPI、CALLBACK等是什么意思 又不是返回值 为什么加在前面 今天终于知道了 这是一个呼叫声明(姑且称之吧)。

引子:

看看这个函数:

int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
{
     MSG msg;

//进行程序的初始化工作
     if(!AppInit(hInst,hPrev,sw))
         return FALSE;

//消息循环处理
     for(;;)
     {
         while(PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))//Peek只是查看事件,一般不作任何处理
                          //Get会做一些例行处理,并且把事件从队列中删除掉(WM_PAINT除外)

//通常先peek,看某事件是否存在,再get,进行处理

//未经严格测试:如果你get某个在队列中不存在的事件,程序会陷入等待,但是peek总是立即返回

{
             if(msg.message == WM_QUIT)
                 break;   // Leave the PeekMessage while() loop
     //TranslateAccelerator将WM_KEYDOWN和WM_SYSYKEYDOWN消息翻译成为WM_COMMAND消息,
//然后直接将消息送到相关的窗口过程中去,直到消息被处理后才返回值
             if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
                 continue;

TranslateMessage(&msg);
             DispatchMessage(&msg);
         }

if(msg.message == WM_QUIT)
             break;   // Leave the for() loop

WaitMessage();//当本窗口的消息序列中没有消息的时候,将控制权交给其他的线程直到再次有消息进入自己的消息队列中时才返回
     }

// Reached on WM_QUIT message
     CoUninitialize();
     return ((int) msg.wParam);
}

别的先别看,现看看这个PASCAL :

The __pascal, __fortran, and __syscall calling conventions are no longer supported. You can emulate their functionality by using one of the supported calling conventions and appropriate linker options.

WINDOWS.H now supports the WINAPI macro, which translates to the appropriate calling convention for the target. Use WINAPI where you previously used PASCAL or __far __pascal.

看来现在用WINAPI来代替己经不用的PASCAL了,那么WINAPI是什么呢?

WINAPI:

查看WINAPI的定义:(WINDOWS.H)

#define WINAPI FAR PASCAL

WINAPI:Use in place of FAR PASCAL in API declarations. If you are writing a DLL with exported API entry points, you can use this for your own APIs.

原来是个宏定义。用法也说到了,你可以使用WINAPI来为自己的API写一个DLL文件(有导出的API入口点的DLL,废话,没有API入口,要DLL干什么?)。

消息处理函数就是这么定义的:LONG WINAPI   AppWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){}

在VC++ 6.0中,WINDEF.h

#define WINAPI       CDECL //=_cdecl

#define CALLBACK     PASCAL //=_pascal,VC已经不支持直接使用_pascal了

顺便提下CALLBACK:CALLBACK:Use in place of FAR PASCAL in application callback routines such as window procedures and dialog procedures.

在BCB(Boland C++ Builder )中:windef.h

#define WINAPI       __stdcall

#define CALLBACK     __stdcall

具体来说,他们是关于堆栈的一些说明,首先是函数参数压栈顺序,其次是压入堆栈的内容由谁来清除,调用者还是函数自己?

简单说明:

__cdecl是C/C++和MFC程序默认使用的调用约定,也可以在函数声明时加上__cdecl关键字来手工指定。采用__cdecl约定时,函数参数按照从右到左的顺序入栈,并且由调用函数者把参数弹出栈以清理堆栈。因此,实现可变参数的函数只能使用该调用约定。由于每一个使用__cdecl约定的函数都要包含清理堆栈的代码,所以产生的可执行文件大小会比较大。__cdecl可以写成_cdecl。
__stdcall调用约定用于调用Win32 API函数。采用__stdcal约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。由于函数体本身知道传进来的参数个数,因此被调用的函数可以在返回前用一条ret n指令直接清理传递参数的堆栈。__stdcall可以写成_stdcall。
__fastcall约定用于对性能要求非常高的场合。__fastcall约定将函数的从左边开始的两个大小不大于4个字节(DWORD)的参数分别放在ECX和EDX寄存器,其余的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的堆栈。__fastcall可以写成_fastcall。

特别说明:
1. 在默认情况下,采用__cdecl方式,因此可以省略.
2. WINAPI一般用于修饰动态链接库中导出函数
3. CALLBACK仅用于修饰回调函数
4. VC下和BCB下对WINAPI的定义不同,所以不能直接从BCB下调用VC的dll的一个原因了。

看来WINAPI与DLL关系很密切,所以还应该探讨一下DLL啊。下次说吧。

【转载】WINAPI宏的更多相关文章

  1. [转载]C宏定义的小结

    FROM:http://blog.csdn.net/sunboy_2050/article/details/6103530 实现代码实例 程序代码: #include <stdio.h> ...

  2. C++ 小知识点 WINAPI

    int WINAPI WINMain 中,WINAPI含义 网友给出回答:在windef.h头文件中有如下定义#define WINAPI      __stdcall#define APIENTRY ...

  3. WINAPI和APIENTRY是一样的

    今天写线程函数时,发现msdn中对ThreadProc的定义有要求:DWORD WINAPI ThreadProc(LPVOID lpParameter); 不解为什么要用WINAPI宏定义,查了后发 ...

  4. [c++] WINAPI

    int WINAPI WINMain 中,WINAPI含义 在windef.h头文件中有如下定义: #define WINAPI __stdcall #define APIENTRY WINAPI 函 ...

  5. __declspec,__cdecl,__stdcall区别和作用

    _cdecl和__stdcall都是函数调用规范(还有一个__fastcall),规定了参数出入栈的 顺序和方法,如果只用VC编程的话可以不用关心,但是要在C++和Pascal等其他语言通信的时候就要 ...

  6. __stdcall,__cdecl,_cdecl,_stdcall,。__fastcall,_fastcall 区别简介

    1. 今天写线程函数时,发现msdn中对ThreadProc的定义有要求:DWORD WINAPI ThreadProc(LPVOID lpParameter); 不解为什么要用WINAPI宏定义,查 ...

  7. C/C++函数调用的几种方式及函数名修饰规则以及c++为什么不允许重载仅返回类型不同的函数

    我们知道,调用函数时,计算机常用栈来存放函数执行需要的参数,由于栈的空间大小是有限的,在windows下栈是向低地址扩展的数据结构,是一块连续的内存区域.这句话的意思是栈顶的地址和栈的最大容量是系统预 ...

  8. C/C++ 函数压栈方式

    一,不同关键字,系统压栈方式 1,如果函数func是__cdecl(VC下的默认调用方式),调用时情况如下 int   main()   {   //参数从右到左压栈   push   4   pus ...

  9. __cdecl、__stdcall、__fastcall、thiscall 进栈、出栈区别

    https://en.wikipedia.org/wiki/X86_calling_conventions https://msdn.microsoft.com/en-us/library/984x0 ...

随机推荐

  1. 团队项目个人进展——Day09

    一.昨天工作总结 冲刺第九天,把地图和界面整合了一下 二.遇到的问题 地图的样式和一些公共样式有冲突 三.今日工作规划 团队共同整合程序,做出第一阶段的成品.

  2. VMware部署ubuntu后开机提示piix4_smbus: Host SMBus controller not enabled!

    在虚拟机部署ubuntu10.04-server,每次启动完成之后,出现“piix4_smbus0000:00:07.3: Host SMBus controller not enabled!”提示信 ...

  3. 反向代理负载均衡调度:nginx

    一.概述 反向代理:以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个 ...

  4. Windows窗体数据抓取详解

    最近在客户项目上刚好遇到一个问题,项目需求是要获取某台机床的实时状态,问题点刚好就在于该机床不是传统意义上的数控机床,也不是PLC控制器,只有一个上传下载程序文件的应用程序,上面刚好有几个按钮可以大概 ...

  5. Office 手动kms激活方法

    服务作用:在线激活windows和office 适用对象:VOL版本的windows和office 适用版本:截止到win10和office2016的所有版本 服务时间:24H,偶尔更新维护 优点:在 ...

  6. ansible 增加本机/etc/hosts 下hostsname 与IP

    --- - hosts: all vars: IP: "{{ ansible_eth0['ipv4']['address'] }}" tasks: - name: 将原有的host ...

  7. vs2008编译openssl,静态库/动态库,批处理

    ::前期准备准备工作::1,下载安装好ActivePerl,::2,下载Openssl源码::3,本机有安装vc::4,此例在vs2008(vc9),openssl-1.0.2o下完成 echo of ...

  8. SDN2017 第四次作业

    1.阅读 了解SDN控制器的发展 http://www.sdnlab.com/13306.html http://www.docin.com/p-1536626509.html 了解ryu控制器 ht ...

  9. RMAN 备份数据库到DISK后进行数据恢复

    RMAN 备份数据库到DISK,然后进行数据恢复 一.rman备份 1. 全备脚本 vi bakup_level0.sql connect target / run { allocate channe ...

  10. mysql中的delete , drop 和truncate 区别

    1.delete 和 truncate 仅仅删除表数据,drop 连表数据和表结构一起删除,打个比方,delete 是单杀,truncate 是团灭,drop 是把电脑摔了. 2.delete 是 D ...