今天遇到一个问题用C++编写一个动态链接库生成的文件为dll.dll,用在visual stdio 2010调用这个dll

调用形式:[DllImport("dll.dll")]

出现了如下问题:

对 PInvoke 函数“TestDLL!TestDLL.Program::write”的调用导致堆栈不对称。
原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。
请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。
 
一开始我以为是因为函数传了指针,所以把指针改成了传整型变量,依然出现上述问题,查了网上的解决方案,
解决方案一:要在调用时加上[DllImport("dll.dll", CallingConvention = CallingConvention.Cdecl)]手册给出的意思是使用Cdecl(即调用方清理堆栈)。
解决方案二:在要生成dll的文件中,函数名前加上_stdcall,如:extern "C" __declspec(dllexport) int _stdcall write_test(int size)

两者之间的区别: WINDOWS的函数调用时需要用到栈(STACK,一种先入后出的存储结构)。当函数调用完成后,栈需要清除,这里就是问题的关键,如何清除?? 如果我们的函数使用了_cdecl,那么栈的清除工作是由调用者,用COM的术语来讲就是客户来完成的。这样带来了一个棘手的问题,不同的编译器产生栈的方式不尽相同,那么调用者能否正常的完成清除工作呢?答案是不能。 如果使用__stdcall,上面的问题就解决了,函数自己解决清除工作。所以,在跨(开发)平台的调用中,我们都使用__stdcall(虽然有时是以WINAPI的样子出现)。那么为什么还需要_cdecl呢?当我们遇到这样的函数如fprintf()它的参数是可变的,不定长的,被调用者事先无法知道参数的长度,事后的清除工作也无法正常的进行,因此,这种情况我们只能使用_cdecl。到这里我们有一个结论,如果你的程序中没有涉及可变参数,最好使用__stdcall关键字。

而__cdecl是C/C++和MFC程序默认使用的调用约定。

_stdcall 和 _cdecl的更多相关文章

  1. _stdcall与_cdecl(了解)

    调用约定(Calling Convention)是指在程序设计语言中为了实现函数调用而建立的一种协议.这种协议规定了该语言的函数中的参数传送方式.参数是否可变和由谁来处理堆栈等问题.不同的语言定义了不 ...

  2. _stdcall与_cdecl

    _cdecl(C Declaration的缩写)是C/C++和MFC程序默认使用的调用约定,因此可以省略,也可以在函数声明时加上_cdecl关键字来手工指定.采用_cdecl约定时,函数参数按照从右到 ...

  3. 转:函数调用的区别:_cdecl以及_stdcall

    函数调用的几个概念:_stdcall,_cdecl.... 1._stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈.VC将 ...

  4. __cdecl 、__fastcall、__stdcall

    调用约定: __cdecl __fastcall与 __stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数 ...

  5. _fastcall

    * 1楼 __fastcall具体含义 在C语言中,假设我们有这样的一个函数: int function(int a,int b) 调用时只要用result = function(1,2)这样的方式就 ...

  6. __cdecl __stdcall __fastcall之函数调用约定讲解

    首先讲解一下栈帧的概念: 从逻辑上讲,栈帧就是一个函数执行的环境:函数参数.函数的局部变量.函数执行完后返回到哪里等等. 实现上有硬件方式和软件方式(有些体系不支持硬件栈) 首先应该明白,栈是从高地址 ...

  7. Linux--变量与虚拟内存

    定义一个变量:存储类型  数据类型  变量名 存储类型(变量存储的位置):auto.register.static.extern 1.auto:对于局部变量,atuo可以缺省.位置:栈 2.exter ...

  8. VC内存溢出一例 –- 调用约定不一致 (_CRT_DEBUGGER_HOOK(_CRT_DEBUGGER_GSFAILURE)

    VC (_CRT_DEBUGGER_HOOK(_CRT_DEBUGGER_GSFAILURE) 问题记录 VC内存溢出一例 –- 调用约定不一致 (_CRT_DEBUGGER_HOOK(_CRT_DE ...

  9. C/C++:函数的编译方式与调用约定以及extern “C”的使用

    转自:https://www.cnblogs.com/qinfengxiaoyue/archive/2013/02/04/2891908.html 函数在C++编译方式与C编译方式下的主要不同在于:由 ...

随机推荐

  1. Fuel 30 分钟快速安装OpenStack

    一直以来,对于openstack 的初学者来讲,安装往往是入门的头大难题.在E版本之前,要搭建一个基本能用的openstack 环境那是相当麻烦,自己要装机,自己搞源,自己照着文档敲命令,又没有靠谱的 ...

  2. loglevel-metamask

    pimterry/loglevel https://github.com/pimterry/loglevel Minimal lightweight simple logging for JavaSc ...

  3. RedHat 7.3 Oracle 12.2.0.1 RAC 安装手册(转)

    1  准备工作 1.1   关于GRID的一些变化 1.1.1  简化的基于映像的Oracle Grid Infrastructure安装 从Oracle Grid Infrastructure 12 ...

  4. python+requests实现接口测试 - get与post请求使用(转载)

    转自:http://www.cnblogs.com/nizhihong/p/6567928.html 简介:Requests 是用Python语言编写,基于 urllib,采用 Apache2 Lic ...

  5. 【hdu4405】AeroplaneChess

    题目大意:问从0到n所花费时间平均时间.每次有投骰子,投到几就走几步.原题还有坐飞机 #include<iostream> #include<cmath> #include&l ...

  6. shell杂记

    (本文将持续更新)从2015年9月25日开始正式学习linux类的东西. 书籍入门:UNIX.Shell编程24学时教程(中文版).Linux与UNIX Shell编程指南.shell十三问.LINU ...

  7. 20155311《网络对抗》Web基础

    20155311<网络对抗>Web基础 实验过程 Web前端:HTML 使用netstat -aptn查看80端口是否被占用(上次实验设置为Apache使用80端口),如果被占用了就kil ...

  8. post请求参数Json字符串包含数组的校验和处理

    传入参数类型 {"aaa":"aaaa","bbb":"bbb","ccc":"ccc&q ...

  9. 基于Vue手写一个下拉刷新

    当然不乏有很多下拉刷新的插件可以直接使用,但是自定义程度不强,大部分都只能改改文字,很难满足设计师的创意,譬如淘宝和京东首页那种效果,就需要自己花心思倒腾了,最近刚好有这种需求,做完了稍微总结一下,具 ...

  10. Js_图片切换左右点击

    <!DOCTYPE HTML><html><head><meta http-equiv="Content-Type" content=&q ...