From 34cc2368082fcb46a2c48afed7a6aa055028aacb Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 16 Jun 2021 11:44:13 +0200 Subject: [PATCH] Make Sel an opaque struct like Ivar, Method, Class, Protocol and Object The discrepancy between usage of `Class`/`Object`/... and `Sel` annoyed me, the others were used behind pointers / references, while `Sel` was consumed directly. This changes the definition of `Sel` to be like the other types (so it has to be used as `&Sel`), and also opens up for the possiblity of non-static selectors (if that ever becomes a thing). This is a breaking change, but fortunately most cases where `Sel` is used in user code (e.g. `add_method`) the error is caught at compile-time, with recommendations on how to fix it. --- README.md | 4 +-- src/cache.rs | 11 +++--- src/declare.rs | 53 +++++++++++++++------------ src/encode.rs | 7 ++-- src/macros.rs | 2 +- src/message/apple/mod.rs | 4 +-- src/message/gnustep.rs | 8 ++--- src/message/mod.rs | 20 +++++------ src/message/verify.rs | 13 +++---- src/runtime.rs | 77 ++++++++++++++-------------------------- src/test_utils.rs | 30 ++++++++-------- 11 files changed, 109 insertions(+), 120 deletions(-) diff --git a/README.md b/README.md index 55fba6484..8892fed2e 100644 --- a/README.md +++ b/README.md @@ -60,12 +60,12 @@ let mut decl = ClassDecl::new("MyNumber", superclass).unwrap(); decl.add_ivar::("_number"); // Add an ObjC method for getting the number -extern fn my_number_get(this: &Object, _cmd: Sel) -> u32 { +extern fn my_number_get(this: &Object, _cmd: &Sel) -> u32 { unsafe { *this.get_ivar("_number") } } unsafe { decl.add_method(sel!(number), - my_number_get as extern fn(&Object, Sel) -> u32); + my_number_get as extern fn(&Object, &Sel) -> u32); } decl.register(); diff --git a/src/cache.rs b/src/cache.rs index 14bf98182..675bcbc37 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -1,4 +1,3 @@ -use std::os::raw::c_void; use std::ptr; use std::sync::atomic::{AtomicPtr, Ordering}; @@ -7,7 +6,7 @@ use crate::runtime::{Class, Sel, self}; /// Allows storing a `Sel` in a static and lazily loading it. #[doc(hidden)] pub struct CachedSel { - ptr: AtomicPtr + ptr: AtomicPtr, } impl CachedSel { @@ -21,16 +20,16 @@ impl CachedSel { /// Returns the cached selector. If no selector is yet cached, registers /// one with the given name and stores it. #[inline(always)] - pub unsafe fn get(&self, name: &str) -> Sel { + pub unsafe fn get(&self, name: &str) -> &'static Sel { let ptr = self.ptr.load(Ordering::Relaxed); // It should be fine to use `Relaxed` ordering here because `sel_registerName` is // thread-safe. if ptr.is_null() { let sel = runtime::sel_registerName(name.as_ptr() as *const _); - self.ptr.store(sel.as_ptr() as *mut _, Ordering::Relaxed); - sel + self.ptr.store(sel as *mut _, Ordering::Relaxed); + &*sel } else { - Sel::from_ptr(ptr) + &*ptr } } } diff --git a/src/declare.rs b/src/declare.rs index 729a650aa..c2e3c74da 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -21,12 +21,12 @@ let mut decl = ClassDecl::new("MyNumber", superclass).unwrap(); decl.add_ivar::("_number"); // Add an ObjC method for getting the number -extern fn my_number_get(this: &Object, _cmd: Sel) -> u32 { +extern fn my_number_get(this: &Object, _cmd: &Sel) -> u32 { unsafe { *this.get_ivar("_number") } } unsafe { decl.add_method(sel!(number), - my_number_get as extern fn(&Object, Sel) -> u32); + my_number_get as extern fn(&Object, &Sel) -> u32); } decl.register(); @@ -68,8 +68,8 @@ macro_rules! method_decl_impl { } ); ($($t:ident),*) => ( - method_decl_impl!(-T, R, extern fn(&T, Sel $(, $t)*) -> R, $($t),*); - method_decl_impl!(-T, R, extern fn(&mut T, Sel $(, $t)*) -> R, $($t),*); + method_decl_impl!(-T, R, extern fn(&T, &Sel $(, $t)*) -> R, $($t),*); + method_decl_impl!(-T, R, extern fn(&mut T, &Sel $(, $t)*) -> R, $($t),*); ); } @@ -87,14 +87,13 @@ method_decl_impl!(A, B, C, D, E, F, G, H, I, J); method_decl_impl!(A, B, C, D, E, F, G, H, I, J, K); method_decl_impl!(A, B, C, D, E, F, G, H, I, J, K, L); -fn count_args(sel: Sel) -> usize { +fn count_args(sel: &Sel) -> usize { sel.name().chars().filter(|&c| c == ':').count() } fn method_type_encoding(ret: &Encoding, args: &[Encoding]) -> CString { // First two arguments are always self and the selector - let mut types = format!("{}{}{}", - ret, <*mut Object>::ENCODING, Sel::ENCODING); + let mut types = format!("{}{}{}", ret, <*mut Object>::ENCODING, <&Sel>::ENCODING); for enc in args { use std::fmt::Write; write!(&mut types, "{}", enc).unwrap(); @@ -150,8 +149,7 @@ impl ClassDecl { Functionality it expects, like implementations of `-retain` and `-release` used by ARC, will not be present otherwise. */ - pub fn root(name: &str, intitialize_fn: extern fn(&Class, Sel)) - -> Option { + pub fn root(name: &str, intitialize_fn: extern "C" fn(&Class, &Sel)) -> Option { let mut decl = ClassDecl::with_superclass(name, None); if let Some(ref mut decl) = decl { unsafe { @@ -166,7 +164,7 @@ impl ClassDecl { /// or if the selector and function take different numbers of arguments. /// Unsafe because the caller must ensure that the types match those that /// are expected when the method is invoked from Objective-C. - pub unsafe fn add_method(&mut self, sel: Sel, func: F) + pub unsafe fn add_method(&mut self, sel: &Sel, func: F) where F: MethodImplementation { let encs = F::Args::ENCODINGS; let sel_args = count_args(sel); @@ -186,8 +184,10 @@ impl ClassDecl { /// or if the selector and function take different numbers of arguments. /// Unsafe because the caller must ensure that the types match those that /// are expected when the method is invoked from Objective-C. - pub unsafe fn add_class_method(&mut self, sel: Sel, func: F) - where F: MethodImplementation { + pub unsafe fn add_class_method(&mut self, sel: &Sel, func: F) + where + F: MethodImplementation, + { let encs = F::Args::ENCODINGS; let sel_args = count_args(sel); assert!(sel_args == encs.len(), @@ -265,10 +265,15 @@ impl ProtocolDecl { } } - fn add_method_description_common(&mut self, sel: Sel, is_required: bool, - is_instance_method: bool) - where Args: EncodeArguments, - Ret: Encode { + fn add_method_description_common( + &mut self, + sel: &Sel, + is_required: bool, + is_instance_method: bool, + ) where + Args: EncodeArguments, + Ret: Encode, + { let encs = Args::ENCODINGS; let sel_args = count_args(sel); assert!(sel_args == encs.len(), @@ -283,16 +288,20 @@ impl ProtocolDecl { } /// Adds an instance method declaration with a given description to self. - pub fn add_method_description(&mut self, sel: Sel, is_required: bool) - where Args: EncodeArguments, - Ret: Encode { + pub fn add_method_description(&mut self, sel: &Sel, is_required: bool) + where + Args: EncodeArguments, + Ret: Encode, + { self.add_method_description_common::(sel, is_required, true) } /// Adds a class method declaration with a given description to self. - pub fn add_class_method_description(&mut self, sel: Sel, is_required: bool) - where Args: EncodeArguments, - Ret: Encode { + pub fn add_class_method_description(&mut self, sel: &Sel, is_required: bool) + where + Args: EncodeArguments, + Ret: Encode, + { self.add_method_description_common::(sel, is_required, false) } diff --git a/src/encode.rs b/src/encode.rs index 87d5a4669..a48ff4cba 100644 --- a/src/encode.rs +++ b/src/encode.rs @@ -1,10 +1,12 @@ use crate::runtime::{Class, Object, Sel}; use crate::{Encode, Encoding}; -unsafe impl Encode for Sel { +unsafe impl<'a> Encode for &'a Sel { const ENCODING: Encoding<'static> = Encoding::Sel; } +// We don't implement `Encode` for `&mut Sel` because selectors are immutable. + unsafe impl<'a> Encode for &'a Object { const ENCODING: Encoding<'static> = Encoding::Object; } @@ -62,6 +64,7 @@ mod tests { assert!(<&Object>::ENCODING.to_string() == "@"); assert!(<*mut Object>::ENCODING.to_string() == "@"); assert!(<&Class>::ENCODING.to_string() == "#"); - assert!(Sel::ENCODING.to_string() == ":"); + assert!(<*const Sel>::ENCODING.to_string() == ":"); + assert!(<&Sel>::ENCODING.to_string() == ":"); } } diff --git a/src/macros.rs b/src/macros.rs index f0e9fabc0..751e14378 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -27,7 +27,7 @@ macro_rules! class { } /** -Registers a selector, returning a `Sel`. +Registers a selector, returning a `&'static Sel`. # Example ``` diff --git a/src/message/apple/mod.rs b/src/message/apple/mod.rs index 34b6f14c0..b77fb4e5e 100644 --- a/src/message/apple/mod.rs +++ b/src/message/apple/mod.rs @@ -18,7 +18,7 @@ mod arch; use self::arch::{msg_send_fn, msg_send_super_fn}; -pub unsafe fn send_unverified(obj: *const T, sel: Sel, args: A) +pub unsafe fn send_unverified(obj: *const T, sel: &Sel, args: A) -> Result where T: Message, A: MessageArguments, R: Any { let receiver = obj as *mut T as *mut Object; @@ -29,7 +29,7 @@ pub unsafe fn send_unverified(obj: *const T, sel: Sel, args: A) } pub unsafe fn send_super_unverified(obj: *const T, superclass: &Class, - sel: Sel, args: A) -> Result + sel: &Sel, args: A) -> Result where T: Message, A: MessageArguments, R: Any { let sup = Super { receiver: obj as *mut T as *mut Object, superclass: superclass }; let receiver = &sup as *const Super as *mut Object; diff --git a/src/message/gnustep.rs b/src/message/gnustep.rs index 382ef8625..6b099a47b 100644 --- a/src/message/gnustep.rs +++ b/src/message/gnustep.rs @@ -5,11 +5,11 @@ use crate::runtime::{Class, Object, Imp, Sel}; use super::{Message, MessageArguments, MessageError, Super}; extern { - fn objc_msg_lookup(receiver: *mut Object, op: Sel) -> Imp; - fn objc_msg_lookup_super(sup: *const Super, sel: Sel) -> Imp; + fn objc_msg_lookup(receiver: *mut Object, op: &Sel) -> Imp; + fn objc_msg_lookup_super(sup: *const Super, sel: &Sel) -> Imp; } -pub unsafe fn send_unverified(obj: *const T, sel: Sel, args: A) +pub unsafe fn send_unverified(obj: *const T, sel: &Sel, args: A) -> Result where T: Message, A: MessageArguments, R: Any { if obj.is_null() { @@ -24,7 +24,7 @@ pub unsafe fn send_unverified(obj: *const T, sel: Sel, args: A) } pub unsafe fn send_super_unverified(obj: *const T, superclass: &Class, - sel: Sel, args: A) -> Result + sel: &Sel, args: A) -> Result where T: Message, A: MessageArguments, R: Any { let receiver = obj as *mut T as *mut Object; let sup = Super { receiver: receiver, superclass: superclass }; diff --git a/src/message/mod.rs b/src/message/mod.rs index 86f80dcee..19783e627 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -59,14 +59,14 @@ pub unsafe trait Message { `msg_send!` macro rather than this method. */ #[cfg(not(feature = "verify_message"))] - unsafe fn send_message(&self, sel: Sel, args: A) + unsafe fn send_message(&self, sel: &Sel, args: A) -> Result where Self: Sized, A: MessageArguments, R: Any { send_message(self, sel, args) } #[cfg(feature = "verify_message")] - unsafe fn send_message(&self, sel: Sel, args: A) + unsafe fn send_message(&self, sel: &Sel, args: A) -> Result where Self: Sized, A: MessageArguments + EncodeArguments, R: Any + Encode { @@ -96,7 +96,7 @@ pub unsafe trait Message { # } ``` */ - fn verify_message(&self, sel: Sel) -> Result<(), MessageError> + fn verify_message(&self, sel: &Sel) -> Result<(), MessageError> where Self: Sized, A: EncodeArguments, R: Encode { let obj = unsafe { &*(self as *const _ as *const Object) }; verify_message_signature::(obj.class(), sel) @@ -115,16 +115,16 @@ pub trait MessageArguments: Sized { /// This method is the primitive used when sending messages and should not /// be called directly; instead, use the `msg_send!` macro or, in cases /// with a dynamic selector, the `Message::send_message` method. - unsafe fn invoke(imp: Imp, obj: *mut Object, sel: Sel, args: Self) -> R + unsafe fn invoke(imp: Imp, obj: *mut Object, sel: &Sel, args: Self) -> R where R: Any; } macro_rules! message_args_impl { ($($a:ident : $t:ident),*) => ( impl<$($t),*> MessageArguments for ($($t,)*) { - unsafe fn invoke(imp: Imp, obj: *mut Object, sel: Sel, ($($a,)*): Self) -> R + unsafe fn invoke(imp: Imp, obj: *mut Object, sel: &Sel, ($($a,)*): Self) -> R where R: Any { - let imp: unsafe extern fn(*mut Object, Sel $(, $t)*) -> R = + let imp: unsafe extern fn(*mut Object, &Sel $(, $t)*) -> R = mem::transmute(imp); imp(obj, sel $(, $a)*) } @@ -179,7 +179,7 @@ impl<'a> From> for MessageError { #[doc(hidden)] #[inline(always)] #[cfg(not(feature = "verify_message"))] -pub unsafe fn send_message(obj: *const T, sel: Sel, args: A) +pub unsafe fn send_message(obj: *const T, sel: &Sel, args: A) -> Result where T: Message, A: MessageArguments, R: Any { send_unverified(obj, sel, args) @@ -188,7 +188,7 @@ pub unsafe fn send_message(obj: *const T, sel: Sel, args: A) #[doc(hidden)] #[inline(always)] #[cfg(feature = "verify_message")] -pub unsafe fn send_message(obj: *const T, sel: Sel, args: A) +pub unsafe fn send_message(obj: *const T, sel: &Sel, args: A) -> Result where T: Message, A: MessageArguments + EncodeArguments, R: Any + Encode { @@ -206,7 +206,7 @@ pub unsafe fn send_message(obj: *const T, sel: Sel, args: A) #[inline(always)] #[cfg(not(feature = "verify_message"))] pub unsafe fn send_super_message(obj: *const T, superclass: &Class, - sel: Sel, args: A) -> Result + sel: &Sel, args: A) -> Result where T: Message, A: MessageArguments, R: Any { send_super_unverified(obj, superclass, sel, args) } @@ -215,7 +215,7 @@ pub unsafe fn send_super_message(obj: *const T, superclass: &Class, #[inline(always)] #[cfg(feature = "verify_message")] pub unsafe fn send_super_message(obj: *const T, superclass: &Class, - sel: Sel, args: A) -> Result + sel: &Sel, args: A) -> Result where T: Message, A: MessageArguments + EncodeArguments, R: Any + Encode { if obj.is_null() { diff --git a/src/message/verify.rs b/src/message/verify.rs index 6bafabe16..2a69b5ba2 100644 --- a/src/message/verify.rs +++ b/src/message/verify.rs @@ -4,8 +4,8 @@ use crate::runtime::{Class, Method, Object, Sel}; use crate::{Encode, Encoding, EncodeArguments}; pub enum VerificationError<'a> { - NilReceiver(Sel), - MethodNotFound(&'a Class, Sel), + NilReceiver(&'a Sel), + MethodNotFound(&'a Class, &'a Sel), MismatchedReturn(&'a Method, Encoding<'static>), MismatchedArgumentsCount(&'a Method, usize), MismatchedArgument(&'a Method, usize, Encoding<'static>), @@ -39,9 +39,10 @@ impl<'a> fmt::Display for VerificationError<'a> { } } -pub fn verify_message_signature(cls: &Class, sel: Sel) - -> Result<(), VerificationError> - where A: EncodeArguments, R: Encode { +pub fn verify_message_signature<'a, A: EncodeArguments, R: Encode>( + cls: &'a Class, + sel: &'a Sel, +) -> Result<(), VerificationError<'a>> { let method = match cls.instance_method(sel) { Some(method) => method, None => return Err(VerificationError::MethodNotFound(cls, sel)), @@ -53,7 +54,7 @@ pub fn verify_message_signature(cls: &Class, sel: Sel) return Err(VerificationError::MismatchedReturn(method, ret)); } - let self_and_cmd = [<*mut Object>::ENCODING, Sel::ENCODING]; + let self_and_cmd = [<*mut Object>::ENCODING, <&Sel>::ENCODING]; let args = A::ENCODINGS; let count = self_and_cmd.len() + args.len(); diff --git a/src/runtime.rs b/src/runtime.rs index dd8f3aa09..54db8aad2 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -31,16 +31,16 @@ pub const YES: BOOL = true; #[cfg(target_arch = "aarch64")] pub const NO: BOOL = false; +/// A marker type to be embedded into other types just so that they cannot be +/// constructed externally. +type PrivateMarker = [u8; 0]; + /// A type that represents a method selector. #[repr(C)] pub struct Sel { - ptr: *const c_void, + _priv: PrivateMarker, } -/// A marker type to be embedded into other types just so that they cannot be -/// constructed externally. -type PrivateMarker = [u8; 0]; - /// A type that represents an instance variable. #[repr(C)] pub struct Ivar { @@ -76,17 +76,17 @@ pub type Imp = unsafe extern fn(); #[link(name = "objc", kind = "dylib")] extern { - pub fn sel_registerName(name: *const c_char) -> Sel; - pub fn sel_getName(sel: Sel) -> *const c_char; + pub fn sel_registerName(name: *const c_char) -> *const Sel; + pub fn sel_getName(sel: *const Sel) -> *const c_char; pub fn class_getName(cls: *const Class) -> *const c_char; pub fn class_getSuperclass(cls: *const Class) -> *const Class; pub fn class_getInstanceSize(cls: *const Class) -> usize; - pub fn class_getInstanceMethod(cls: *const Class, sel: Sel) -> *const Method; + pub fn class_getInstanceMethod(cls: *const Class, sel: *const Sel) -> *const Method; pub fn class_getInstanceVariable(cls: *const Class, name: *const c_char) -> *const Ivar; pub fn class_copyMethodList(cls: *const Class, outCount: *mut c_uint) -> *mut *const Method; pub fn class_copyIvarList(cls: *const Class, outCount: *mut c_uint) -> *mut *const Ivar; - pub fn class_addMethod(cls: *mut Class, name: Sel, imp: Imp, types: *const c_char) -> BOOL; + pub fn class_addMethod(cls: *mut Class, name: *const Sel, imp: Imp, types: *const c_char) -> BOOL; pub fn class_addIvar(cls: *mut Class, name: *const c_char, size: usize, alignment: u8, types: *const c_char) -> BOOL; pub fn class_addProtocol(cls: *mut Class, proto: *const Protocol) -> BOOL; pub fn class_conformsToProtocol(cls: *const Class, proto: *const Protocol) -> BOOL; @@ -111,7 +111,7 @@ extern { pub fn objc_autoreleasePoolPush() -> *mut c_void; pub fn objc_autoreleasePoolPop(context: *mut c_void); - pub fn protocol_addMethodDescription(proto: *mut Protocol, name: Sel, types: *const c_char, isRequiredMethod: BOOL, + pub fn protocol_addMethodDescription(proto: *mut Protocol, name: *const Sel, types: *const c_char, isRequiredMethod: BOOL, isInstanceMethod: BOOL); pub fn protocol_addProtocol(proto: *mut Protocol, addition: *const Protocol); pub fn protocol_getName(proto: *const Protocol) -> *const c_char; @@ -123,7 +123,7 @@ extern { pub fn ivar_getOffset(ivar: *const Ivar) -> isize; pub fn ivar_getTypeEncoding(ivar: *const Ivar) -> *const c_char; - pub fn method_getName(method: *const Method) -> Sel; + pub fn method_getName(method: *const Method) -> *const Sel; pub fn method_getImplementation(method: *const Method) -> Imp; pub fn method_copyReturnType(method: *const Method) -> *mut c_char; pub fn method_copyArgumentType(method: *const Method, index: c_uint) -> *mut c_char; @@ -144,55 +144,34 @@ extern { impl Sel { /// Registers a method with the Objective-C runtime system, /// maps the method name to a selector, and returns the selector value. - pub fn register(name: &str) -> Sel { + pub fn register(name: &str) -> &'static Sel { let name = CString::new(name).unwrap(); - unsafe { - sel_registerName(name.as_ptr()) - } + // The input is not a null pointer, so this cannot return null + unsafe { &*sel_registerName(name.as_ptr()) } } /// Returns the name of the method specified by self. pub fn name(&self) -> &str { - let name = unsafe { - CStr::from_ptr(sel_getName(*self)) - }; + let name = unsafe { CStr::from_ptr(sel_getName(self)) }; str::from_utf8(name.to_bytes()).unwrap() } - - /// Wraps a raw pointer to a selector into a `Sel` object. - /// - /// This is almost never what you want; use `Sel::register()` instead. - #[inline] - pub unsafe fn from_ptr(ptr: *const c_void) -> Sel { - Sel { - ptr: ptr, - } - } - - /// Returns a pointer to the raw selector. - #[inline] - pub fn as_ptr(&self) -> *const c_void { - self.ptr - } } impl PartialEq for Sel { - fn eq(&self, other: &Sel) -> bool { - self.ptr == other.ptr + fn eq(&self, other: &Self) -> bool { + // Pointer equality + self as *const Self == other as *const Self } } impl Eq for Sel { } -// Sel is safe to share across threads because it is immutable -unsafe impl Sync for Sel { } -unsafe impl Send for Sel { } - -impl Copy for Sel { } +/// [`Sel`] is immutable and safe to share across threads. +unsafe impl Sync for Sel {} -impl Clone for Sel { - fn clone(&self) -> Sel { *self } -} +/// You can never own a [`Sel`], so this implementation is a bit moot, but a +/// [`Sel`] is not bound to a specific thread, so this should be safe. +unsafe impl Send for Sel {} impl fmt::Debug for Sel { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -228,10 +207,8 @@ impl Ivar { impl Method { /// Returns the name of self. - pub fn name(&self) -> Sel { - unsafe { - method_getName(self) - } + pub fn name(&self) -> &'static Sel { + unsafe { &*method_getName(self) } } /// Returns the `Encoding` of self's return type. @@ -331,7 +308,7 @@ impl Class { /// Returns a specified instance method for self, or `None` if self and /// its superclasses do not contain an instance method with the /// specified selector. - pub fn instance_method(&self, sel: Sel) -> Option<&Method> { + pub fn instance_method<'a>(&'a self, sel: &Sel) -> Option<&'a Method> { unsafe { let method = class_getInstanceMethod(self, sel); if method.is_null() { None } else { Some(&*method) } @@ -550,7 +527,7 @@ mod tests { assert!(method.name().name() == "foo"); assert!(method.arguments_count() == 2); assert!(*method.return_type() == ::ENCODING); - assert!(*method.argument_type(1).unwrap() == Sel::ENCODING); + assert!(*method.argument_type(1).unwrap() == <&Sel>::ENCODING); let methods = cls.instance_methods(); assert!(methods.len() > 0); diff --git a/src/test_utils.rs b/src/test_utils.rs index 226be9fe5..e2bad9f5b 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -59,7 +59,7 @@ pub fn custom_class() -> &'static Class { REGISTER_CUSTOM_CLASS.call_once(|| { // The runtime will call this method, so it has to be implemented - extern fn custom_obj_class_initialize(_this: &Class, _cmd: Sel) { } + extern fn custom_obj_class_initialize(_this: &Class, _cmd: &Sel) { } let mut decl = ClassDecl::root("CustomObject", custom_obj_class_initialize).unwrap(); let proto = custom_protocol(); @@ -67,43 +67,43 @@ pub fn custom_class() -> &'static Class { decl.add_protocol(proto); decl.add_ivar::("_foo"); - extern fn custom_obj_set_foo(this: &mut Object, _cmd: Sel, foo: u32) { + extern fn custom_obj_set_foo(this: &mut Object, _cmd: &Sel, foo: u32) { unsafe { this.set_ivar::("_foo", foo); } } - extern fn custom_obj_get_foo(this: &Object, _cmd: Sel) -> u32 { + extern fn custom_obj_get_foo(this: &Object, _cmd: &Sel) -> u32 { unsafe { *this.get_ivar::("_foo") } } - extern fn custom_obj_get_struct(_this: &Object, _cmd: Sel) -> CustomStruct { + extern fn custom_obj_get_struct(_this: &Object, _cmd: &Sel) -> CustomStruct { CustomStruct { a: 1, b: 2, c: 3, d: 4 } } - extern fn custom_obj_class_method(_this: &Class, _cmd: Sel) -> u32 { + extern fn custom_obj_class_method(_this: &Class, _cmd: &Sel) -> u32 { 7 } - extern fn custom_obj_set_bar(this: &mut Object, _cmd: Sel, bar: u32) { + extern fn custom_obj_set_bar(this: &mut Object, _cmd: &Sel, bar: u32) { unsafe { this.set_ivar::("_foo", bar) ;} } - extern fn custom_obj_add_number_to_number(_this: &Class, _cmd: Sel, fst: i32, snd: i32) -> i32 { + extern fn custom_obj_add_number_to_number(_this: &Class, _cmd: &Sel, fst: i32, snd: i32) -> i32 { fst + snd } unsafe { - let set_foo: extern fn(&mut Object, Sel, u32) = custom_obj_set_foo; + let set_foo: extern fn(&mut Object, &Sel, u32) = custom_obj_set_foo; decl.add_method(sel!(setFoo:), set_foo); - let get_foo: extern fn(&Object, Sel) -> u32 = custom_obj_get_foo; + let get_foo: extern fn(&Object, &Sel) -> u32 = custom_obj_get_foo; decl.add_method(sel!(foo), get_foo); - let get_struct: extern fn(&Object, Sel) -> CustomStruct = custom_obj_get_struct; + let get_struct: extern fn(&Object, &Sel) -> CustomStruct = custom_obj_get_struct; decl.add_method(sel!(customStruct), get_struct); - let class_method: extern fn(&Class, Sel) -> u32 = custom_obj_class_method; + let class_method: extern fn(&Class, &Sel) -> u32 = custom_obj_class_method; decl.add_class_method(sel!(classFoo), class_method); - let protocol_instance_method: extern fn(&mut Object, Sel, u32) = custom_obj_set_bar; + let protocol_instance_method: extern fn(&mut Object, &Sel, u32) = custom_obj_set_bar; decl.add_method(sel!(setBar:), protocol_instance_method); - let protocol_class_method: extern fn(&Class, Sel, i32, i32) -> i32 = custom_obj_add_number_to_number; + let protocol_class_method: extern fn(&Class, &Sel, i32, i32) -> i32 = custom_obj_add_number_to_number; decl.add_class_method(sel!(addNumber:toNumber:), protocol_class_method); } @@ -156,7 +156,7 @@ pub fn custom_subclass() -> &'static Class { let superclass = custom_class(); let mut decl = ClassDecl::new("CustomSubclassObject", superclass).unwrap(); - extern fn custom_subclass_get_foo(this: &Object, _cmd: Sel) -> u32 { + extern fn custom_subclass_get_foo(this: &Object, _cmd: &Sel) -> u32 { let foo: u32 = unsafe { msg_send![super(this, custom_class()), foo] }; @@ -164,7 +164,7 @@ pub fn custom_subclass() -> &'static Class { } unsafe { - let get_foo: extern fn(&Object, Sel) -> u32 = custom_subclass_get_foo; + let get_foo: extern fn(&Object, &Sel) -> u32 = custom_subclass_get_foo; decl.add_method(sel!(foo), get_foo); }