Re: StdCall vs. CDecl
- From: jialge@xxxxxxxxxxxxxxxxxxxx ("Jialiang Ge [MSFT]")
- Date: Tue, 15 Jul 2008 11:09:21 GMT
Hello Bob,
Apart from Jeroen's inputs, I'd like to add my ideas of this issue.
First, let's look at the pure native world (without .NET).
__stdcall means that the function itself will remove the args from the
stack. __cdecl means that the caller needs to remove the args. If you call
a __cdecl function as __stdcall, it means that the function will expect the
caller to clean up the stack, while the caller will expect the function to
clean up the stack. This means that nobody will clean up the stack.
(It's like two roommates that each believe that the other is going to pay
the rent bill. This will result in the rent not being paid (unless there
happened to be no rent due that month) with equally bad consequences.)
This will work if the function takes no arguments (nothing to clean up), or
if immediately after the function returns, the next thing happens to be
something that "autofixes" the stack (e.g., the caller immediately returns
to its caller and uses something like EBP to restore its stack frame (so
the current value of ESP doesn't matter). This is exceedingly fragile.
[If you call a __stdcall function as __cdecl, it means that the function
will clean up the stack and then the caller will also cleanup the stack,
resulting in too much being removed from the stack with equally disastrous
consequences.]
Now, why does our VB.NET code work well when the calling convention
mismatches?
This is because the .NET interop layer is able (to a certain extend) to fix
the calling convention mismatches. See:
http://msdn.microsoft.com/en-us/library/ms998551.aspx
The RCW is responsible for marshaling parameters as execution flow
transitions between managed code and unmanaged code. Calling into unmanaged
COM code from managed code is made easy by the CLR; however, it carries a
performance cost. The following steps are performed:
Perform data marshaling.
*Fix the calling convention.*
Protect callee-saved registers.
Switch thread mode to ensure that the garbage collector does not block
unmanaged threads.
Erect an exception-handling frame on calls into unmanaged code.
Optionally take control of the thread.
Though this article is for COM-.NET Interop, the work of "fixing the
calling convention" is done by CLR. However, we'd better change our code so
the caller matches the callee, otherwise, there may be some performance
problems.
Please let me know if you have any other concerns, or need anything else.
P.S.
Bob, I sent another letter to your email box yesterday, to illustrate the
differences between the calling conventions. Have you received it? I am not
able to paste the comparison in newsgroup because it contains some rich
texts.
Regards,
Jialiang Ge (jialge@xxxxxxxxxxxxxxxxxxxx, remove 'online.')
Microsoft Online Community Support
=================================================
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
msdnmg@xxxxxxxxxxxxxx
This posting is provided "AS IS" with no warranties, and confers no rights.
=================================================
.
- References:
- StdCall vs. CDecl
- From: Bob Altman
- Re: StdCall vs. CDecl
- From: Jeroen Mostert
- Re: StdCall vs. CDecl
- From: Bob Altman
- Re: StdCall vs. CDecl
- From: Jeroen Mostert
- Re: StdCall vs. CDecl
- From: Bob Altman
- Re: StdCall vs. CDecl
- From: Jeroen Mostert
- Re: StdCall vs. CDecl
- From: Bob Altman
- StdCall vs. CDecl
- Prev by Date: returning and accessing an object via com
- Next by Date: Get data from VARIANT
- Previous by thread: Re: StdCall vs. CDecl
- Next by thread: interop dll file version - where does it come from?
- Index(es):
Relevant Pages
|