Skip to content

Commit

Permalink
Merge pull request #38 from madsmtm/better-message
Browse files Browse the repository at this point in the history
Improve message sending
  • Loading branch information
madsmtm authored Oct 3, 2021
2 parents 923b893 + 18b26ba commit bf75ec3
Show file tree
Hide file tree
Showing 17 changed files with 324 additions and 188 deletions.
2 changes: 1 addition & 1 deletion objc2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ let cls = class!(NSObject);
unsafe {
let obj: *mut Object = msg_send![cls, new];
let hash: usize = msg_send![obj, hash];
let is_kind: BOOL = msg_send![obj, isKindOfClass:cls];
let is_kind: BOOL = msg_send![obj, isKindOfClass: cls];
// Even void methods must have their return type annotated
let _: () = msg_send![obj, release];
}
Expand Down
2 changes: 1 addition & 1 deletion objc2/src/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ mod tests {
// Registering the custom class is in test_utils
let obj = test_utils::custom_object();
unsafe {
let _: () = msg_send![obj, setFoo:13u32];
let _: () = msg_send![obj, setFoo: 13u32];
let result: u32 = msg_send![obj, foo];
assert!(result == 13);
}
Expand Down
10 changes: 6 additions & 4 deletions objc2/src/exception.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use core::ptr::NonNull;

use crate::rc::Id;
use crate::rc::{Id, Shared};
use crate::runtime::Object;
use objc2_exception::{r#try, Exception};
use objc2_exception::r#try;

// Comment copied from `objc2_exception`

Expand All @@ -21,6 +21,8 @@ use objc2_exception::{r#try, Exception};
/// undefined behaviour until `C-unwind` is stabilized, see [RFC-2945].
///
/// [RFC-2945]: https://rust-lang.github.io/rfcs/2945-c-unwind-abi.html
pub unsafe fn catch_exception<R>(closure: impl FnOnce() -> R) -> Result<R, Id<Exception>> {
r#try(closure).map_err(|e| Id::new(NonNull::new(e).unwrap()))
pub unsafe fn catch_exception<R>(
closure: impl FnOnce() -> R,
) -> Result<R, Option<Id<Object, Shared>>> {
r#try(closure).map_err(|e| NonNull::new(e).map(|e| Id::new(e.cast())))
}
6 changes: 2 additions & 4 deletions objc2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Objective-C objects can be messaged using the [`msg_send!`](macro.msg_send!.html
let cls = class!(NSObject);
let obj: *mut Object = msg_send![cls, new];
let hash: usize = msg_send![obj, hash];
let is_kind: BOOL = msg_send![obj, isKindOfClass:cls];
let is_kind: BOOL = msg_send![obj, isKindOfClass: cls];
// Even void methods must have their return type annotated
let _: () = msg_send![obj, release];
# }
Expand Down Expand Up @@ -81,12 +81,10 @@ extern "C" {}

pub use objc2_encode::{Encode, EncodeArguments, Encoding, RefEncode};

pub use crate::message::{Message, MessageArguments, MessageError};
pub use crate::message::{Message, MessageArguments, MessageError, MessageReceiver};

pub use crate::cache::CachedClass as __CachedClass;
pub use crate::cache::CachedSel as __CachedSel;
pub use crate::message::send_message as __send_message;
pub use crate::message::send_super_message as __send_super_message;

#[macro_use]
mod macros;
Expand Down
16 changes: 9 additions & 7 deletions objc2/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ method's argument's encoding does not match the encoding of the given arguments.
let obj: *mut Object;
# let obj: *mut Object = 0 as *mut Object;
let description: *const Object = msg_send![obj, description];
let _: () = msg_send![obj, setArg1:1 arg2:2];
let _: () = msg_send![obj, setArg1: 1 arg2: 2];
// Or with an optional comma between arguments:
let _: () = msg_send![obj, setArg1: 1, arg2: 2];
# }
```
*/
Expand All @@ -102,16 +104,16 @@ macro_rules! msg_send {
(super($obj:expr, $superclass:expr), $name:ident) => ({
let sel = $crate::sel!($name);
let result;
match $crate::__send_super_message(&*$obj, $superclass, sel, ()) {
match $crate::MessageReceiver::send_super_message(&$obj, $superclass, sel, ()) {
Err(s) => panic!("{}", s),
Ok(r) => result = r,
}
result
});
(super($obj:expr, $superclass:expr), $($name:ident : $arg:expr)+) => ({
(super($obj:expr, $superclass:expr), $($name:ident : $arg:expr $(,)?)+) => ({
let sel = $crate::sel!($($name:)+);
let result;
match $crate::__send_super_message(&*$obj, $superclass, sel, ($($arg,)*)) {
match $crate::MessageReceiver::send_super_message(&$obj, $superclass, sel, ($($arg,)+)) {
Err(s) => panic!("{}", s),
Ok(r) => result = r,
}
Expand All @@ -120,16 +122,16 @@ macro_rules! msg_send {
($obj:expr, $name:ident) => ({
let sel = $crate::sel!($name);
let result;
match $crate::__send_message(&*$obj, sel, ()) {
match $crate::MessageReceiver::send_message(&$obj, sel, ()) {
Err(s) => panic!("{}", s),
Ok(r) => result = r,
}
result
});
($obj:expr, $($name:ident : $arg:expr)+) => ({
($obj:expr, $($name:ident : $arg:expr $(,)?)+) => ({
let sel = $crate::sel!($($name:)+);
let result;
match $crate::__send_message(&*$obj, sel, ($($arg,)*)) {
match $crate::MessageReceiver::send_message(&$obj, sel, ($($arg,)+)) {
Err(s) => panic!("{}", s),
Ok(r) => result = r,
}
Expand Down
23 changes: 13 additions & 10 deletions objc2/src/message/apple/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use objc2_sys::objc_super;

use super::{Encode, Message, MessageArguments, MessageError};
use super::{conditional_try, Encode, MessageArguments, MessageError};
use crate::runtime::{Class, Imp, Object, Sel};

#[cfg(target_arch = "x86")]
Expand All @@ -23,33 +23,36 @@ trait MsgSendFn: Encode {
const MSG_SEND_SUPER: Imp;
}

pub unsafe fn send_unverified<T, A, R>(obj: *const T, sel: Sel, args: A) -> Result<R, MessageError>
#[inline(always)]
pub unsafe fn send_unverified<A, R>(
receiver: *mut Object,
sel: Sel,
args: A,
) -> Result<R, MessageError>
where
T: Message,
A: MessageArguments,
R: Encode,
{
let receiver = obj as *mut T as *mut Object;
let msg_send_fn = R::MSG_SEND;
objc_try!({ A::invoke(msg_send_fn, receiver, sel, args) })
conditional_try(|| A::invoke(msg_send_fn, receiver, sel, args))
}

pub unsafe fn send_super_unverified<T, A, R>(
obj: *const T,
#[inline]
pub unsafe fn send_super_unverified<A, R>(
receiver: *mut Object,
superclass: &Class,
sel: Sel,
args: A,
) -> Result<R, MessageError>
where
T: Message,
A: MessageArguments,
R: Encode,
{
let sup = objc_super {
receiver: obj as *mut T as *mut Object as *mut _,
receiver: receiver as *mut _,
super_class: superclass as *const Class as *const _,
};
let receiver = &sup as *const objc_super as *mut Object;
let msg_send_fn = R::MSG_SEND_SUPER;
objc_try!({ A::invoke(msg_send_fn, receiver, sel, args) })
conditional_try(|| A::invoke(msg_send_fn, receiver, sel, args))
}
22 changes: 11 additions & 11 deletions objc2/src/message/gnustep.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
use core::mem;
use objc2_sys::{objc_msg_lookup, objc_msg_lookup_super, objc_super};

use super::{Encode, Message, MessageArguments, MessageError};
use super::{conditional_try, Encode, MessageArguments, MessageError};
use crate::runtime::{Class, Object, Sel};

pub unsafe fn send_unverified<T, A, R>(obj: *const T, sel: Sel, args: A) -> Result<R, MessageError>
pub unsafe fn send_unverified<A, R>(
receiver: *mut Object,
sel: Sel,
args: A,
) -> Result<R, MessageError>
where
T: Message,
A: MessageArguments,
R: Encode,
{
if obj.is_null() {
if receiver.is_null() {
return mem::zeroed();
}

let receiver = obj as *mut T as *mut Object;
let msg_send_fn = objc_msg_lookup(receiver as *mut _, sel.as_ptr() as *const _);
objc_try!({ A::invoke(msg_send_fn.expect("Null IMP"), receiver, sel, args) })
conditional_try(|| A::invoke(msg_send_fn.expect("Null IMP"), receiver, sel, args))
}

pub unsafe fn send_super_unverified<T, A, R>(
obj: *const T,
pub unsafe fn send_super_unverified<A, R>(
receiver: *mut Object,
superclass: &Class,
sel: Sel,
args: A,
) -> Result<R, MessageError>
where
T: Message,
A: MessageArguments,
R: Encode,
{
let receiver = obj as *mut T as *mut Object;
let sup = objc_super {
receiver: receiver as *mut _,
super_class: superclass as *const Class as *const _,
};
let msg_send_fn = objc_msg_lookup_super(&sup, sel.as_ptr() as *const _);
objc_try!({ A::invoke(msg_send_fn.expect("Null IMP"), receiver, sel, args) })
conditional_try(|| A::invoke(msg_send_fn.expect("Null IMP"), receiver, sel, args))
}
Loading

0 comments on commit bf75ec3

Please sign in to comment.