Skip to content

Commit f588ebc

Browse files
authored
Merge pull request #23 from segevfiner/derive_builder_capi
Add a C API
2 parents 2252abc + fbd0ddc commit f588ebc

File tree

7 files changed

+126
-1
lines changed

7 files changed

+126
-1
lines changed

.vscode/settings.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"rust-analyzer.cargo.features": [
3-
"bin"
3+
"bin",
4+
"capi"
45
]
56
}

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## Unreleased
8+
### Added
9+
- 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.
10+
11+
[cargo-c]: https://crates.io/crates/cargo-c
12+
813
### Changed
914
- **BREAKING** Switched to `derive_builder` for the builder (The builder is now created using `default()`).
1015
- **BREAKING** Renamed `AwakeHandle` to `KeepAwake`.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ exclude = ["/tools/"]
1313

1414
[features]
1515
bin = ["dep:clap", "dep:clap_complete", "dep:ctrlc", "dep:shadow-rs", "dep:sysinfo", "dep:winresource"]
16+
capi = []
1617

1718
[profile.release]
1819
strip = true

README.md

+20
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55

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

8+
Also available as a [Rust crate], and as a [C library](#c-library-experimental) (experimental).
9+
810
[`caffeinate`]: https://ss64.com/osx/caffeinate.html
911
[`systemd-inhibit`]: https://www.freedesktop.org/software/systemd/man/systemd-inhibit.html
1012
[`gnome-session-inhibit`]: https://manpages.ubuntu.com/manpages/jammy/man1/gnome-session-inhibit.1.html
1113
[PowerToys Awake]: https://learn.microsoft.com/en-us/windows/powertoys/awake
1214
[Rust]: https://www.rust-lang.org/
15+
[Rust crate]: https://docs.rs/keepawake
1316

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

52+
## C library (experimental)
53+
Built using [cargo-c].
54+
55+
```sh
56+
# build the library, create the .h header, create the .pc file
57+
$ cargo cbuild --destdir=${D} --prefix=/usr --libdir=/usr/lib64
58+
```
59+
60+
```sh
61+
# build the library, create the .h header, create the .pc file and install all of it
62+
$ cargo cinstall --destdir=${D} --prefix=/usr --libdir=/usr/lib64
63+
```
64+
65+
See the generated header file for details on the API. See [cargo-c] for futher details on cargo-c usage.
66+
67+
[cargo-c]: https://crates.io/crates/cargo-c
68+
4969
## Notes
5070
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).
5171

cbindgen.toml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
language = "C"
2+
include_guard = "KEEPAWAKE_H"
3+
cpp_compat = true
4+
5+
after_includes = """
6+
7+
typedef struct KeepAwakeBuilder KeepAwakeBuilder;"""
8+
9+
[export.rename]
10+
Builder = "KeepAwakeBuilder"

src/capi.rs

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#![allow(clippy::missing_safety_doc)]
2+
3+
use std::{
4+
ffi::{c_char, CStr},
5+
ptr,
6+
};
7+
8+
use crate::{Builder, KeepAwake};
9+
10+
/// Create a new [`KeepAwakeBuilder`].
11+
#[no_mangle]
12+
pub extern "C" fn keepawake_new() -> *mut Builder {
13+
Box::into_raw(Box::default())
14+
}
15+
16+
/// Prevent the display from turning off.
17+
#[no_mangle]
18+
pub unsafe extern "C" fn keepawake_display(builder: *mut Builder, value: bool) {
19+
assert!(!builder.is_null());
20+
(*builder).display(value);
21+
}
22+
23+
/// Prevent the system from sleeping due to idleness.
24+
#[no_mangle]
25+
pub unsafe extern "C" fn keepawake_idle(builder: *mut Builder, value: bool) {
26+
assert!(!builder.is_null());
27+
(*builder).idle(value);
28+
}
29+
30+
/// Prevent the system from sleeping. Only works under certain, OS dependant, conditions.
31+
#[no_mangle]
32+
pub unsafe extern "C" fn keepawake_sleep(builder: *mut Builder, value: bool) {
33+
assert!(!builder.is_null());
34+
(*builder).sleep(value);
35+
}
36+
37+
/// Reason the consumer is keeping the system awake. Defaults to `"User requested"`. (Used on Linux & macOS)
38+
#[no_mangle]
39+
pub unsafe extern "C" fn keepawake_reason(builder: *mut Builder, value: *const c_char) {
40+
assert!(!builder.is_null());
41+
(*builder).reason(CStr::from_ptr(value).to_string_lossy());
42+
}
43+
44+
/// Name of the program keeping the system awake. Defaults to `"keepawake-rs"`. (Used on Linux)
45+
#[no_mangle]
46+
pub unsafe extern "C" fn keepawake_app_name(builder: *mut Builder, value: *const c_char) {
47+
assert!(!builder.is_null());
48+
(*builder).app_name(CStr::from_ptr(value).to_string_lossy());
49+
}
50+
51+
/// Reverse domain name of the program keeping the system awake. Defaults to `"io.github.segevfiner.keepawake-rs"`. (Used on Linux)
52+
#[no_mangle]
53+
pub unsafe extern "C" fn keepawake_app_reverse_domain(builder: *mut Builder, value: *const c_char) {
54+
assert!(!builder.is_null());
55+
(*builder).app_reverse_domain(CStr::from_ptr(value).to_string_lossy());
56+
}
57+
58+
/// Create the [`KeepAwake`]. Optionally destroying the builder.
59+
#[no_mangle]
60+
pub unsafe extern "C" fn keepawake_create(
61+
builder: *mut Builder,
62+
free_builder: bool,
63+
) -> *mut KeepAwake {
64+
assert!(!builder.is_null());
65+
let result = (*builder).create();
66+
if free_builder {
67+
drop(Box::from_raw(builder));
68+
}
69+
result.map_or(ptr::null_mut(), |v| Box::into_raw(Box::new(v)))
70+
}
71+
72+
/// Destroy the [`KeepAwakeBuilder`].
73+
#[no_mangle]
74+
pub unsafe extern "C" fn keepawake_builder_destroy(builder: *mut Builder) {
75+
assert!(!builder.is_null());
76+
drop(Box::from_raw(builder));
77+
}
78+
79+
/// Destroy the [`KeepAwake`].
80+
#[no_mangle]
81+
pub unsafe extern "C" fn keepawake_destroy(awake: *mut KeepAwake) {
82+
assert!(!awake.is_null());
83+
drop(Box::from_raw(awake));
84+
}

src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ use derive_builder::Builder;
3232

3333
mod sys;
3434

35+
#[cfg(feature = "capi")]
36+
pub mod capi;
37+
3538
#[derive(Builder, Debug)]
3639
#[builder(public, name = "Builder", build_fn(private))]
3740
#[allow(dead_code)] // Some fields are unused on some platforms
@@ -66,6 +69,7 @@ struct Options {
6669
}
6770

6871
impl Builder {
72+
/// Create the [`KeepAwake`].
6973
pub fn create(&self) -> Result<KeepAwake> {
7074
Ok(KeepAwake {
7175
_imp: sys::KeepAwake::new(self.build()?)?,

0 commit comments

Comments
 (0)