Skip to content

Commit 9480a6f

Browse files
authored
Merge pull request #18 from madsmtm/objc_block
Move `block` crate into this repo
2 parents 1f82d5b + 50704af commit 9480a6f

File tree

21 files changed

+790
-22
lines changed

21 files changed

+790
-22
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
5252
- name: Install Packages
5353
if: contains(matrix.platform.os, 'ubuntu')
54-
run: sudo apt-get install gobjc clang make
54+
run: sudo apt-get install gobjc clang make libblocksruntime-dev
5555

5656
- name: Install different Rust toolchain
5757
# A default toolchain is already installed
@@ -120,12 +120,11 @@ jobs:
120120
uses: actions-rs/cargo@v1
121121
with:
122122
command: test
123-
# TODO: `objc_foundation/block` feature doesn't work
124123
args: --verbose --no-fail-fast --no-default-features
125124

126-
- name: Test w. exception and verify_message features
125+
- name: Test with features
127126
uses: actions-rs/cargo@v1
128127
with:
129128
command: test
130-
# TODO: `objc_foundation/block` feature doesn't work
131-
args: --verbose --no-fail-fast --no-default-features --features exception,verify_message
129+
# Not using --all-features because some features are nightly-only
130+
args: --verbose --no-fail-fast --features block,exception,verify_message

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
[workspace]
22
members = [
33
"objc",
4+
"objc_block",
45
"objc_encode",
56
"objc_exception",
67
"objc_foundation",
78
"objc_foundation_derive",
89
"objc_id",
10+
"objc_test_utils",
911
]
1012
exclude = ["objc/tests-ios"]

objc/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ The bindings can be used on Linux or *BSD utilizing the
5959
*/
6060

6161
#![no_std]
62-
#![cfg_attr(feature = "unstable_autoreleasesafe", feature(negative_impls, auto_traits))]
63-
62+
#![cfg_attr(
63+
feature = "unstable_autoreleasesafe",
64+
feature(negative_impls, auto_traits)
65+
)]
6466
#![warn(missing_docs)]
6567
#![allow(clippy::missing_safety_doc)]
6668
// Update in Cargo.toml as well.

objc/src/rc/autorelease.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use core::ffi::c_void;
22
#[cfg(all(debug_assertions, not(feature = "unstable_autoreleasesafe")))]
3-
use std::{cell::RefCell, vec::Vec, thread_local};
3+
use std::{cell::RefCell, thread_local, vec::Vec};
44

55
use crate::runtime::{objc_autoreleasePoolPop, objc_autoreleasePoolPush};
66

@@ -81,6 +81,7 @@ impl AutoreleasePool {
8181
all(debug_assertions, not(feature = "unstable_autoreleasesafe")),
8282
inline
8383
)]
84+
#[allow(clippy::needless_lifetimes)]
8485
pub unsafe fn ptr_as_ref<'p, T>(&'p self, ptr: *const T) -> &'p T {
8586
#[cfg(all(debug_assertions, not(feature = "unstable_autoreleasesafe")))]
8687
POOLS.with(|c| {
@@ -110,6 +111,8 @@ impl AutoreleasePool {
110111
all(debug_assertions, not(feature = "unstable_autoreleasesafe")),
111112
inline
112113
)]
114+
#[allow(clippy::needless_lifetimes)]
115+
#[allow(clippy::mut_from_ref)]
113116
pub unsafe fn ptr_as_mut<'p, T>(&'p self, ptr: *mut T) -> &'p mut T {
114117
#[cfg(all(debug_assertions, not(feature = "unstable_autoreleasesafe")))]
115118
POOLS.with(|c| {
@@ -265,7 +268,10 @@ impl !AutoreleaseSafe for AutoreleasePool {}
265268
/// inner pool:
266269
///
267270
#[cfg_attr(feature = "unstable_autoreleasesafe", doc = "```rust,compile_fail")]
268-
#[cfg_attr(not(feature = "unstable_autoreleasesafe"), doc = "```rust,should_panic")]
271+
#[cfg_attr(
272+
not(feature = "unstable_autoreleasesafe"),
273+
doc = "```rust,should_panic"
274+
)]
269275
/// # use objc::{class, msg_send};
270276
/// # use objc::rc::{autoreleasepool, AutoreleasePool};
271277
/// # use objc::runtime::Object;

objc_block/Cargo.toml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[package]
2+
name = "block"
3+
version = "0.1.6"
4+
authors = ["Steven Sheldon", "Mads Marquart <[email protected]>"]
5+
edition = "2018"
6+
7+
description = "Interface for Apple's C language extension of blocks."
8+
keywords = ["objective-c", "macos", "ios", "blocks"]
9+
categories = [
10+
"api-bindings",
11+
"development-tools::ffi",
12+
"os::macos-apis",
13+
]
14+
readme = "README.md"
15+
repository = "https://github.com/madsmtm/objc"
16+
documentation = "https://docs.rs/block/"
17+
license = "MIT"
18+
19+
exclude = [
20+
"tests-ios/**",
21+
]
22+
23+
[dependencies]
24+
objc-encode = { path = "../objc_encode", version = "1.1.0" }
25+
26+
[dev-dependencies]
27+
objc_test_utils = { path = "../objc_test_utils", version = "0.0" }

objc_block/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# `block`
2+
3+
[![Latest version](https://badgen.net/crates/v/block)](https://crates.io/crates/block)
4+
[![License](https://badgen.net/badge/license/MIT/blue)](../LICENSE.txt)
5+
[![Documentation](https://docs.rs/block/badge.svg)](https://docs.rs/block/)
6+
[![CI Status](https://github.com/madsmtm/objc/workflows/CI/badge.svg)](https://github.com/madsmtm/objc/actions)
7+
8+
Rust interface for Apple's C language extension of blocks.
9+
10+
For more information on the specifics of the block implementation, see
11+
Clang's documentation: http://clang.llvm.org/docs/Block-ABI-Apple.html
12+
13+
## Invoking blocks
14+
15+
The `Block` struct is used for invoking blocks from Objective-C. For example,
16+
consider this Objective-C function:
17+
18+
``` objc
19+
int32_t sum(int32_t (^block)(int32_t, int32_t)) {
20+
return block(5, 8);
21+
}
22+
```
23+
24+
We could write it in Rust as the following:
25+
26+
``` rust
27+
unsafe fn sum(block: &Block<(i32, i32), i32>) -> i32 {
28+
block.call((5, 8))
29+
}
30+
```
31+
32+
Note the extra parentheses in the `call` method, since the arguments must be
33+
passed as a tuple.
34+
35+
## Creating blocks
36+
37+
Creating a block to pass to Objective-C can be done with the `ConcreteBlock`
38+
struct. For example, to create a block that adds two `i32`s, we could write:
39+
40+
``` rust
41+
let block = ConcreteBlock::new(|a: i32, b: i32| a + b);
42+
let block = block.copy();
43+
assert!(unsafe { block.call((5, 8)) } == 13);
44+
```
45+
46+
It is important to copy your block to the heap (with the `copy` method) before
47+
passing it to Objective-C; this is because our `ConcreteBlock` is only meant
48+
to be copied once, and we can enforce this in Rust, but if Objective-C code
49+
were to copy it twice we could have a double free.

0 commit comments

Comments
 (0)