-2

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.

IInspectable
  • 46,945
  • 8
  • 85
  • 181
  • Welcome to Stack Overflow! It's hard to answer your question because it doesn't include a [MRE]. We can't tell what crates (and their versions), types, traits, fields, etc. are present in the code. It would make it easier for us to help you if you try to reproduce your error on the [Rust Playground](https://play.rust-lang.org) if possible, otherwise in a brand new Cargo project, then [edit] your question to include the additional info. There are [Rust-specific MRE tips](//stackoverflow.com/tags/rust/info) you can use to reduce your original code for posting here. Thanks! – Shepmaster Apr 07 '21 at 13:02
  • Please [edit] your question and paste the exact and entire error that you're getting — that will help us to understand what the problem is so we can help best. Sometimes trying to interpret an error message is tricky and it's actually a different part of the error message that's important. Please use the message from running the compiler directly, not the message produced by an IDE, which might be trying to interpret the error for you. – Shepmaster Apr 07 '21 at 13:02
  • https://doc.rust-lang.org/book/ch10-02-traits.html#trait-bound-syntax – Shepmaster Apr 07 '21 at 13:04
  • what do you use as crate ? where does come from this `bindings` thing ? – Stargateur Apr 08 '21 at 11:50
  • @sta How do you propose to encode the `L` now? You do realize that at some point, there were "long pointers", that were different from, say, "near pointers". Sure, if you ignore the problem you need to solve, you can always come up with a solution that looks more elegant than someone else's, and ridicule them. – IInspectable Apr 08 '21 at 12:46
  • @IInspectable "Historically, P stands for "pointer" and LP stands for "long pointer". Long pointers (also called far pointers) are a holdover from 16-bit Windows, when they were needed to address memory ranges outside the current segment. The LP prefix was preserved to make it easier to port 16-bit code to 32-bit Windows. Today there is no distinction — a pointer is a pointer." https://learn.microsoft.com/en-us/windows/win32/learnwin32/windows-coding-conventions#pointer-types please stop we are in 2021 not in 1980 – Stargateur Apr 08 '21 at 12:48
  • @sta That's called ABI stability. Clearly, a concept you have yet to grasp. It'll take the better part of a decade until you stand a chance of actually appreciating it. You can come back here once you've matured, and revisit your statements. Since all of that is off-topic, you may as well consider leaving it at that. You haven't added anything useful to the question, or the answer. – IInspectable Apr 08 '21 at 12:54
  • @IInspectable I will answer with one picture https://imgur.com/y6clspP, stability is good, legacy problem are not. – Stargateur Apr 08 '21 at 12:57
  • @sta You cannot both have stability and not have stability at the same time. This whole debate revolves around a single, unfounded claim: Windows' API declaration were to hide meaningful information. That's ludicrous. You will not find a **single** Windows developer, that wouldn't **instantly** know what a `LPCSTR` maps to in C. A non-Windows developer might be confused, but then, they are not the target audience. Clearly, you are not a Windows developer, so voicing your opinion isn't entirely helpful in convincing Windows developers why their API declarations are wrong. – IInspectable Apr 08 '21 at 13:03
  • @sta Windows is also the only OS with a sustainable compatibility story. There is no other OS that is close. Keeping a stable API across decades is exactly the reason that enables this. And type aliases like `LPCSTR` are part of that. – IInspectable Apr 08 '21 at 13:14

1 Answers1

2

Update for version 0.8.0

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.

IInspectable
  • 46,945
  • 8
  • 85
  • 181