objc_rs/
macros.rs

1/**
2Gets a reference to a `Class`.
3
4Panics if no class with the given name can be found.
5To check for a class that may not exist, use `Class::get`.
6
7# Example
8``` no_run
9# #[macro_use] extern crate objc;
10# fn main() {
11let cls = class!(NSObject);
12# }
13```
14*/
15#[macro_export]
16macro_rules! class {
17    ($name:ident) => ({
18        #[allow(deprecated)]
19        #[inline(always)]
20        fn get_class(name: &str) -> Option<&'static $crate::runtime::Class> {
21            unsafe {
22                static CLASS: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::AtomicUsize::new(0);
23                // `Relaxed` should be fine since `objc_getClass` is thread-safe.
24                let ptr = CLASS.load(::std::sync::atomic::Ordering::Relaxed) as *const $crate::runtime::Class;
25                if ptr.is_null() {
26                    let cls = $crate::runtime::objc_getClass(name.as_ptr() as *const _);
27                    CLASS.store(cls as usize, ::std::sync::atomic::Ordering::Relaxed);
28                    if cls.is_null() { None } else { Some(&*cls) }
29                } else {
30                    Some(&*ptr)
31                }
32            }
33        }
34        match get_class(concat!(stringify!($name), '\0')) {
35            Some(cls) => cls,
36            None => panic!("Class with name {} could not be found", stringify!($name)),
37        }
38    })
39}
40
41#[doc(hidden)]
42#[macro_export]
43macro_rules! sel_impl {
44    // Declare a function to hide unsafety, otherwise we can trigger the
45    // unused_unsafe lint; see rust-lang/rust#8472
46    ($name:expr) => ({
47        #[allow(deprecated)]
48        #[inline(always)]
49        fn register_sel(name: &str) -> $crate::runtime::Sel {
50            unsafe {
51                static SEL: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::AtomicUsize::new(0);
52                let ptr = SEL.load(::std::sync::atomic::Ordering::Relaxed) as *const ::std::os::raw::c_void;
53                // It should be fine to use `Relaxed` ordering here because `sel_registerName` is
54                // thread-safe.
55                if ptr.is_null() {
56                    let sel = $crate::runtime::sel_registerName(name.as_ptr() as *const _);
57                    SEL.store(sel.as_ptr() as usize, ::std::sync::atomic::Ordering::Relaxed);
58                    sel
59                } else {
60                    $crate::runtime::Sel::from_ptr(ptr)
61                }
62            }
63        }
64        register_sel($name)
65    })
66}
67
68/**
69Registers a selector, returning a `Sel`.
70
71# Example
72```
73# #[macro_use] extern crate objc;
74# fn main() {
75let sel = sel!(description);
76let sel = sel!(setObject:forKey:);
77# }
78```
79*/
80#[macro_export]
81macro_rules! sel {
82    ($name:ident) => ({sel_impl!(concat!(stringify!($name), '\0'))});
83    ($($name:ident :)+) => ({sel_impl!(concat!($(stringify!($name), ':'),+, '\0'))});
84}
85
86/**
87Sends a message to an object.
88
89The first argument can be any type that dereferences to a type that implements
90`Message`, like a reference, pointer, or an `Id`.
91The syntax is similar to the message syntax in Objective-C.
92Variadic arguments are not currently supported.
93
94# Example
95``` no_run
96# #[macro_use] extern crate objc;
97# use objc::runtime::Object;
98# fn main() {
99# unsafe {
100let obj: *mut Object;
101# let obj: *mut Object = 0 as *mut Object;
102let description: *const Object = msg_send![obj, description];
103let _: () = msg_send![obj, setArg1:1 arg2:2];
104# }
105# }
106```
107*/
108#[macro_export]
109macro_rules! msg_send {
110    (super($obj:expr, $superclass:expr), $name:ident) => ({
111        let sel = sel!($name);
112        let result;
113        match $crate::__send_super_message(&*$obj, $superclass, sel, ()) {
114            Err(s) => panic!("{}", s),
115            Ok(r) => result = r,
116        }
117        result
118    });
119    (super($obj:expr, $superclass:expr), $($name:ident : $arg:expr)+) => ({
120        let sel = sel!($($name:)+);
121        let result;
122        match $crate::__send_super_message(&*$obj, $superclass, sel, ($($arg,)*)) {
123            Err(s) => panic!("{}", s),
124            Ok(r) => result = r,
125        }
126        result
127    });
128    ($obj:expr, $name:ident) => ({
129        let sel = sel!($name);
130        let result;
131        match $crate::__send_message(&*$obj, sel, ()) {
132            Err(s) => panic!("{}", s),
133            Ok(r) => result = r,
134        }
135        result
136    });
137    ($obj:expr, $($name:ident : $arg:expr)+) => ({
138        let sel = sel!($($name:)+);
139        let result;
140        match $crate::__send_message(&*$obj, sel, ($($arg,)*)) {
141            Err(s) => panic!("{}", s),
142            Ok(r) => result = r,
143        }
144        result
145    });
146}