Skip to content

Commit

Permalink
Merge pull request #23 from segevfiner/derive_builder_capi
Browse files Browse the repository at this point in the history
Add a C API
  • Loading branch information
segevfiner committed Feb 5, 2024
2 parents 2252abc + fbd0ddc commit f588ebc
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"rust-analyzer.cargo.features": [
"bin"
"bin",
"capi"
]
}
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased
### Added
- An experimental C API buildable using [cargo-c]. See the generated header file for details on the API. See [cargo-c] for futher details on cargo-c usage.

[cargo-c]: https://crates.io/crates/cargo-c

### Changed
- **BREAKING** Switched to `derive_builder` for the builder (The builder is now created using `default()`).
- **BREAKING** Renamed `AwakeHandle` to `KeepAwake`.
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ exclude = ["/tools/"]

[features]
bin = ["dep:clap", "dep:clap_complete", "dep:ctrlc", "dep:shadow-rs", "dep:sysinfo", "dep:winresource"]
capi = []

[profile.release]
strip = true
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@

Keep your computer awake. Like [`caffeinate`], [`systemd-inhibit`]/[`gnome-session-inhibit`], or [PowerToys Awake], but cross-platform and written in [Rust].

Also available as a [Rust crate], and as a [C library](#c-library-experimental) (experimental).

[`caffeinate`]: https://ss64.com/osx/caffeinate.html
[`systemd-inhibit`]: https://www.freedesktop.org/software/systemd/man/systemd-inhibit.html
[`gnome-session-inhibit`]: https://manpages.ubuntu.com/manpages/jammy/man1/gnome-session-inhibit.1.html
[PowerToys Awake]: https://learn.microsoft.com/en-us/windows/powertoys/awake
[Rust]: https://www.rust-lang.org/
[Rust crate]: https://docs.rs/keepawake

## Usage
```
Expand Down Expand Up @@ -46,6 +49,23 @@ Download from https://github.com/segevfiner/keepawake-rs/releases/latest.
Use: `keepawake --completions <SHELL>` to generate a completion script, you will have to install it
as appropriate for the specific shell you are using.

## C library (experimental)
Built using [cargo-c].

```sh
# build the library, create the .h header, create the .pc file
$ cargo cbuild --destdir=${D} --prefix=/usr --libdir=/usr/lib64
```

```sh
# build the library, create the .h header, create the .pc file and install all of it
$ cargo cinstall --destdir=${D} --prefix=/usr --libdir=/usr/lib64
```

See the generated header file for details on the API. See [cargo-c] for futher details on cargo-c usage.

[cargo-c]: https://crates.io/crates/cargo-c

## Notes
Preventing the computer from explicitly sleeping, and/or by closing the lid, is often restricted in various ways by the OS, e.g. Only on AC power, not in any PC running Windows with [Modern Standby](https://learn.microsoft.com/en-us/windows-hardware/design/device-experiences/modern-standby). Also note that Modern Standby ignores/terminates power requests on DC (Battery) power, [PowerSetRequest - Remarks](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-powersetrequest#remarks).

Expand Down
10 changes: 10 additions & 0 deletions cbindgen.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
language = "C"
include_guard = "KEEPAWAKE_H"
cpp_compat = true

after_includes = """
typedef struct KeepAwakeBuilder KeepAwakeBuilder;"""

[export.rename]
Builder = "KeepAwakeBuilder"
84 changes: 84 additions & 0 deletions src/capi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#![allow(clippy::missing_safety_doc)]

use std::{
ffi::{c_char, CStr},
ptr,
};

use crate::{Builder, KeepAwake};

/// Create a new [`KeepAwakeBuilder`].
#[no_mangle]
pub extern "C" fn keepawake_new() -> *mut Builder {
Box::into_raw(Box::default())
}

/// Prevent the display from turning off.
#[no_mangle]
pub unsafe extern "C" fn keepawake_display(builder: *mut Builder, value: bool) {
assert!(!builder.is_null());
(*builder).display(value);
}

/// Prevent the system from sleeping due to idleness.
#[no_mangle]
pub unsafe extern "C" fn keepawake_idle(builder: *mut Builder, value: bool) {
assert!(!builder.is_null());
(*builder).idle(value);
}

/// Prevent the system from sleeping. Only works under certain, OS dependant, conditions.
#[no_mangle]
pub unsafe extern "C" fn keepawake_sleep(builder: *mut Builder, value: bool) {
assert!(!builder.is_null());
(*builder).sleep(value);
}

/// Reason the consumer is keeping the system awake. Defaults to `"User requested"`. (Used on Linux & macOS)
#[no_mangle]
pub unsafe extern "C" fn keepawake_reason(builder: *mut Builder, value: *const c_char) {
assert!(!builder.is_null());
(*builder).reason(CStr::from_ptr(value).to_string_lossy());
}

/// Name of the program keeping the system awake. Defaults to `"keepawake-rs"`. (Used on Linux)
#[no_mangle]
pub unsafe extern "C" fn keepawake_app_name(builder: *mut Builder, value: *const c_char) {
assert!(!builder.is_null());
(*builder).app_name(CStr::from_ptr(value).to_string_lossy());
}

/// Reverse domain name of the program keeping the system awake. Defaults to `"io.github.segevfiner.keepawake-rs"`. (Used on Linux)
#[no_mangle]
pub unsafe extern "C" fn keepawake_app_reverse_domain(builder: *mut Builder, value: *const c_char) {
assert!(!builder.is_null());
(*builder).app_reverse_domain(CStr::from_ptr(value).to_string_lossy());
}

/// Create the [`KeepAwake`]. Optionally destroying the builder.
#[no_mangle]
pub unsafe extern "C" fn keepawake_create(
builder: *mut Builder,
free_builder: bool,
) -> *mut KeepAwake {
assert!(!builder.is_null());
let result = (*builder).create();
if free_builder {
drop(Box::from_raw(builder));
}
result.map_or(ptr::null_mut(), |v| Box::into_raw(Box::new(v)))
}

/// Destroy the [`KeepAwakeBuilder`].
#[no_mangle]
pub unsafe extern "C" fn keepawake_builder_destroy(builder: *mut Builder) {
assert!(!builder.is_null());
drop(Box::from_raw(builder));
}

/// Destroy the [`KeepAwake`].
#[no_mangle]
pub unsafe extern "C" fn keepawake_destroy(awake: *mut KeepAwake) {
assert!(!awake.is_null());
drop(Box::from_raw(awake));
}
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ use derive_builder::Builder;

mod sys;

#[cfg(feature = "capi")]
pub mod capi;

#[derive(Builder, Debug)]
#[builder(public, name = "Builder", build_fn(private))]
#[allow(dead_code)] // Some fields are unused on some platforms
Expand Down Expand Up @@ -66,6 +69,7 @@ struct Options {
}

impl Builder {
/// Create the [`KeepAwake`].
pub fn create(&self) -> Result<KeepAwake> {
Ok(KeepAwake {
_imp: sys::KeepAwake::new(self.build()?)?,
Expand Down

0 comments on commit f588ebc

Please sign in to comment.