I'm trying to open a window with the Windows API and for learning purposes I decided to write the bindings myself for the moment.
Among other bindings, I have defined the WNDPROC
type and a handler function:
pub type WNDPROC = unsafe extern "system" fn(HWND, UINT, WPARAM, LPARAM) -> LRESULT;
#[no_mangle]
pub unsafe extern "system" fn WndProc(
hwnd: HWND,
uMessage: UINT,
wParam: WPARAM,
lParam: LPARAM,
) -> LRESULT
{
match uMessage
{
_ => DefWindowProcW(hwnd, uMessage, wParam, lParam),
}
}
I then pass the function to the window class by name (lpfnWndProc: WndProc
), and that works, the handler gets called, the handle is valid, I get a window.
However, when I tried matching other uMessages
, the call to CreateWindowExW
started returning NULL
. After some tests, it turns out whatever statement I put on the handler function before the DefWindowProcW
call breaks it:
// When this is the body of WndProc, createWindow returns NULL
match uMessage
{
0x0010 =>
{
DestroyWindow(hwnd);
0 as LRESULT
},
_ => DefWindowProcW(hwnd, uMessage, wParam, lParam),
}
// When this is the body of WndProc, createWindow returns NULL
println!("");
match uMessage
{
_ => DefWindowProcW(hwnd, uMessage, wParam, lParam),
}
// Works fine
let res = DefWindowProcW(hwnd, uMessage, wParam, lParam);
let a = 1;
let b = 1;
println!("{}", a + b);
res
Am I missing something obvious here? Are there any common mistakes when passing function pointers to Windows?
Checking with a debugger, the execution flow looks normal and the correct match arm is hit. I'm running out of ideas besides checking the generated assembly, but I'm not quite competent enough to do that without significant pain.