Skip to content

Option to Generate Function Pointer Types for windows-sys Win32 APIs #3781

@uint-nate

Description

@uint-nate

Suggestion

As shown in the delay load sample here, windows-rs provides the ability to dynamically load Windows Win32 APIs at runtime with GetProcAddress.

However if a developer wants to dynamically load an API, the developer needs to copy-paste the function signature even though windows-sys already knows the signature that needs to be used here (since it used that signature to generate the bindings in the first place).

From the delay_load example, Kenny had to re-declare ShellMessageBoxW's signature even though windows-rs "already knows" that signature since it generates the function signature already for linking against:

type ShellMessageBoxW = unsafe extern "C" fn(
    happinst: usize,
    hwnd: usize,
    lpctext: PCWSTR,
    lpctitle: PCWSTR,
    fustyle: u32,
    ...
) -> i32;
// vs this generated from windows_sys
windows_link::link!("shlwapi.dll" "C" fn ShellMessageBoxW(happinst : super::super::Foundation:: HINSTANCE, hwnd : super::super::Foundation:: HWND, lpctext : windows_sys::core::PCWSTR, lpctitle : windows_sys::core::PCWSTR, fustyle : super::WindowsAndMessaging:: MESSAGEBOX_STYLE, ...) -> i32);

I propose that windows-sys (or the bindings generation code only) provide an option to generate function pointer types along side the sys style windows_link bindings for the dynamic loading scenarios. This would allow Rust app developers to load Windows functionality at runtime without having to copy-paste the windows-sys generated bindings and hand-edit them from raw-dylib bindings into the function pointer types they want to use.

The binding generation code could look something like this in my head:

windows_link::link!("shlwapi.dll" "C" fn ShellMessageBoxW(happinst : super::super::Foundation:: HINSTANCE, hwnd : super::super::Foundation:: HWND, lpctext : windows_sys::core::PCWSTR, lpctitle : windows_sys::core::PCWSTR, fustyle : super::WindowsAndMessaging:: MESSAGEBOX_STYLE, ...) -> i32);
type ShellMessageBoxWFn = unsafe extern "C" fn(happinst : super::super::Foundation:: HINSTANCE, hwnd : super::super::Foundation:: HWND, lpctext : windows_sys::core::PCWSTR, lpctitle : windows_sys::core::PCWSTR, fustyle : super::WindowsAndMessaging:: MESSAGEBOX_STYLE, ...) -> i32);

The real world use case is that many app developers rely on dynamic loading of Windows APIs in order to allow for a single binary to run across both new and old versions of Windows that may or may not have a DLL export for a given API. Without this dynamic loading behavior using GetProcAddress and function pointers, on older versions of Windows that don't have a DLL export for a function, you'd get an error similar to this one:

Image

I have started and stopped a few times trying to implement this feature myself. Maybe I'll still find time to do that soon, but in the mean time I thought I'd open this feature request for tracking in case someone else can easily implement this before I get the chance to, and if I'm barking up the wrong tree here for some reason it would be useful to know that early before I go too far down the rabbit hole :).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions