Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve message sending #38

Merged
merged 9 commits into from
Oct 3, 2021
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