Win32函数调用约定(Calling Convention)

news2024/12/23 13:36:52

平常我们在C#中使用DllImportAttribute引入函数时,不指明函数调用约定(CallingConvention)这个参数,也可以正常调用。如FindWindow函数

[DllImport("user32.dll", EntryPoint="FindWindow", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

在DllImportAttribute类中, CallingConvention属性可以用于指明函数调用约定,默认值是Winapi(__stdcall),而Windows API函数默认的调用约定是Winapi(__stdcall),这也是为什么平常我们不指定CallingConvention值也能调用成功的原因。

函数调用约定

函数调用约定(Calling Convention)是指在函数调用时关于函数的多个参数入栈和出栈顺序的约定。

通俗地讲就是关于堆栈的一些说明,首先是函数参数压栈顺序,其次是压入堆栈的内容由谁来清除,调用者还是函数自己。如果函数调用约定不一致,在使用库中的导出函数时会调用异常。

下面介绍一下在Windows的库编程中的5种调用约定

__cdecl

__cdecl(_cdecl)调用约定又称为C调用约定,是C默认的调用约定,也是C++全局函数的默认调用约定,通常省略。在未指定调用约定时就默认为__cdecl,如下面两个写法是一样的

1 int sum(int num1,int num2);
2 int __cdecl sum(int num1,int num2);

在__cdecl调用约定下,函数的多个参数由调用者按从右到左的顺序压入堆栈,被调函数获得参数的序列是从左到右的,清理堆栈的工作由调用者负责,因为函数参数的个数是可变的。如果是被调函数清理堆栈,则参数个数必须确定,否则由于被调用函数事先无法知道参数的个数,事后的清除工作也将无法正常进行。

__stdcall

__stdcall(_stdcall)调用约定又称为Pascal调用约定,也是Pascal语言的调用约定,如下:

1 int __stdcall sum(int num1,int num2);

__stdcall调用约定下,函数的多个参数由调用者从右到左的顺序压入堆栈,被调函数获得参数的序列是从左到右的,清理堆栈的工作由被调用函数负责。

常用宏WINAPICALLBACK来表示 __stdcall调用约定。

1 #define CALLBACK __stdcall
2 #define WINAPI __stdcall

Windows API函数大部分是__stdcall约定,如文章最开头提到的FindWindow函数。

1 HWND
2 WINAPI
3 FindWindowA(
4     _In_opt_ LPCSTR lpClassName,
5     _In_opt_ LPCSTR lpWindowName);
6 WINUSERAPI

__fastcall调用约定

__fastcall调用约定称为快速调用约定,前两个双字(DWORD)参数或更小尺寸的参数通过寄存器ECX和EDX来传递,剩下的参数按照自右向左的顺序压栈传递,清理堆栈的工作由被调用者函数来完成。

1 int __fastcall sum(int num1,int num2);

thiscall调用约定

thiscall调用约定是C++中的非静态类成员函数的默认调用约定。thiscall只能被编译器使用,没有相应的关键字。因此不能手动指定。采用thiscall约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈。ECX寄存器传送一个额外的参数,this指针

naked call调用约定

naked call调用约定也称为裸调,是一个不大用的调用约定,不建议使用。编译器不会给这样的函数增加初台化和清理的代码。naked call不是类型修饰符,它必须和__declspec共同使用。

1 __declspec(naked) int sum(int num1,int num2);

未指定函数调用约定或函数调用约定错误的情况

如果函数调用约定错误,会出现如下这种:

Run-Time Check Failure #0- The value of ESP was not properly saved across a function call. Thie is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

我最近就遇到了这个问题,在C++动态去调用一个库中的函数,运行时就报这个错,后面给函数指针加上了__stdcall就调用成功了,类似下面这样

1 typedef void (__stdcall *FUNC)(int num1, int num2);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2115271.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

来啦| LVMH路威酩轩25届校招智鼎高潜人才思维能力测验高分攻略

路威酩轩香水化妆品(上海)有限公司是LVMH集团于2000年成立,负责集团旗下的部分香水化妆品品牌在中国的销售包括迪奥、娇兰、纪梵希、贝玲妃、玫珂菲、凯卓、帕尔马之水以及馥蕾诗等。作为目前全球最大的奢侈品集团LVMH 集团秉承悠久的历史,不断打破常规&…

群晖最新版(DSM 7.2) 下使用 Web Station 部署 flask 项目

0. 需求由来 为了在 DSM 7.2 版本下的群晖 NAS 里运行我基于 flask 3.0.2 编写的网页应用程序,我上网查了非常多资料,也踩了很多坑。最主要的就是 7.2 版本的界面与旧版略有不同,而网络上的资料大多基于旧版界面,且大部分仅仅说明…

记忆化搜索【下】

375. 猜数字大小II 题目分析 题目链接:375. 猜数字大小 II - 力扣(LeetCode) 题目比较长,大致意思就是给一个数,比如说10,定的数字是7,让我们在[1, 10]这个区间猜。 如果猜大或猜小都会说明…

2024AI绘画工具排行榜:探索最受欢迎的AI绘图软件特点与选择指南

AI绘画工具各有优势,从开放性到对特定语言和文化的支持,以及对图像细节和艺术性的不同关注点,根据具体需求选择合适的工具 MidJourney 图片品质卓越,充满独特创意,初期能够免费获取数十账高质量图片,整个生…

C++20中支持的非类型模板参数

C20中支持将类类型作为非类型模板参数:作为模板参数传入的对象具有const T类型,其中T是对象的类型,并且具有静态存储持续时间(static storage duration)。 在C20之前,非类型模板参数仅限于:左值引用类型、整数类型、指…

VMware Fusion Pro 13 Mac版虚拟机 安装Win11系统教程

Mac分享吧 文章目录 Win11安装完成,软件打开效果一、VMware安装Windows11虚拟机1️⃣:准备镜像2️⃣:创建虚拟机3️⃣:虚拟机设置4️⃣:安装虚拟机5️⃣:解决连不上网问题 安装完成!&#xff0…

用Pytho解决分类问题_DBSCAN聚类算法模板

一:DBSCAN聚类算法的介绍 DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的聚类算法,DBSCAN算法的核心思想是将具有足够高密度的区域划分为簇,并能够在具有噪声的空间数据库中发…

关于SpringMVC的理解

1、SpringMVC 应用 1.1、简介 1.1.1、MVC 体系结构 三层架构: 我们的开发架构⼀般都是基于两种形式,⼀种是 C/S 架构,也就是客户端/服务器;另⼀种是 B/S 架构,也就是浏览器服务器。在 JavaEE 开发中,⼏乎…

陪护系统|陪护系统源码|护理陪护小程序

随着医疗水平的不断提高,人们对护理服务的需求也越来越高。为了更好地满足患者和家属的需求,陪护系统定制开发应运而生。 陪护系统定制开发是根据医疗机构的实际需求,设计并开发一套专门用于陪护服务的系统。该系统拥有一系列丰富的功能&…

基于人工智能的图片生成系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图片生成是计算机视觉领域的一个重要任务,基于生成对抗网络(GAN)的图片生成系统能够从噪声中生成逼…

大数据-119 - Flink Window总览 窗口机制-滚动时间窗口-基于时间驱动基于事件驱动

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…

揭秘 AMD GPU 上 PyTorch Profiler 的性能洞察

Unveiling performance insights with PyTorch Profiler on an AMD GPU — ROCm Blogs 2024年5月29日,作者:Phillip Dang。 在机器学习领域,优化性能通常和改进模型架构一样重要。在本文中,我们将深入探讨 PyTorch Profiler&#…

小白建立个人网站初步尝试

一、VScode 代码是在VScode上运行的&#xff0c;可以看作者另一篇文章&#xff1a;http://t.csdnimg.cn/mOmdF 二、代码基本框架 代码解释<!DOCTYPE html>声明为HTML5文档<html><head>头部元素&#xff0c;不显示在页面<meta charset"utf-8"…

数学建模强化宝典(14)Fisher 最优分割法

前言 Fisher最优分割法是一种对有序样品进行聚类的方法&#xff0c;它在分类过程中不允许打破样品的顺序。这种方法的目标是找到一种分割方式&#xff0c;使得各段内样品之间的差异最小&#xff0c;而各段之间的差异最大。以下是关于Fisher最优分割法的详细介绍&#xff1a; 一…

【LeetCode热题100】前缀和

这篇博客共记录了8道前缀和算法相关的题目&#xff0c;分别是&#xff1a;【模版】前缀和、【模版】二维前缀和、寻找数组的中心下标、除自身以外数组的乘积、和为K的子数组、和可被K整除的子数组、连续数组、矩阵区域和。 #include <iostream> #include <vector> …

【408数据结构】散列 (哈希)知识点集合复习考点题目

苏泽 “弃工从研”的路上很孤独&#xff0c;于是我记下了些许笔记相伴&#xff0c;希望能够帮助到大家 知识点 1. 散列查找 散列查找是一种高效的查找方法&#xff0c;它通过散列函数将关键字映射到数组的一个位置&#xff0c;从而实现快速查找。这种方法的时间复杂度平均为…

自我指导:提升语言模型自我生成指令的能力

人工智能咨询培训老师叶梓 转载标明出处 传统的语言模型&#xff0c;尤其是经过指令微调的大型模型&#xff0c;虽然在零样本&#xff08;zero-shot&#xff09;任务泛化上表现出色&#xff0c;但它们高度依赖于人类编写的指令数据。这些数据往往数量有限、多样性不足&#xf…

配置Java(JDK)环境变量

一、配置JDK环境变量 将JDK-22压缩包加压缩到指定目录下面&#xff0c;本机路径是&#xff1a;C:\Program Files\Java&#xff08;可以加压缩到自己的指定路径&#xff0c;记住这个路径&#xff0c;配置环境变量时候要使用&#xff09;。 鼠标右键“此电脑”&#xff0c;点击“…

独立按键单击检测(延时消抖+定时器扫描)

目录 独立按键简介 按键抖动 模块接线 延时消抖 Key.h Key.c 定时器扫描按键代码 Key.h Key.c main.c 思考 MultiButton按键驱动 独立按键简介 ​ 轻触按键相当于一种电子开关&#xff0c;按下时开关接通&#xff0c;松开时开关断开&#xff0c;实现原理是通过轻触…

Spring框架-----ioc

基本概念 Spring 是一个轻量级的,IOC和AOP的一站式Java 开发框架&#xff0c;是为了简化企业级应用开发而生的 轻量级&#xff1a;框架核心模块体积小 IOC:Inversion of Control&#xff08;控制反转&#xff09;把创建对象的控制权反转给Spring框架管理 以前我们程序中需要…