Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a function that can be either cdecl or stdcall

I need to write code that calls an external function that can be either stdcall call or cdecl in a 32bit windows application.
My code, the caller, can't know in advance which of these its going to be. Right now, if I try to call a cdecl function from a call site that was defined as stdcall, I get a checkEsp exception dialog, and I'm guessing that's there for a good reason.
Is there any way to do it?

like image 777
shoosh Avatar asked Jul 13 '13 00:07

shoosh


People also ask

What does __ Stdcall mean?

__stdcall is a calling convention: a way of determining how parameters are passed to a function (on the stack or in registers) and who is responsible for cleaning up after the function returns (the caller or the callee).

What is meant by calling convention?

In computer science, a calling convention is an implementation-level (low-level) scheme for how subroutines receive parameters from their caller and how they return a result.

What are calling conventions in C++?

Calling conventions specify how arguments are passed to a function, how return values are passed back out of a function, how the function is called, and how the function manages the stack and its stack frame. In short, the calling convention specifies how a function call in C or C++ is converted into assembly language.

What is the use of __ cdecl?

The __cdecl keyword instructs the compiler to read and write a parameter list by using C linkage conventions. To set the __cdecl calling convention for a function, place the linkage keyword immediately before the function name or at the beginning of the declarator.


2 Answers

It can be done following way:

          mov     esi, esp

          push    arg3
          push    arg2
          push    arg1
          call    [SomeExternalProc]

          mov     esp, esi   ; now the stack is always properly cleaned 

The external procedure will preserve esi. Or you can use any other register preserved by the external procedure or even memory variable - local or global.

Good, the order of the arguments is the same for CDECL and STDCALL - in reverse order. (Left-most arg at the lowest address.) So they're compatible except for where ESP points on return. Both conventions agree on which registers are call-preserved vs. call-clobbered.

like image 66
johnfound Avatar answered Sep 27 '22 21:09

johnfound


You can also use alloca() which has the side effect of saving and restoring the stack pointer:

{
    alloca( (uintptr_t)callback & 2 );
    callback();
}
like image 40
Sam Lantinga Avatar answered Sep 27 '22 19:09

Sam Lantinga