调用dll中的函数中stdcall和cdecl的问题

bxh566 2011-01-10 01:31:22
我需要调用一个dll中的函数,dll的接口文档里说明了是stdcall的调用约定。
而我再vc++中调用的时候,声明函数中加上stdcall,在运行的时候会出现下面一段信息:
The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
而我在声明中不加stdcall,就不会出现上面的信息,函数调用正常。
查看下网上的一些资料,没有看出个所以然。
请高手解释下为什么加上stdcall会出现这段信息?
如果不加的话,会不会有什么影响?如果我想加上stdcall的话,需要在调用的时候怎么弄(不能修改dll)?

另,dll导出的函数是直接一个函数名,比如:add,没有像网上有些描述的有_或者@
...全文
364 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
bxh566 2011-01-10
  • 打赏
  • 举报
回复
dll是显式加载的,我只有dll和一份接口文档。
虽然还是不知道到底是文档中的调用约定写错,还是其他原因造成的。
不过现在用cdecl调用结果是没有问题。
谢谢各位,把贴先结了。
之前没有做过这方面的东西,等有空了,再好好研究下。
zhanshen2891 2011-01-10
  • 打赏
  • 举报
回复
对了,你不是隐式加载的么??难道它的头文件里没写调用约定???
zhanshen2891 2011-01-10
  • 打赏
  • 举报
回复
如果你懂汇编直接进行汇编级调试一下就知道它到底是标准调用约定还是C调用约定了,不过按你说这情况应该是文档写错了,那个dll是C调用约定的。
无言猪 2011-01-10
  • 打赏
  • 举报
回复
那只能说明文档里面写的错误了.这个函数的堆栈调用约定是__cdecl的,他确写成了__stdcall.如果是__cdecl,由调用函数进行堆栈的清理,比如A调用B,一般就是push param1 push param2 .... call B add esp, n .而在B里面不会清理堆栈,最后直接ret了. 如果是__stdcall ,在B里面就会清理堆栈,retn N . 你碰到的情况就是大家的约定不一样,那个函数本来是__cdecl,就是要你这个调用者来清理堆栈,而你没有清理,而他也不清理.所以在调用这个函数的前后的esp就不一样了,在vs 2005以上的debug版本里面都加了esp检查的,就报错了.
「已注销」 2011-01-10
  • 打赏
  • 举报
回复
1: __stdcall,pascal,__fastcall 在定长参数时,函数自己恢复栈,__cdecl在定长参数时,调用者恢复栈
2: __stdcall,pascal,__cdecl,__fastcall 在变长参数时,调用者恢复栈
3: thiscall (本身不是关键字,是C++类函数默认声明方式),在定长参数时,函数自己恢复栈(this 指针不入栈);在变长参数时,调用者恢复栈(thsi指针入栈).



-----------上面信息记不清了,也许有错误,你自己搜一下资料吧.关键字"调用约定".
bxh566 2011-01-10
  • 打赏
  • 举报
回复
谢谢oyljerry

不过我把工程属性中的调用约定改成_stdcall后,函数声明中加上stdcall或者不加,都会出现那段debug error信息了。
只有在声明中加上__cdecl后,才不会出现那段信息.
这个是不是说明就是应该要加上cdecl来调用?网上没有查到相关的说明。

忘说了一点,出现那段信息后,我点忽略,函数调用结果却是正常
oyljerry 2011-01-10
  • 打赏
  • 举报
回复
查看你vc工程属性中的调用约定,把那个改成_stdcall试试。

导出函数可以用def等,指定名称,编译器就不会修饰了

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧