Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function pointers for winapi functions (stdcall/cdecl)

Please could someone give me a few tips for creating function pointers for MS winapi functions? I'm trying to create a pointer for DefWindowProc (DefWindowProcA/DefWindowProcW) but getting this error:

LRESULT (*dwp)(HWND, UINT, WPARAM, LPARAM) = &DefWindowProc;

error C2440: 'initializing' : cannot convert from 
'LRESULT (__stdcall *)(HWND,UINT,WPARAM,LPARAM)' 
to 'LRESULT (__cdecl *)(HWND,UINT,WPARAM,LPARAM)'

I can't figure out what I need to use because I am not used to the MS ascii/wide macros. By the way, I'm creating a function pointer to make a quick hack, and unfortunately I don't have time to explain why - but regardless, I think this question will be helpful to people who need to create winapi function pointers.

Update:

This code works, but I'm worried that it is bad practice (and does not adhere to unicode/ascii compile options). Should I define two specifications?

LRESULT (__stdcall* dwp)(HWND, UINT, WPARAM, LPARAM) = &DefWindowProc;

Update 2:

This is nicer (thanks to nobugz):

WNDPROC dwp = DefWindowProc;
like image 495
Nick Bolton Avatar asked Dec 28 '09 16:12

Nick Bolton


People also ask

What does __ Stdcall mean?

The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack, so the compiler makes vararg functions __cdecl . Functions that use this calling convention require a function prototype. The __stdcall modifier is Microsoft-specific.

When to use__ cdecl?

Place the __cdecl modifier before a variable or a function name. Because the C naming and calling conventions are the default, the only time you must use __cdecl in x86 code is when you have specified the /Gv (vectorcall), /Gz (stdcall), or /Gr (fastcall) compiler option.

How does cdecl work?

In cdecl, subroutine arguments are passed on the stack. Integer values and memory addresses are returned in the EAX register, floating point values in the ST0 x87 register. Registers EAX, ECX, and EDX are caller-saved, and the rest are callee-saved.


2 Answers

Fix the calling convention mismatch like this:

LRESULT (__stdcall * dwp)(HWND, UINT, WPARAM, LPARAM) = DefWindowProc;

A typedef can make this more readable:

typedef LRESULT (__stdcall * WindowProcedure)(HWND, UINT, WPARAM, LPARAM);
...
WindowProcedure dwp = DefWindowProc;

But, <windows.h> already has a typedef for this, you might as well use it:

WNDPROC dwp = DefWindowProc;
like image 79
Hans Passant Avatar answered Oct 26 '22 09:10

Hans Passant


You lack __stdcall in your prototype. You need to have a matching calling convention apart from a matching prototype. WINAPI functions are all __stdcall, while the default for C++ is __cdecl.

Using extern "C" { code } is a viable alternative.

like image 45
Kornel Kisielewicz Avatar answered Oct 26 '22 11:10

Kornel Kisielewicz