Как использовать SetWindowsHookEx в Rust? - PullRequest
0 голосов
/ 26 июня 2018

Я пытаюсь выяснить, как установить глобальные хуки для Windows внутри Rust.Я могу найти несколько примеров для других языков, но для Rust, похоже, ничего нет.

Что мне удалось получить до сих пор:

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 {
    // ...
}

Компилятор жалуется, что ему нужна "system" fn для функции обратного вызова, но получает Rust fn,это имеет смысл, но я все еще не знаю, как заставить это работать.

Из того, что я собрал из документации, третий параметр hMod должен указывать на тот же модуль, который имеет функцию обратного вызова, ипримеры в других языках используют некоторую функцию, которая получает текущий дескриптор модуля, но я не знаю, как это сделать в Rust.

1 Ответ

0 голосов
/ 26 июня 2018

Компилятор жалуется, что ему нужна "system" fn для функции обратного вызова, но он получает Rust fn, что имеет смысл, но я все еще не знаю, как заставить это работать.

Компилятор на самом деле дает вам точно то, что вам нужно ... если вы продолжите читать ошибку, вы увидите:

expected type `unsafe extern "system" fn(i32, u64, i64) -> i64`
   found type `fn(i32, u64, i64) -> i64 {hook_callback}`

Добавление этого,дает:

extern "system" fn hook_callback(code: i32, wParam: u64, lParam: i64) -> i64 {
    0
}

Из того, что я собрал из документации, третий параметр hMod должен указывать на тот же модуль, который имеет функцию обратного вызова, а в примерах на других языках используется некоторая функция, котораяполучает текущий дескриптор модуля, но я не знаю, как это сделать в Rust.

Опять же, чтение далее в документации WinAPI показывает, что NULL должно быть значением этого параметра, еслиID потока (последний аргумент) указывает на то, что он находится внутри одного и того же процесса.Поскольку вы прошли ноль - состояние документации связано со всеми потоками в текущем процессе ... так оно и должно быть ... NULL.Итак, теперь мы получаем:

let hook_id =
    user32::SetWindowsHookExA(WH_KEYBOARD_LL, Some(hook_callback), std::ptr::null_mut(), 0);

Это компилируется.

Учет других ошибок вокруг unsafe, которые вы получите ... это дает вам (полный рабочий код):

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
}
...