Crates.io | blocksr |
lib.rs | blocksr |
version | 1.0.0 |
source | src |
created_at | 2024-10-15 04:43:55.826763 |
updated_at | 2024-10-15 04:43:55.826763 |
description | Drew's Rust library for (clang/objc) blocks |
homepage | https://sealedabstract.com/code/blocksr |
repository | https://github.com/drewcrawford/blocksr |
max_upload_size | |
id | 1408978 |
size | 150,955 |
This is my Rust crate for using blocks, the Apple C extension often used with ObjC. This crate may be compared with the more popular block crate.
This crate is part of the objr expanded universe universe which provide low-level, zero-cost abstractions for Apple platform features that mimic code from first-party compilers. Distinctive features of this library include:
FnOnce
, FnMut
(implemented), or Fn
(planned), unlocking the full Rust typesystemcontinuation
feature (off by default) bridges block-based completion handlers to Rust async fn
s.
use blocksr::once_escaping;
once_escaping!(MyBlock (arg: u8) -> u8);
let f = unsafe{ MyBlock::new(|_arg| {
3
})};
//pass f somewhere...
In ObjC, blocks have a lifetime that extends beyond any single invocation, and are dropped after the block is dropped.
In Rust, types cannot generally be moved into an Fn
or FnMut
closure, as the syntax moves them into an invocation,
of which there are an arbitrary number.
Because this mismatch in usecase is quite common, the many
macros have an additional component, the environment.
The environment is moved into our block as a whole upon creation, rather than any single invocation, and a reference is passed
as the first argument to the closure.
In an FnMut
context we can mutate the environment:
use blocksr::many_escaping_nonreentrant;
many_escaping_nonreentrant!(MyBlock (environment: &mut u8) -> ());
let f = unsafe{ MyBlock::new(23, |environment| {
*environment += 1
})};
//pass f somewhere...
The environment is dropped when the block is dropped, with assistance from the ObjC runtime. This will occur sometime after the last execution.