I have the following code:
use bindings::Windows::Win32::DisplayDevices::POINT;
use bindings::Windows::Win32::Gdi::{GetPixel, GetWindowDC, HDC};
use bindings::Windows::Win32::SystemServices::{BOOL, PSTR};
use bindings::Windows::Win32::WindowsAndMessaging::{self, FindWindowA, HWND};
use std::ffi::CString;
fn main() {
let mut window_name_2 = "Window Title";
let hwnd;
unsafe { hwnd = FindWindowA(std::ptr::null_mut(), window_name_2) }
}
It produces the error:
bindings::Windows::Win32::WindowsAndMessaging
pub unsafe fn FindWindowA<'a, T0__, T1__>(lpclassname: T0__, lpwindowname: T1__) -> HWND
where
T0__: ::windows::IntoParam<'a, super::superSystemServices::PSTR>,
T1__: ::windows::IntoParam<'a, super::superSystemServices::PSTR>,
the trait bound `*mut _: windows::traits::into_param::IntoParam<'_, PSTR>` is not satisfied
the trait `windows::traits::into_param::IntoParam<'_, PSTR>` is not implemented for `*mut _`rustcE0277
main.rs(1, 1): required by a bound in this
windows.rs(311, 23): required by this bound in `FindWindowA`
I don't understand what this means or how to fix it.
Version 0.8.0 of the windows-rs crate switched to using impl Trait
, making both the signatures easier to read, as well as decluttering the error diagnostics.
Given the code in the question, the error message now reads:
error[E0277]: the trait bound `*mut _: IntoParam<'_, PSTR>` is not satisfied
--> src\main.rs:11:21
|
11 | unsafe { hwnd = FindWindowA(std::ptr::null_mut(), window_name_2) }
| ^^^^^^^^^^^ the trait `IntoParam<'_, PSTR>` is not implemented for `*mut _`
|
::: C:\...\target\debug\build\findwindow_test-67a9095d9a724f24\out/windows.rs:129:27
|
129 | pub unsafe fn FindWindowA<'a>(
| ----------- required by a bound in this
130 | lpclassname: impl ::windows::IntoParam<'a, super::SystemServices::PSTR>,
| ----------------------------------------------------- required by this bound in `FindWindowA`
The underlying issue is still the same as before (see below): The IntoParam
trait isn't implemented for the combination of types involved. The previous solution (see below) is still valid, although version 0.8.0 also introduced a NULL
constant, so the following will work as well:
unsafe { hwnd = FindWindowA(PSTR::NULL, window_name_2) }
The GitHub repository also introduce a FAQ with an entry on this specific topic (How do I read the signatures of generated functions and methods? What's with IntoParam
?)
The real error message is a fair bit more enlightening:
error[E0277]: the trait bound `*mut _: IntoParam<'_, PSTR>` is not satisfied
--> src\main.rs:11:21
|
11 | unsafe { hwnd = FindWindowA(std::ptr::null_mut(), window_name_2) }
| ^^^^^^^^^^^ the trait `IntoParam<'_, PSTR>` is not implemented for `*mut _`
|
::: C:\...\target\debug\build\findwindow_test-805b35ca49628608\out/windows.rs:117:27
|
117 | pub unsafe fn FindWindowA<
| ----------- required by a bound in this
118 | 'a,
119 | T0__: ::windows::IntoParam<'a, super::SystemServices::PSTR>,
| ----------------------------------------------------- required by this bound in `FindWindowA`
It's telling you which parameter doesn't meet the requirements, i.e. T0__
, the first one. It's failing to implement the IntoParam trait to convert *mut _
into a PSTR
. The purpose of the IntoParam
trait is to allow convenient conversions between Rust types (like &str
) and ABI types (like PSTR
).
To solve this, you can construct a default PSTR
instead, i.e.
unsafe { hwnd = FindWindowA(PSTR::default(), window_name_2) }
PSTR
(currently) lives in Windows::Win32::SystemServices
.