Convert Figma logo to code with AI

retep998 logowinapi-rs

Rust bindings to Windows API

1,831
387
1,831
278

Top Related Projects

Rust for Windows

SDL2 bindings for Rust

2,058

Raw bindings to platform APIs for Rust

1,246

DEPRECATED, use https://github.com/gtk-rs/gtk3-rs repository instead!

Quick Overview

winapi-rs is a Rust library that provides bindings to Windows API functions. It aims to offer a safe and idiomatic Rust interface to the Windows API, allowing Rust developers to interact with Windows-specific functionality more easily and safely.

Pros

  • Provides safe Rust wrappers for Windows API functions
  • Extensive coverage of Windows API, including both common and less-used functions
  • Actively maintained and regularly updated
  • Allows for writing Windows-specific applications in Rust

Cons

  • Limited to Windows platforms, reducing cross-platform compatibility
  • Learning curve for developers not familiar with Windows API
  • Some functions may still require unsafe code blocks
  • Documentation can be sparse for less common API functions

Code Examples

  1. Getting the current process ID:
use winapi::um::processthreadsapi::GetCurrentProcessId;

fn main() {
    let pid = unsafe { GetCurrentProcessId() };
    println!("Current process ID: {}", pid);
}
  1. Creating a message box:
use winapi::um::winuser::{MessageBoxW, MB_OK};
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;

fn main() {
    let title: Vec<u16> = OsStr::new("Hello").encode_wide().chain(Some(0)).collect();
    let text: Vec<u16> = OsStr::new("Hello, World!").encode_wide().chain(Some(0)).collect();
    
    unsafe {
        MessageBoxW(std::ptr::null_mut(), text.as_ptr(), title.as_ptr(), MB_OK);
    }
}
  1. Getting system metrics:
use winapi::um::winuser::{GetSystemMetrics, SM_CXSCREEN, SM_CYSCREEN};

fn main() {
    let screen_width = unsafe { GetSystemMetrics(SM_CXSCREEN) };
    let screen_height = unsafe { GetSystemMetrics(SM_CYSCREEN) };
    println!("Screen resolution: {}x{}", screen_width, screen_height);
}

Getting Started

To use winapi-rs in your Rust project, add the following to your Cargo.toml file:

[dependencies]
winapi = { version = "0.3", features = ["processthreadsapi", "winuser"] }

Then, in your Rust code, you can import and use the Windows API functions:

use winapi::um::winuser::MessageBoxW;

fn main() {
    // Your code using Windows API functions
}

Remember to use unsafe blocks when calling Windows API functions, as they are inherently unsafe in Rust's safety model.

Competitor Comparisons

Rust for Windows

Pros of windows-rs

  • Official Microsoft support and maintenance
  • More comprehensive coverage of Windows APIs
  • Better integration with modern Rust practices and idioms

Cons of windows-rs

  • Larger binary size due to more extensive API coverage
  • Steeper learning curve for newcomers to Windows API development

Code Comparison

winapi-rs:

use winapi::um::winuser::MessageBoxW;
use std::ptr::null_mut;

unsafe {
    MessageBoxW(null_mut(), wide_string!("Hello"), wide_string!("Title"), 0);
}

windows-rs:

use windows::Win32::UI::WindowsAndMessaging::MessageBoxW;

unsafe {
    MessageBoxW(None, "Hello", "Title", Default::default());
}

The windows-rs example demonstrates a more idiomatic Rust approach, with better type safety and easier-to-read code. It doesn't require manual null pointer handling or explicit string conversion macros.

Both libraries serve the purpose of providing Rust bindings for Windows APIs, but windows-rs offers a more modern and officially supported solution. While winapi-rs has been a popular choice for many years, windows-rs is gaining traction due to its official backing and improved Rust integration. Developers should consider their specific needs and project requirements when choosing between the two libraries.

SDL2 bindings for Rust

Pros of rust-sdl2

  • Cross-platform support for multiple operating systems
  • Provides high-level abstractions for multimedia and game development
  • Active community and frequent updates

Cons of rust-sdl2

  • Larger dependency footprint
  • May have performance overhead compared to direct API calls
  • Requires linking to external SDL2 libraries

Code Comparison

winapi-rs:

use winapi::um::winuser::{MessageBoxW, MB_OK};
use std::ptr::null_mut;

unsafe {
    MessageBoxW(null_mut(), wide_string!("Hello"), wide_string!("Title"), MB_OK);
}

rust-sdl2:

use sdl2::messagebox::show_simple_message_box;

sdl2::init().unwrap();
show_simple_message_box(sdl2::messagebox::MessageBoxFlag::INFORMATION,
                        "Title", "Hello", None).unwrap();

The winapi-rs example directly calls Windows API functions, while rust-sdl2 provides a cross-platform abstraction layer. winapi-rs offers more fine-grained control but is Windows-specific, whereas rust-sdl2 simplifies development across multiple platforms at the cost of some performance and flexibility.

2,058

Raw bindings to platform APIs for Rust

Pros of libc

  • More comprehensive, covering multiple platforms (Unix-like systems, Windows, etc.)
  • Part of the official Rust project, ensuring long-term maintenance and support
  • Provides a unified interface for system calls across different operating systems

Cons of libc

  • Less specialized for Windows-specific functionality
  • May have a steeper learning curve for developers focusing solely on Windows development
  • Potentially larger overhead due to cross-platform support

Code Comparison

winapi-rs:

use winapi::um::winuser::{MessageBoxW, MB_OK};
use winapi::um::winnt::LPCWSTR;

unsafe {
    MessageBoxW(std::ptr::null_mut(), "Hello" as LPCWSTR, "Title" as LPCWSTR, MB_OK);
}

libc:

use libc::{c_int, c_char};
use std::ffi::CString;

unsafe {
    libc::printf(CString::new("Hello, %s!\n").unwrap().as_ptr(), CString::new("World").unwrap().as_ptr());
}

The winapi-rs example demonstrates Windows-specific API usage, while the libc example shows a more general, cross-platform approach to system calls. winapi-rs provides a more idiomatic Rust interface for Windows programming, whereas libc offers a broader range of system functions across different platforms.

1,246

DEPRECATED, use https://github.com/gtk-rs/gtk3-rs repository instead!

Pros of gtk

  • Cross-platform support for Linux, macOS, and Windows
  • Extensive documentation and examples for Rust bindings
  • Active community and frequent updates

Cons of gtk

  • Larger dependency footprint
  • Steeper learning curve for those unfamiliar with GTK

Code Comparison

gtk:

use gtk::prelude::*;
use gtk::{Application, ApplicationWindow};

fn main() {
    let app = Application::builder().build();
    app.connect_activate(build_ui);
    app.run();
}

winapi-rs:

use winapi::um::winuser::{CreateWindowExW, ShowWindow};

fn main() {
    unsafe {
        let hwnd = CreateWindowExW(/* params */);
        ShowWindow(hwnd, /* params */);
    }
}

The gtk example demonstrates a higher-level abstraction for creating a window, while winapi-rs requires more low-level interaction with the Windows API. gtk provides a more idiomatic Rust experience, but winapi-rs offers finer control over Windows-specific functionality.

gtk is better suited for cross-platform GUI development, while winapi-rs is specifically tailored for Windows systems. The choice between them depends on the project requirements, target platforms, and developer preferences.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

winapi-rs

Build status Build status Build Status Gitter Crates.io Lines of Code 100% unsafe Open issues License

Documentation

Official communication channel: #windows-dev on the Rust Community Discord

This crate provides raw FFI bindings to all of Windows API. They are gathered by hand using the Windows 10 SDK from Microsoft. I aim to replace all existing Windows FFI in other crates with this crate through the "Embrace, extend, and extinguish" technique.

If this crate is missing something you need, feel free to create an issue, open a pull request, or contact me via other means.

This crate depends on Rust 1.6 or newer on Windows. On other platforms this crate is a no-op and should compile with Rust 1.2 or newer.

Frequently asked questions

How do I create an instance of a union?

Use std::mem::zeroed() to create an instance of the union, and then assign the value you want using one of the variant methods.

Why am I getting errors about unresolved imports?

Each module is gated on a feature flag, so you must enable the appropriate feature to gain access to those items. For example, if you want to use something from winapi::um::winuser you must enable the winuser feature.

How do I know which module an item is defined in?

You can use the search functionality in the documentation to find where items are defined.

Why is there no documentation on how to use anything?

This crate is nothing more than raw bindings to Windows API. If you wish to know how to use the various functionality in Windows API, you can look up the various items on MSDN which is full of detailed documentation.

Can I use this library in no_std projects?

Yes, absolutely! By default the std feature of winapi is disabled, allowing you to write Windows applications using nothing but core and winapi.

Why is winapi's HANDLE incompatible with std's HANDLE?

Because winapi does not depend on std by default, it has to define c_void itself instead of using std::os::raw::c_void. However, if you enable the std feature of winapi then it will re-export c_void from std and cause winapi's HANDLE to be the same type as std's HANDLE.

Should I still use those -sys crates such as kernel32-sys?

No. Those crates are a legacy of how winapi 0.2 was organized. Starting with winapi 0.3 all definitions are directly in winapi itself, and so there is no longer any need to use those -sys crates.

Example

Cargo.toml:

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["winuser"] }

main.rs:

#[cfg(windows)] extern crate winapi;
use std::io::Error;

#[cfg(windows)]
fn print_message(msg: &str) -> Result<i32, Error> {
    use std::ffi::OsStr;
    use std::iter::once;
    use std::os::windows::ffi::OsStrExt;
    use std::ptr::null_mut;
    use winapi::um::winuser::{MB_OK, MessageBoxW};
    let wide: Vec<u16> = OsStr::new(msg).encode_wide().chain(once(0)).collect();
    let ret = unsafe {
        MessageBoxW(null_mut(), wide.as_ptr(), wide.as_ptr(), MB_OK)
    };
    if ret == 0 { Err(Error::last_os_error()) }
    else { Ok(ret) }
}
#[cfg(not(windows))]
fn print_message(msg: &str) -> Result<(), Error> {
    println!("{}", msg);
    Ok(())
}
fn main() {
    print_message("Hello, world!").unwrap();
}

Financial Support

Do you use winapi in your projects? If so, you may be interested in financially supporting me on Patreon. Companies in particular are especially encouraged to donate (I'm looking at you Microsoft).