Reputation: 4133
I am trying to figure out how to set global Windows hooks inside of Rust. I can find multiple examples for other languages, but there doesn't seem to be anything for Rust.
What I managed to get so far:
extern crate user32;
extern crate winapi;
const WH_KEYBOARD_LL: i32 = 13;
fn main() {
let hook_id = user32::SetWindowsHookExA(
WH_KEYBOARD_LL,
Some(hook_callback),
// No idea what goes here ,
0,
);
}
fn hook_callback(code: i32, wParam: u64, lParam: i64) -> i64 {
// ...
}
The compiler complains that it needs a "system" fn
for the callback function, but is getting a Rust fn
, which makes sense, but I still don't know how to make that work.
From what I gathered from the documentation, the third parameter hMod
should point to the same module that has the callback function, and the examples in other languages uses some function that gets the current module handle, but I don't know how to do that in Rust.
Upvotes: 2
Views: 2955
Reputation: 65069
The compiler complains that it needs a "system"
fn
for the callback function, but is getting a Rustfn
, which makes sense, but I still don't know how to make that work.
The compiler actually gives you exactly what you need ... if you continue reading the error you'll see:
expected type `unsafe extern "system" fn(i32, u64, i64) -> i64`
found type `fn(i32, u64, i64) -> i64 {hook_callback}`
Adding that, gives:
extern "system" fn hook_callback(code: i32, wParam: u64, lParam: i64) -> i64 {
0
}
From what I gathered from the documentation, the third parameter
hMod
should point to the same module that has the callback function, and the examples in other languages uses some function that gets the current module handle, but I don't know how to do that in Rust.
Again, reading further into the WinAPI documentation shows that NULL
should be the value of this parameter if the thread ID (the last argument) specifies that its within the same process. Since you've passed zero - which the documentation states is associated with all threads in the current process ... that's what it should be... NULL
. So now we get:
let hook_id =
user32::SetWindowsHookExA(WH_KEYBOARD_LL, Some(hook_callback), std::ptr::null_mut(), 0);
This compiles.
Accounting for the other errors around unsafe
that you'll get ... this gives you (full working code):
extern crate user32;
extern crate winapi;
const WH_KEYBOARD_LL: i32 = 13;
fn main() {
unsafe {
let hook_id =
user32::SetWindowsHookExA(WH_KEYBOARD_LL, Some(hook_callback), std::ptr::null_mut(), 0);
// Don't forget to release the hook eventually
user32::UnhookWindowsHookEx(hook_id);
}
}
extern "system" fn hook_callback(code: i32, wParam: u64, lParam: i64) -> i64 {
0
}
Upvotes: 9