From a626c49f3ed041fe26fe294f62d1d2567d2744f9 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 2 Sep 2021 18:30:39 +0200 Subject: [PATCH 01/36] Move objc::runtime into new objc_sys crate --- Cargo.toml | 1 + objc/Cargo.toml | 1 + objc/src/cache.rs | 8 +- objc/src/declare.rs | 34 ++++-- objc/src/rc/strong.rs | 6 +- objc/src/rc/weak.rs | 10 +- objc/src/runtime.rs | 271 ++++++++++++++--------------------------- objc/src/test_utils.rs | 7 +- objc_sys/Cargo.toml | 15 +++ objc_sys/src/lib.rs | 161 ++++++++++++++++++++++++ 10 files changed, 307 insertions(+), 207 deletions(-) create mode 100644 objc_sys/Cargo.toml create mode 100644 objc_sys/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 75b073626..35b2465f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ members = [ "objc_foundation", "objc_foundation_derive", "objc_id", + "objc_sys", "objc_test_utils", ] exclude = ["objc/tests-ios"] diff --git a/objc/Cargo.toml b/objc/Cargo.toml index e28336916..a9487ba07 100644 --- a/objc/Cargo.toml +++ b/objc/Cargo.toml @@ -28,5 +28,6 @@ unstable_autoreleasesafe = [] [dependencies] malloc_buf = "1.0" +objc_sys = { path = "../objc_sys" } objc-encode = { path = "../objc_encode", version = "1.0" } objc_exception = { path = "../objc_exception", version = "0.1", optional = true } diff --git a/objc/src/cache.rs b/objc/src/cache.rs index 4cfb1ae96..bf9080f53 100644 --- a/objc/src/cache.rs +++ b/objc/src/cache.rs @@ -26,9 +26,9 @@ impl CachedSel { // 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 + let ptr = runtime::sel_registerName(name.as_ptr() as *const _); + self.ptr.store(ptr as *mut _, Ordering::Relaxed); + Sel::from_ptr(ptr as *const _) } else { Sel::from_ptr(ptr) } @@ -56,7 +56,7 @@ impl CachedClass { // `Relaxed` should be fine since `objc_getClass` is thread-safe. let ptr = self.ptr.load(Ordering::Relaxed); if ptr.is_null() { - let cls = runtime::objc_getClass(name.as_ptr() as *const _); + let cls = runtime::objc_getClass(name.as_ptr() as *const _) as *const Class; self.ptr.store(cls as *mut _, Ordering::Relaxed); cls.as_ref() } else { diff --git a/objc/src/declare.rs b/objc/src/declare.rs index 099fb7519..0cfbe0c8e 100644 --- a/objc/src/declare.rs +++ b/objc/src/declare.rs @@ -118,12 +118,12 @@ pub struct ClassDecl { impl ClassDecl { fn with_superclass(name: &str, superclass: Option<&Class>) -> Option { let name = CString::new(name).unwrap(); - let super_ptr = superclass.map_or(ptr::null(), |c| c); + let super_ptr = superclass.map_or(ptr::null(), |c| c) as _; let cls = unsafe { runtime::objc_allocateClassPair(super_ptr, name.as_ptr(), 0) }; if cls.is_null() { None } else { - Some(ClassDecl { cls }) + Some(ClassDecl { cls: cls as _ }) } } @@ -182,7 +182,8 @@ impl ClassDecl { ); let types = method_type_encoding(&F::Ret::ENCODING, encs); - let success = runtime::class_addMethod(self.cls, sel, func.imp(), types.as_ptr()); + let success = + runtime::class_addMethod(self.cls as _, sel.as_ptr() as _, func.imp(), types.as_ptr()); assert!(success != NO, "Failed to add method {:?}", sel); } @@ -212,7 +213,8 @@ impl ClassDecl { let types = method_type_encoding(&F::Ret::ENCODING, encs); let metaclass = (*self.cls).metaclass() as *const _ as *mut _; - let success = runtime::class_addMethod(metaclass, sel, func.imp(), types.as_ptr()); + let success = + runtime::class_addMethod(metaclass, sel.as_ptr() as _, func.imp(), types.as_ptr()); assert!(success != NO, "Failed to add class method {:?}", sel); } @@ -227,7 +229,13 @@ impl ClassDecl { let size = mem::size_of::(); let align = log2_align_of::(); let success = unsafe { - runtime::class_addIvar(self.cls, c_name.as_ptr(), size, align, encoding.as_ptr()) + runtime::class_addIvar( + self.cls as _, + c_name.as_ptr(), + size, + align, + encoding.as_ptr(), + ) }; assert!(success != NO, "Failed to add ivar {}", name); } @@ -238,7 +246,7 @@ impl ClassDecl { /// /// If the protocol wasn't successfully added. pub fn add_protocol(&mut self, proto: &Protocol) { - let success = unsafe { runtime::class_addProtocol(self.cls, proto) }; + let success = unsafe { runtime::class_addProtocol(self.cls as _, proto.as_ptr()) }; assert!(success != NO, "Failed to add protocol {:?}", proto); } @@ -247,7 +255,7 @@ impl ClassDecl { pub fn register(self) -> &'static Class { unsafe { let cls = self.cls; - runtime::objc_registerClassPair(cls); + runtime::objc_registerClassPair(cls as _); // Forget self otherwise the class will be disposed in drop mem::forget(self); &*cls @@ -258,7 +266,7 @@ impl ClassDecl { impl Drop for ClassDecl { fn drop(&mut self) { unsafe { - runtime::objc_disposeClassPair(self.cls); + runtime::objc_disposeClassPair(self.cls as _); } } } @@ -275,7 +283,7 @@ impl ProtocolDecl { /// Returns [`None`] if the protocol couldn't be allocated. pub fn new(name: &str) -> Option { let c_name = CString::new(name).unwrap(); - let proto = unsafe { runtime::objc_allocateProtocol(c_name.as_ptr()) }; + let proto = unsafe { runtime::objc_allocateProtocol(c_name.as_ptr()) } as *mut Protocol; if proto.is_null() { None } else { @@ -303,8 +311,8 @@ impl ProtocolDecl { let types = method_type_encoding(&Ret::ENCODING, encs); unsafe { runtime::protocol_addMethodDescription( - self.proto, - sel, + self.proto as _, + sel.as_ptr() as _, types.as_ptr(), is_required as BOOL, is_instance_method as BOOL, @@ -333,7 +341,7 @@ impl ProtocolDecl { /// Adds a requirement on another protocol. pub fn add_protocol(&mut self, proto: &Protocol) { unsafe { - runtime::protocol_addProtocol(self.proto, proto); + runtime::protocol_addProtocol(self.proto as _, proto.as_ptr()); } } @@ -341,7 +349,7 @@ impl ProtocolDecl { /// to the newly registered [`Protocol`]. pub fn register(self) -> &'static Protocol { unsafe { - runtime::objc_registerProtocol(self.proto); + runtime::objc_registerProtocol(self.proto as _); &*self.proto } } diff --git a/objc/src/rc/strong.rs b/objc/src/rc/strong.rs index 67eca8824..eb2264443 100644 --- a/objc/src/rc/strong.rs +++ b/objc/src/rc/strong.rs @@ -27,7 +27,7 @@ impl StrongPtr { /// /// The caller must ensure the given object pointer is valid. pub unsafe fn retain(ptr: *mut Object) -> Self { - StrongPtr(runtime::objc_retain(ptr)) + Self(runtime::objc_retain(ptr as _) as _) } /// Autoreleases self, meaning that the object is not immediately released, @@ -37,7 +37,7 @@ impl StrongPtr { let ptr = self.0; mem::forget(self); unsafe { - runtime::objc_autorelease(ptr); + runtime::objc_autorelease(ptr as _); } ptr } @@ -51,7 +51,7 @@ impl StrongPtr { impl Drop for StrongPtr { fn drop(&mut self) { unsafe { - runtime::objc_release(self.0); + runtime::objc_release(self.0 as _); } } } diff --git a/objc/src/rc/weak.rs b/objc/src/rc/weak.rs index da24cf02b..448810a2e 100644 --- a/objc/src/rc/weak.rs +++ b/objc/src/rc/weak.rs @@ -21,7 +21,7 @@ impl WeakPtr { /// The caller must ensure the given object pointer is valid. pub unsafe fn new(obj: *mut Object) -> Self { let ptr = Box::new(UnsafeCell::new(ptr::null_mut())); - runtime::objc_initWeak(ptr.get(), obj); + runtime::objc_initWeak(ptr.get() as _, obj as _); WeakPtr(ptr) } @@ -29,8 +29,8 @@ impl WeakPtr { /// If the object has been deallocated, the returned pointer will be null. pub fn load(&self) -> StrongPtr { unsafe { - let ptr = runtime::objc_loadWeakRetained(self.0.get()); - StrongPtr::new(ptr) + let ptr = runtime::objc_loadWeakRetained(self.0.get() as _); + StrongPtr::new(ptr as _) } } } @@ -38,7 +38,7 @@ impl WeakPtr { impl Drop for WeakPtr { fn drop(&mut self) { unsafe { - runtime::objc_destroyWeak(self.0.get()); + runtime::objc_destroyWeak(self.0.get() as _); } } } @@ -47,7 +47,7 @@ impl Clone for WeakPtr { fn clone(&self) -> Self { let ptr = Box::new(UnsafeCell::new(ptr::null_mut())); unsafe { - runtime::objc_copyWeak(ptr.get(), self.0.get()); + runtime::objc_copyWeak(ptr.get() as _, self.0.get() as _); } WeakPtr(ptr) } diff --git a/objc/src/runtime.rs b/objc/src/runtime.rs index c402bbd71..51d5f039b 100644 --- a/objc/src/runtime.rs +++ b/objc/src/runtime.rs @@ -9,173 +9,67 @@ use core::ptr; use core::str; use malloc_buf::Malloc; use std::ffi::{CStr, CString}; -use std::os::raw::{c_char, c_int, c_uint}; +use std::os::raw::c_uint; use crate::Encode; -/// The Objective-C `BOOL` type. -/// -/// To convert an Objective-C `BOOL` into a Rust [`bool`], compare it with [`NO`]. -#[cfg(all(target_vendor = "apple", not(target_arch = "aarch64")))] -pub type BOOL = ::std::os::raw::c_schar; -#[cfg(all(not(target_vendor = "apple"), not(target_arch = "aarch64")))] -pub type BOOL = u8; - -/// The equivalent of true for Objective-C's [`BOOL`] type. -#[cfg(not(target_arch = "aarch64"))] -pub const YES: BOOL = 1; -/// The equivalent of false for Objective-C's [`BOOL`] type. -#[cfg(not(target_arch = "aarch64"))] -pub const NO: BOOL = 0; - -#[cfg(target_arch = "aarch64")] -pub type BOOL = bool; -#[cfg(target_arch = "aarch64")] -pub const YES: BOOL = true; -#[cfg(target_arch = "aarch64")] -pub const NO: BOOL = false; +use objc_sys; +pub use objc_sys::{ + class_addIvar, class_addMethod, class_addProtocol, class_conformsToProtocol, + class_copyIvarList, class_copyMethodList, class_copyProtocolList, class_createInstance, + class_getInstanceMethod, class_getInstanceSize, class_getInstanceVariable, class_getName, + class_getSuperclass, ivar_getName, ivar_getOffset, ivar_getTypeEncoding, + method_copyArgumentType, method_copyReturnType, method_exchangeImplementations, + method_getImplementation, method_getName, method_getNumberOfArguments, + method_setImplementation, objc_allocateClassPair, objc_allocateProtocol, objc_autorelease, + objc_autoreleasePoolPop, objc_autoreleasePoolPush, objc_copyClassList, objc_copyProtocolList, + objc_copyWeak, objc_destroyWeak, objc_disposeClassPair, objc_getClass, objc_getClassList, + objc_getProtocol, objc_initWeak, objc_loadWeakRetained, objc_registerClassPair, + objc_registerProtocol, objc_release, objc_retain, object_dispose, object_getClass, + protocol_addMethodDescription, protocol_addProtocol, protocol_conformsToProtocol, + protocol_copyProtocolList, protocol_getName, protocol_isEqual, sel_getName, sel_registerName, +}; +pub use objc_sys::{Imp, BOOL, NO, YES}; /// A type that represents a method selector. -#[repr(C)] +#[repr(transparent)] pub struct Sel { - ptr: *const c_void, + ptr: *const objc_sys::Sel, } -/// 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 { - _priv: PrivateMarker, -} +pub struct Ivar(objc_sys::Ivar); /// A type that represents a method in a class definition. #[repr(C)] -pub struct Method { - _priv: PrivateMarker, -} +pub struct Method(objc_sys::Method); /// A type that represents an Objective-C class. #[repr(C)] -pub struct Class { - _priv: PrivateMarker, -} +pub struct Class(objc_sys::Class); /// A type that represents an Objective-C protocol. #[repr(C)] -pub struct Protocol { - _priv: PrivateMarker, -} +pub struct Protocol(objc_sys::Protocol); /// A type that represents an instance of a class. #[repr(C)] -pub struct Object { - _priv: PrivateMarker, -} - -/// A pointer to the start of a method implementation. -pub type Imp = unsafe extern "C" fn(); - -#[allow(missing_docs)] -#[link(name = "objc", kind = "dylib")] -extern "C" { - pub fn sel_registerName(name: *const c_char) -> Sel; - pub fn sel_getName(sel: 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_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_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; - pub fn class_copyProtocolList(cls: *const Class, outCount: *mut c_uint) - -> *mut *const Protocol; - - pub fn objc_allocateClassPair( - superclass: *const Class, - name: *const c_char, - extraBytes: usize, - ) -> *mut Class; - pub fn objc_disposeClassPair(cls: *mut Class); - pub fn objc_registerClassPair(cls: *mut Class); - - pub fn class_createInstance(cls: *const Class, extraBytes: usize) -> *mut Object; - pub fn object_dispose(obj: *mut Object) -> *mut Object; - pub fn object_getClass(obj: *const Object) -> *const Class; - - pub fn objc_getClassList(buffer: *mut *const Class, bufferLen: c_int) -> c_int; - pub fn objc_copyClassList(outCount: *mut c_uint) -> *mut *const Class; - pub fn objc_getClass(name: *const c_char) -> *const Class; - pub fn objc_getProtocol(name: *const c_char) -> *const Protocol; - pub fn objc_copyProtocolList(outCount: *mut c_uint) -> *mut *const Protocol; - pub fn objc_allocateProtocol(name: *const c_char) -> *mut Protocol; - pub fn objc_registerProtocol(proto: *mut Protocol); - - 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, - isInstanceMethod: BOOL, - ); - pub fn protocol_addProtocol(proto: *mut Protocol, addition: *const Protocol); - pub fn protocol_getName(proto: *const Protocol) -> *const c_char; - pub fn protocol_isEqual(proto: *const Protocol, other: *const Protocol) -> BOOL; - pub fn protocol_copyProtocolList( - proto: *const Protocol, - outCount: *mut c_uint, - ) -> *mut *const Protocol; - pub fn protocol_conformsToProtocol(proto: *const Protocol, other: *const Protocol) -> BOOL; - - pub fn ivar_getName(ivar: *const Ivar) -> *const c_char; - 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_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; - pub fn method_getNumberOfArguments(method: *const Method) -> c_uint; - pub fn method_setImplementation(method: *mut Method, imp: Imp) -> Imp; - pub fn method_exchangeImplementations(m1: *mut Method, m2: *mut Method); - - pub fn objc_retain(obj: *mut Object) -> *mut Object; - pub fn objc_release(obj: *mut Object); - pub fn objc_autorelease(obj: *mut Object); - - pub fn objc_loadWeakRetained(location: *mut *mut Object) -> *mut Object; - pub fn objc_initWeak(location: *mut *mut Object, obj: *mut Object) -> *mut Object; - pub fn objc_destroyWeak(location: *mut *mut Object); - pub fn objc_copyWeak(to: *mut *mut Object, from: *mut *mut Object); -} +pub struct Object(objc_sys::Object); 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) -> Self { let name = CString::new(name).unwrap(); - unsafe { sel_registerName(name.as_ptr()) } + Self { + ptr: 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.ptr)) }; str::from_utf8(name.to_bytes()).unwrap() } @@ -187,14 +81,16 @@ impl Sel { /// /// This is almost never what you want; use [`Sel::register`] instead. #[inline] - pub unsafe fn from_ptr(ptr: *const c_void) -> Sel { - Sel { ptr } + pub unsafe fn from_ptr(ptr: *const c_void) -> Self { + Self { + ptr: ptr as *const objc_sys::Sel, + } } /// Returns a pointer to the raw selector. #[inline] pub fn as_ptr(&self) -> *const c_void { - self.ptr + self.ptr as *const c_void } } @@ -213,8 +109,8 @@ unsafe impl Send for Sel {} impl Copy for Sel {} impl Clone for Sel { - fn clone(&self) -> Sel { - *self + fn clone(&self) -> Self { + Self { ptr: self.ptr } } } @@ -225,35 +121,45 @@ impl fmt::Debug for Sel { } impl Ivar { + pub(crate) fn as_ptr(&self) -> *const objc_sys::Ivar { + self as *const Self as *const _ + } + /// Returns the name of self. pub fn name(&self) -> &str { - let name = unsafe { CStr::from_ptr(ivar_getName(self)) }; + let name = unsafe { CStr::from_ptr(ivar_getName(self.as_ptr())) }; str::from_utf8(name.to_bytes()).unwrap() } /// Returns the offset of self. pub fn offset(&self) -> isize { - let offset = unsafe { ivar_getOffset(self) }; + let offset = unsafe { ivar_getOffset(self.as_ptr()) }; offset as isize } /// Returns the `Encoding` of self. pub fn type_encoding(&self) -> &str { - let encoding = unsafe { CStr::from_ptr(ivar_getTypeEncoding(self)) }; + let encoding = unsafe { CStr::from_ptr(ivar_getTypeEncoding(self.as_ptr())) }; str::from_utf8(encoding.to_bytes()).unwrap() } } impl Method { + pub(crate) fn as_ptr(&self) -> *const objc_sys::Method { + self as *const Self as *const _ + } + /// Returns the name of self. pub fn name(&self) -> Sel { - unsafe { method_getName(self) } + Sel { + ptr: unsafe { method_getName(self.as_ptr()) }, + } } /// Returns the `Encoding` of self's return type. pub fn return_type(&self) -> Malloc { unsafe { - let encoding = method_copyReturnType(self); + let encoding = method_copyReturnType(self.as_ptr()); Malloc::from_c_str(encoding).unwrap() } } @@ -262,7 +168,7 @@ impl Method { /// [`None`] if self has no parameter at the given index. pub fn argument_type(&self, index: usize) -> Option> { unsafe { - let encoding = method_copyArgumentType(self, index as c_uint); + let encoding = method_copyArgumentType(self.as_ptr(), index as c_uint); if encoding.is_null() { None } else { @@ -273,32 +179,36 @@ impl Method { /// Returns the number of arguments accepted by self. pub fn arguments_count(&self) -> usize { - unsafe { method_getNumberOfArguments(self) as usize } + unsafe { method_getNumberOfArguments(self.as_ptr()) as usize } } /// Returns the implementation of self. pub fn implementation(&self) -> Imp { - unsafe { method_getImplementation(self) } + unsafe { method_getImplementation(self.as_ptr()) } } } impl Class { + pub(crate) fn as_ptr(&self) -> *const objc_sys::Class { + self as *const Self as *const _ + } + /// Returns the class definition of a specified class, or [`None`] if the /// class is not registered with the Objective-C runtime. - pub fn get(name: &str) -> Option<&'static Class> { + pub fn get(name: &str) -> Option<&'static Self> { let name = CString::new(name).unwrap(); unsafe { let cls = objc_getClass(name.as_ptr()); if cls.is_null() { None } else { - Some(&*cls) + Some(&*(cls as *const Self)) } } } /// Obtains the list of registered class definitions. - pub fn classes() -> Malloc<[&'static Class]> { + pub fn classes() -> Malloc<[&'static Self]> { unsafe { let mut count: c_uint = 0; let classes = objc_copyClassList(&mut count); @@ -313,33 +223,30 @@ impl Class { /// Returns the name of the class. pub fn name(&self) -> &str { - let name = unsafe { CStr::from_ptr(class_getName(self)) }; + let name = unsafe { CStr::from_ptr(class_getName(self.as_ptr())) }; str::from_utf8(name.to_bytes()).unwrap() } /// Returns the superclass of self, or [`None`] if self is a root class. pub fn superclass(&self) -> Option<&Class> { unsafe { - let superclass = class_getSuperclass(self); + let superclass = class_getSuperclass(self.as_ptr()); if superclass.is_null() { None } else { - Some(&*superclass) + Some(&*(superclass as *const Self)) } } } /// Returns the metaclass of self. - pub fn metaclass(&self) -> &Class { - unsafe { - let self_ptr: *const Class = self; - &*object_getClass(self_ptr as *const Object) - } + pub fn metaclass(&self) -> &Self { + unsafe { &*(object_getClass(self.as_ptr() as *const objc_sys::Object) as *const Self) } } /// Returns the size of instances of self. pub fn instance_size(&self) -> usize { - unsafe { class_getInstanceSize(self) as usize } + unsafe { class_getInstanceSize(self.as_ptr()) as usize } } /// Returns a specified instance method for self, or [`None`] if self and @@ -347,11 +254,11 @@ impl Class { /// selector. pub fn instance_method(&self, sel: Sel) -> Option<&Method> { unsafe { - let method = class_getInstanceMethod(self, sel); + let method = class_getInstanceMethod(self.as_ptr(), sel.ptr); if method.is_null() { None } else { - Some(&*method) + Some(&*(method as *const Method)) } } } @@ -361,11 +268,11 @@ impl Class { pub fn instance_variable(&self, name: &str) -> Option<&Ivar> { let name = CString::new(name).unwrap(); unsafe { - let ivar = class_getInstanceVariable(self, name.as_ptr()); + let ivar = class_getInstanceVariable(self.as_ptr(), name.as_ptr()); if ivar.is_null() { None } else { - Some(&*ivar) + Some(&*(ivar as *const Ivar)) } } } @@ -374,21 +281,21 @@ impl Class { pub fn instance_methods(&self) -> Malloc<[&Method]> { unsafe { let mut count: c_uint = 0; - let methods = class_copyMethodList(self, &mut count); + let methods = class_copyMethodList(self.as_ptr(), &mut count); Malloc::from_array(methods as *mut _, count as usize) } } /// Checks whether this class conforms to the specified protocol. pub fn conforms_to(&self, proto: &Protocol) -> bool { - unsafe { class_conformsToProtocol(self, proto) == YES } + unsafe { class_conformsToProtocol(self.as_ptr(), proto.as_ptr()) == YES } } /// Get a list of the protocols to which this class conforms. pub fn adopted_protocols(&self) -> Malloc<[&Protocol]> { unsafe { let mut count: c_uint = 0; - let protos = class_copyProtocolList(self, &mut count); + let protos = class_copyProtocolList(self.as_ptr(), &mut count); Malloc::from_array(protos as *mut _, count as usize) } } @@ -397,7 +304,7 @@ impl Class { pub fn instance_variables(&self) -> Malloc<[&Ivar]> { unsafe { let mut count: c_uint = 0; - let ivars = class_copyIvarList(self, &mut count); + let ivars = class_copyIvarList(self.as_ptr(), &mut count); Malloc::from_array(ivars as *mut _, count as usize) } } @@ -405,9 +312,7 @@ impl Class { impl PartialEq for Class { fn eq(&self, other: &Class) -> bool { - let self_ptr: *const Class = self; - let other_ptr: *const Class = other; - self_ptr == other_ptr + self.as_ptr() == other.as_ptr() } } @@ -420,6 +325,10 @@ impl fmt::Debug for Class { } impl Protocol { + pub(crate) fn as_ptr(&self) -> *const objc_sys::Protocol { + self as *const Self as *const _ + } + /// Returns the protocol definition of a specified protocol, or [`None`] /// if the protocol is not registered with the Objective-C runtime. pub fn get(name: &str) -> Option<&'static Protocol> { @@ -429,7 +338,7 @@ impl Protocol { if proto.is_null() { None } else { - Some(&*proto) + Some(&*(proto as *const Self)) } } } @@ -447,26 +356,26 @@ impl Protocol { pub fn adopted_protocols(&self) -> Malloc<[&Protocol]> { unsafe { let mut count: c_uint = 0; - let protocols = protocol_copyProtocolList(self, &mut count); + let protocols = protocol_copyProtocolList(self.as_ptr(), &mut count); Malloc::from_array(protocols as *mut _, count as usize) } } /// Checks whether this protocol conforms to the specified protocol. pub fn conforms_to(&self, proto: &Protocol) -> bool { - unsafe { protocol_conformsToProtocol(self, proto) == YES } + unsafe { protocol_conformsToProtocol(self.as_ptr(), proto.as_ptr()) == YES } } /// Returns the name of self. pub fn name(&self) -> &str { - let name = unsafe { CStr::from_ptr(protocol_getName(self)) }; + let name = unsafe { CStr::from_ptr(protocol_getName(self.as_ptr())) }; str::from_utf8(name.to_bytes()).unwrap() } } impl PartialEq for Protocol { fn eq(&self, other: &Protocol) -> bool { - unsafe { protocol_isEqual(self, other) == YES } + unsafe { protocol_isEqual(self.as_ptr(), other.as_ptr()) == YES } } } @@ -489,9 +398,13 @@ fn get_ivar_offset(cls: &Class, name: &str) -> isize { } impl Object { + pub(crate) fn as_ptr(&self) -> *const objc_sys::Object { + self as *const Self as *const _ + } + /// Returns the class of this object. pub fn class(&self) -> &Class { - unsafe { &*object_getClass(self) } + unsafe { &*(object_getClass(self.as_ptr()) as *const Class) } } /// Returns a shared reference to the ivar with the given name. @@ -543,7 +456,7 @@ impl Object { impl fmt::Debug for Object { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "<{:?}: {:p}>", self.class(), self) + write!(f, "<{:?}: {:p}>", self.class(), self.as_ptr()) } } diff --git a/objc/src/test_utils.rs b/objc/src/test_utils.rs index 7b2a80435..e0609ac2d 100644 --- a/objc/src/test_utils.rs +++ b/objc/src/test_utils.rs @@ -12,8 +12,9 @@ pub struct CustomObject { impl CustomObject { fn new(class: &Class) -> Self { - let obj = unsafe { runtime::class_createInstance(class, 0) }; - CustomObject { obj } + let ptr = class as *const Class as _; + let obj = unsafe { runtime::class_createInstance(ptr, 0) }; + CustomObject { obj: obj as _ } } } @@ -34,7 +35,7 @@ impl DerefMut for CustomObject { impl Drop for CustomObject { fn drop(&mut self) { unsafe { - runtime::object_dispose(self.obj); + runtime::object_dispose(self.obj as _); } } } diff --git a/objc_sys/Cargo.toml b/objc_sys/Cargo.toml new file mode 100644 index 000000000..b383ec817 --- /dev/null +++ b/objc_sys/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "objc_sys" +version = "0.0.0" +authors = ["Mads Marquart "] +edition = "2018" + +description = "Bindings to the Objective-C core runtime" +keywords = ["objective-c", "macos", "ios", "objc_msgSend", "sys"] +categories = [ + "external-ffi-bindings", + "os::macos-apis", +] +repository = "https://github.com/madsmtm/objc" +documentation = "https://docs.rs/objc_sys/" +license = "MIT" diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs new file mode 100644 index 000000000..ad5d5e197 --- /dev/null +++ b/objc_sys/src/lib.rs @@ -0,0 +1,161 @@ +//! # Bindings to the Objective-C core runtime +#![no_std] +// Update in Cargo.toml as well. +#![doc(html_root_url = "https://docs.rs/objc-encode/1.1.0")] + +extern crate std; + +use core::ffi::c_void; +use std::os::raw::{c_char, c_int, c_uint}; + +/// The Objective-C `BOOL` type. +/// +/// To convert an Objective-C `BOOL` into a Rust [`bool`], compare it with [`NO`]. +#[cfg(all(target_vendor = "apple", not(target_arch = "aarch64")))] +pub type BOOL = i8; +#[cfg(all(not(target_vendor = "apple"), not(target_arch = "aarch64")))] +pub type BOOL = u8; +#[cfg(target_arch = "aarch64")] +pub type BOOL = bool; + +/// The equivalent of true for Objective-C's [`BOOL`] type. +#[cfg(not(target_arch = "aarch64"))] +pub const YES: BOOL = 1; +#[cfg(target_arch = "aarch64")] +pub const YES: BOOL = true; + +/// The equivalent of false for Objective-C's [`BOOL`] type. +#[cfg(not(target_arch = "aarch64"))] +pub const NO: BOOL = 0; +#[cfg(target_arch = "aarch64")] +pub const NO: BOOL = false; + +/// A type that represents a method selector. +#[repr(C)] +pub struct Sel { + _priv: [u8; 0], +} + +/// A type that represents an Objective-C class. +#[repr(C)] +pub struct Class { + _priv: [u8; 0], +} + +/// A type that represents an instance of a class. +#[repr(C)] +pub struct Object { + _priv: [u8; 0], +} + +/// A type that represents an instance variable. +#[repr(C)] +pub struct Ivar { + _priv: [u8; 0], +} + +/// A type that represents a method in a class definition. +#[repr(C)] +pub struct Method { + _priv: [u8; 0], +} + +/// A type that represents an Objective-C protocol. +#[repr(C)] +pub struct Protocol { + _priv: [u8; 0], +} + +/// A pointer to the start of a method implementation. +pub type Imp = unsafe extern "C" fn(); + +#[link(name = "objc", kind = "dylib")] +extern "C" { + 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: *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: *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; + pub fn class_copyProtocolList(cls: *const Class, outCount: *mut c_uint) + -> *mut *const Protocol; + + pub fn objc_allocateClassPair( + superclass: *const Class, + name: *const c_char, + extraBytes: usize, + ) -> *mut Class; + pub fn objc_disposeClassPair(cls: *mut Class); + pub fn objc_registerClassPair(cls: *mut Class); + + pub fn class_createInstance(cls: *const Class, extraBytes: usize) -> *mut Object; + pub fn object_dispose(obj: *mut Object) -> *mut Object; + pub fn object_getClass(obj: *const Object) -> *const Class; + + pub fn objc_getClassList(buffer: *mut *const Class, bufferLen: c_int) -> c_int; + pub fn objc_copyClassList(outCount: *mut c_uint) -> *mut *const Class; + pub fn objc_getClass(name: *const c_char) -> *const Class; + pub fn objc_getProtocol(name: *const c_char) -> *const Protocol; + pub fn objc_copyProtocolList(outCount: *mut c_uint) -> *mut *const Protocol; + pub fn objc_allocateProtocol(name: *const c_char) -> *mut Protocol; + pub fn objc_registerProtocol(proto: *mut Protocol); + + pub fn objc_autoreleasePoolPush() -> *mut c_void; + pub fn objc_autoreleasePoolPop(context: *mut c_void); + + 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; + pub fn protocol_isEqual(proto: *const Protocol, other: *const Protocol) -> BOOL; + pub fn protocol_copyProtocolList( + proto: *const Protocol, + outCount: *mut c_uint, + ) -> *mut *const Protocol; + pub fn protocol_conformsToProtocol(proto: *const Protocol, other: *const Protocol) -> BOOL; + + pub fn ivar_getName(ivar: *const Ivar) -> *const c_char; + 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) -> *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; + pub fn method_getNumberOfArguments(method: *const Method) -> c_uint; + pub fn method_setImplementation(method: *mut Method, imp: Imp) -> Imp; + pub fn method_exchangeImplementations(m1: *mut Method, m2: *mut Method); + + pub fn objc_retain(obj: *mut Object) -> *mut Object; + pub fn objc_release(obj: *mut Object); + pub fn objc_autorelease(obj: *mut Object); + + pub fn objc_loadWeakRetained(location: *mut *mut Object) -> *mut Object; + pub fn objc_initWeak(location: *mut *mut Object, obj: *mut Object) -> *mut Object; + pub fn objc_destroyWeak(location: *mut *mut Object); + pub fn objc_copyWeak(to: *mut *mut Object, from: *mut *mut Object); +} From 62cf446a0609598f4c91e2554375c4d7e7ab2005 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 01:54:22 +0200 Subject: [PATCH 02/36] sys: Rename types to match original header files and docs Types: - Imp -> IMP - Object -> objc_object - Sel -> objc_selector - Protocol -> objc_protocol - Class -> objc_class - Ivar -> objc_ivar - Method -> objc_method New type aliases: - id - SEL - Class - Ivar - Method - Protocol (alias of objc_protocol, not a pointer) --- objc/src/runtime.rs | 27 +++--- objc_sys/src/lib.rs | 203 ++++++++++++++++++++++++++++---------------- 2 files changed, 146 insertions(+), 84 deletions(-) diff --git a/objc/src/runtime.rs b/objc/src/runtime.rs index 51d5f039b..a8187c047 100644 --- a/objc/src/runtime.rs +++ b/objc/src/runtime.rs @@ -29,25 +29,25 @@ pub use objc_sys::{ protocol_addMethodDescription, protocol_addProtocol, protocol_conformsToProtocol, protocol_copyProtocolList, protocol_getName, protocol_isEqual, sel_getName, sel_registerName, }; -pub use objc_sys::{Imp, BOOL, NO, YES}; +pub use objc_sys::{BOOL, NO, YES}; /// A type that represents a method selector. #[repr(transparent)] pub struct Sel { - ptr: *const objc_sys::Sel, + ptr: *const objc_sys::objc_selector, } /// A type that represents an instance variable. #[repr(C)] -pub struct Ivar(objc_sys::Ivar); +pub struct Ivar(objc_sys::objc_ivar); /// A type that represents a method in a class definition. #[repr(C)] -pub struct Method(objc_sys::Method); +pub struct Method(objc_sys::objc_method); /// A type that represents an Objective-C class. #[repr(C)] -pub struct Class(objc_sys::Class); +pub struct Class(objc_sys::objc_class); /// A type that represents an Objective-C protocol. #[repr(C)] @@ -55,7 +55,10 @@ pub struct Protocol(objc_sys::Protocol); /// A type that represents an instance of a class. #[repr(C)] -pub struct Object(objc_sys::Object); +pub struct Object(objc_sys::objc_object); + +/// A pointer to the start of a method implementation. +pub type Imp = objc_sys::IMP; impl Sel { /// Registers a method with the Objective-C runtime system, @@ -83,7 +86,7 @@ impl Sel { #[inline] pub unsafe fn from_ptr(ptr: *const c_void) -> Self { Self { - ptr: ptr as *const objc_sys::Sel, + ptr: ptr as *const objc_sys::objc_selector, } } @@ -121,7 +124,7 @@ impl fmt::Debug for Sel { } impl Ivar { - pub(crate) fn as_ptr(&self) -> *const objc_sys::Ivar { + pub(crate) fn as_ptr(&self) -> *const objc_sys::objc_ivar { self as *const Self as *const _ } @@ -145,7 +148,7 @@ impl Ivar { } impl Method { - pub(crate) fn as_ptr(&self) -> *const objc_sys::Method { + pub(crate) fn as_ptr(&self) -> *const objc_sys::objc_method { self as *const Self as *const _ } @@ -189,7 +192,7 @@ impl Method { } impl Class { - pub(crate) fn as_ptr(&self) -> *const objc_sys::Class { + pub(crate) fn as_ptr(&self) -> *const objc_sys::objc_class { self as *const Self as *const _ } @@ -241,7 +244,7 @@ impl Class { /// Returns the metaclass of self. pub fn metaclass(&self) -> &Self { - unsafe { &*(object_getClass(self.as_ptr() as *const objc_sys::Object) as *const Self) } + unsafe { &*(object_getClass(self.as_ptr() as *const _) as *const Self) } } /// Returns the size of instances of self. @@ -398,7 +401,7 @@ fn get_ivar_offset(cls: &Class, name: &str) -> isize { } impl Object { - pub(crate) fn as_ptr(&self) -> *const objc_sys::Object { + pub(crate) fn as_ptr(&self) -> *const objc_sys::objc_object { self as *const Self as *const _ } diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index ad5d5e197..bf263ca6a 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -1,5 +1,14 @@ -//! # Bindings to the Objective-C core runtime +//! # Bindings to the objc_objective-C core runtime +//! +//! # Notable differences +//! +//! Protocol / objc_protocol is no longer a type alias of objc_object, for +//! better type safety. Their internal representation is the same, so the +//! functionality is just a cast away. + #![no_std] +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] // Update in Cargo.toml as well. #![doc(html_root_url = "https://docs.rs/objc-encode/1.1.0")] @@ -32,130 +41,180 @@ pub const NO: BOOL = false; /// A type that represents a method selector. #[repr(C)] -pub struct Sel { +pub struct objc_selector { _priv: [u8; 0], } /// A type that represents an Objective-C class. #[repr(C)] -pub struct Class { +pub struct objc_class { _priv: [u8; 0], } /// A type that represents an instance of a class. #[repr(C)] -pub struct Object { +pub struct objc_object { _priv: [u8; 0], } /// A type that represents an instance variable. #[repr(C)] -pub struct Ivar { +pub struct objc_ivar { _priv: [u8; 0], } /// A type that represents a method in a class definition. #[repr(C)] -pub struct Method { +pub struct objc_method { _priv: [u8; 0], } -/// A type that represents an Objective-C protocol. +/// Nonstandard naming, actually TODO ... #[repr(C)] -pub struct Protocol { +pub struct objc_protocol { _priv: [u8; 0], } +/// An immutable pointer to a selector. +/// +/// Type alias provided for convenience. +pub type SEL = *const objc_selector; + +/// A mutable pointer to a class. +/// +/// Type alias provided for convenience. +pub type Class = *mut objc_class; + +/// A mutable pointer to an object / instance. +/// +/// Type alias provided for convenience. +pub type id = *mut objc_object; + +/// An immutable pointer to an instance variable. +/// +/// Type alias provided for convenience. +pub type Ivar = *const objc_ivar; + +/// A mutable pointer to a method. +/// +/// Type alias provided for convenience. +pub type Method = *mut objc_method; + +/// An opaque type that represents a protocol. +/// +/// Type alias provided for convenience. +pub type Protocol = objc_protocol; + /// A pointer to the start of a method implementation. -pub type Imp = unsafe extern "C" fn(); +pub type IMP = unsafe extern "C" fn(); #[link(name = "objc", kind = "dylib")] extern "C" { - 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: *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 sel_registerName(name: *const c_char) -> *const objc_selector; + pub fn sel_getName(sel: *const objc_selector) -> *const c_char; + + pub fn class_getName(cls: *const objc_class) -> *const c_char; + pub fn class_getSuperclass(cls: *const objc_class) -> *const objc_class; + pub fn class_getInstanceSize(cls: *const objc_class) -> usize; + pub fn class_getInstanceMethod( + cls: *const objc_class, + sel: *const objc_selector, + ) -> *const objc_method; + pub fn class_getInstanceVariable( + cls: *const objc_class, + name: *const c_char, + ) -> *const objc_ivar; + pub fn class_copyMethodList( + cls: *const objc_class, + outCount: *mut c_uint, + ) -> *mut *const objc_method; + pub fn class_copyIvarList( + cls: *const objc_class, + outCount: *mut c_uint, + ) -> *mut *const objc_ivar; pub fn class_addMethod( - cls: *mut Class, - name: *const Sel, - imp: Imp, + cls: *mut objc_class, + name: *const objc_selector, + imp: IMP, types: *const c_char, ) -> BOOL; pub fn class_addIvar( - cls: *mut Class, + cls: *mut objc_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; - pub fn class_copyProtocolList(cls: *const Class, outCount: *mut c_uint) - -> *mut *const Protocol; + pub fn class_addProtocol(cls: *mut objc_class, proto: *const objc_protocol) -> BOOL; + pub fn class_conformsToProtocol(cls: *const objc_class, proto: *const objc_protocol) -> BOOL; + pub fn class_copyProtocolList( + cls: *const objc_class, + outCount: *mut c_uint, + ) -> *mut *const objc_protocol; pub fn objc_allocateClassPair( - superclass: *const Class, + superclass: *const objc_class, name: *const c_char, extraBytes: usize, - ) -> *mut Class; - pub fn objc_disposeClassPair(cls: *mut Class); - pub fn objc_registerClassPair(cls: *mut Class); - - pub fn class_createInstance(cls: *const Class, extraBytes: usize) -> *mut Object; - pub fn object_dispose(obj: *mut Object) -> *mut Object; - pub fn object_getClass(obj: *const Object) -> *const Class; - - pub fn objc_getClassList(buffer: *mut *const Class, bufferLen: c_int) -> c_int; - pub fn objc_copyClassList(outCount: *mut c_uint) -> *mut *const Class; - pub fn objc_getClass(name: *const c_char) -> *const Class; - pub fn objc_getProtocol(name: *const c_char) -> *const Protocol; - pub fn objc_copyProtocolList(outCount: *mut c_uint) -> *mut *const Protocol; - pub fn objc_allocateProtocol(name: *const c_char) -> *mut Protocol; - pub fn objc_registerProtocol(proto: *mut Protocol); + ) -> *mut objc_class; + pub fn objc_disposeClassPair(cls: *mut objc_class); + pub fn objc_registerClassPair(cls: *mut objc_class); + + pub fn class_createInstance(cls: *const objc_class, extraBytes: usize) -> *mut objc_object; + pub fn object_dispose(obj: *mut objc_object) -> *mut objc_object; + pub fn object_getClass(obj: *const objc_object) -> *const objc_class; + + pub fn objc_getClassList(buffer: *mut *const objc_class, bufferLen: c_int) -> c_int; + pub fn objc_copyClassList(outCount: *mut c_uint) -> *mut *const objc_class; + pub fn objc_getClass(name: *const c_char) -> *const objc_class; + pub fn objc_getProtocol(name: *const c_char) -> *const objc_protocol; + pub fn objc_copyProtocolList(outCount: *mut c_uint) -> *mut *const objc_protocol; + pub fn objc_allocateProtocol(name: *const c_char) -> *mut objc_protocol; + pub fn objc_registerProtocol(proto: *mut objc_protocol); pub fn objc_autoreleasePoolPush() -> *mut c_void; pub fn objc_autoreleasePoolPop(context: *mut c_void); pub fn protocol_addMethodDescription( - proto: *mut Protocol, - name: *const Sel, + proto: *mut objc_protocol, + name: *const objc_selector, 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; - pub fn protocol_isEqual(proto: *const Protocol, other: *const Protocol) -> BOOL; + pub fn protocol_addProtocol(proto: *mut objc_protocol, addition: *const objc_protocol); + pub fn protocol_getName(proto: *const objc_protocol) -> *const c_char; + pub fn protocol_isEqual(proto: *const objc_protocol, other: *const objc_protocol) -> BOOL; pub fn protocol_copyProtocolList( - proto: *const Protocol, + proto: *const objc_protocol, outCount: *mut c_uint, - ) -> *mut *const Protocol; - pub fn protocol_conformsToProtocol(proto: *const Protocol, other: *const Protocol) -> BOOL; - - pub fn ivar_getName(ivar: *const Ivar) -> *const c_char; - 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) -> *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; - pub fn method_getNumberOfArguments(method: *const Method) -> c_uint; - pub fn method_setImplementation(method: *mut Method, imp: Imp) -> Imp; - pub fn method_exchangeImplementations(m1: *mut Method, m2: *mut Method); - - pub fn objc_retain(obj: *mut Object) -> *mut Object; - pub fn objc_release(obj: *mut Object); - pub fn objc_autorelease(obj: *mut Object); - - pub fn objc_loadWeakRetained(location: *mut *mut Object) -> *mut Object; - pub fn objc_initWeak(location: *mut *mut Object, obj: *mut Object) -> *mut Object; - pub fn objc_destroyWeak(location: *mut *mut Object); - pub fn objc_copyWeak(to: *mut *mut Object, from: *mut *mut Object); + ) -> *mut *const objc_protocol; + pub fn protocol_conformsToProtocol( + proto: *const objc_protocol, + other: *const objc_protocol, + ) -> BOOL; + + pub fn ivar_getName(ivar: *const objc_ivar) -> *const c_char; + pub fn ivar_getOffset(ivar: *const objc_ivar) -> isize; + pub fn ivar_getTypeEncoding(ivar: *const objc_ivar) -> *const c_char; + + pub fn method_getName(method: *const objc_method) -> *const objc_selector; + pub fn method_getImplementation(method: *const objc_method) -> IMP; + pub fn method_copyReturnType(method: *const objc_method) -> *mut c_char; + pub fn method_copyArgumentType(method: *const objc_method, index: c_uint) -> *mut c_char; + pub fn method_getNumberOfArguments(method: *const objc_method) -> c_uint; + pub fn method_setImplementation(method: *mut objc_method, imp: IMP) -> IMP; + pub fn method_exchangeImplementations(m1: *mut objc_method, m2: *mut objc_method); + + pub fn objc_retain(obj: *mut objc_object) -> *mut objc_object; + pub fn objc_release(obj: *mut objc_object); + pub fn objc_autorelease(obj: *mut objc_object); + + pub fn objc_loadWeakRetained(location: *mut *mut objc_object) -> *mut objc_object; + pub fn objc_initWeak( + location: *mut *mut objc_object, + obj: *mut objc_object, + ) -> *mut objc_object; + pub fn objc_destroyWeak(location: *mut *mut objc_object); + pub fn objc_copyWeak(to: *mut *mut objc_object, from: *mut *mut objc_object); } From b80be65f57dbeff94dd7359e7d84cbb2da1a0d56 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 01:38:18 +0200 Subject: [PATCH 03/36] sys: Move types to their own file --- objc_sys/src/lib.rs | 93 +----------------------------------------- objc_sys/src/types.rs | 95 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 91 deletions(-) create mode 100644 objc_sys/src/types.rs diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index bf263ca6a..5f133635c 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -7,8 +7,6 @@ //! functionality is just a cast away. #![no_std] -#![allow(non_camel_case_types)] -#![allow(non_upper_case_globals)] // Update in Cargo.toml as well. #![doc(html_root_url = "https://docs.rs/objc-encode/1.1.0")] @@ -17,96 +15,9 @@ extern crate std; use core::ffi::c_void; use std::os::raw::{c_char, c_int, c_uint}; -/// The Objective-C `BOOL` type. -/// -/// To convert an Objective-C `BOOL` into a Rust [`bool`], compare it with [`NO`]. -#[cfg(all(target_vendor = "apple", not(target_arch = "aarch64")))] -pub type BOOL = i8; -#[cfg(all(not(target_vendor = "apple"), not(target_arch = "aarch64")))] -pub type BOOL = u8; -#[cfg(target_arch = "aarch64")] -pub type BOOL = bool; - -/// The equivalent of true for Objective-C's [`BOOL`] type. -#[cfg(not(target_arch = "aarch64"))] -pub const YES: BOOL = 1; -#[cfg(target_arch = "aarch64")] -pub const YES: BOOL = true; - -/// The equivalent of false for Objective-C's [`BOOL`] type. -#[cfg(not(target_arch = "aarch64"))] -pub const NO: BOOL = 0; -#[cfg(target_arch = "aarch64")] -pub const NO: BOOL = false; - -/// A type that represents a method selector. -#[repr(C)] -pub struct objc_selector { - _priv: [u8; 0], -} - -/// A type that represents an Objective-C class. -#[repr(C)] -pub struct objc_class { - _priv: [u8; 0], -} - -/// A type that represents an instance of a class. -#[repr(C)] -pub struct objc_object { - _priv: [u8; 0], -} - -/// A type that represents an instance variable. -#[repr(C)] -pub struct objc_ivar { - _priv: [u8; 0], -} - -/// A type that represents a method in a class definition. -#[repr(C)] -pub struct objc_method { - _priv: [u8; 0], -} - -/// Nonstandard naming, actually TODO ... -#[repr(C)] -pub struct objc_protocol { - _priv: [u8; 0], -} +mod types; -/// An immutable pointer to a selector. -/// -/// Type alias provided for convenience. -pub type SEL = *const objc_selector; - -/// A mutable pointer to a class. -/// -/// Type alias provided for convenience. -pub type Class = *mut objc_class; - -/// A mutable pointer to an object / instance. -/// -/// Type alias provided for convenience. -pub type id = *mut objc_object; - -/// An immutable pointer to an instance variable. -/// -/// Type alias provided for convenience. -pub type Ivar = *const objc_ivar; - -/// A mutable pointer to a method. -/// -/// Type alias provided for convenience. -pub type Method = *mut objc_method; - -/// An opaque type that represents a protocol. -/// -/// Type alias provided for convenience. -pub type Protocol = objc_protocol; - -/// A pointer to the start of a method implementation. -pub type IMP = unsafe extern "C" fn(); +pub use types::*; #[link(name = "objc", kind = "dylib")] extern "C" { diff --git a/objc_sys/src/types.rs b/objc_sys/src/types.rs new file mode 100644 index 000000000..7ce4d650e --- /dev/null +++ b/objc_sys/src/types.rs @@ -0,0 +1,95 @@ +#![allow(non_camel_case_types)] + +/// The Objective-C `BOOL` type. +/// +/// To convert an Objective-C `BOOL` into a Rust [`bool`], compare it with [`NO`]. +#[cfg(all(target_vendor = "apple", not(target_arch = "aarch64")))] +pub type BOOL = i8; +#[cfg(all(not(target_vendor = "apple"), not(target_arch = "aarch64")))] +pub type BOOL = u8; +#[cfg(target_arch = "aarch64")] +pub type BOOL = bool; + +/// The equivalent of true for Objective-C's [`BOOL`] type. +#[cfg(not(target_arch = "aarch64"))] +pub const YES: BOOL = 1; +#[cfg(target_arch = "aarch64")] +pub const YES: BOOL = true; + +/// The equivalent of false for Objective-C's [`BOOL`] type. +#[cfg(not(target_arch = "aarch64"))] +pub const NO: BOOL = 0; +#[cfg(target_arch = "aarch64")] +pub const NO: BOOL = false; + +/// A type that represents a method selector. +#[repr(C)] +pub struct objc_selector { + _priv: [u8; 0], +} + +/// A type that represents an Objective-C class. +#[repr(C)] +pub struct objc_class { + _priv: [u8; 0], +} + +/// A type that represents an instance of a class. +#[repr(C)] +pub struct objc_object { + _priv: [u8; 0], +} + +/// A type that represents an instance variable. +#[repr(C)] +pub struct objc_ivar { + _priv: [u8; 0], +} + +/// A type that represents a method in a class definition. +#[repr(C)] +pub struct objc_method { + _priv: [u8; 0], +} + +/// Nonstandard naming, actually TODO ... +#[repr(C)] +pub struct objc_protocol { + _priv: [u8; 0], +} + +/// An immutable pointer to a selector. +/// +/// Type alias provided for convenience. +pub type SEL = *const objc_selector; + +/// A mutable pointer to a class. +/// +/// Type alias provided for convenience. +pub type Class = *mut objc_class; + +/// A mutable pointer to an object / instance. +/// +/// Type alias provided for convenience. +pub type id = *mut objc_object; + +/// An immutable pointer to an instance variable. +/// +/// Type alias provided for convenience. +pub type Ivar = *const objc_ivar; + +/// A mutable pointer to a method. +/// +/// Type alias provided for convenience. +pub type Method = *mut objc_method; + +/// An opaque type that represents a protocol. +/// +/// Type alias provided for convenience. +pub type Protocol = objc_protocol; + +/// A pointer to the start of a method implementation. +/// +/// Remember that this is non-null! +/// Use `Option` where nullability is expected. +pub type IMP = unsafe extern "C" fn(); From 9e64aeb1a495256a600b8e16706106dd0a052433 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 02:14:18 +0200 Subject: [PATCH 04/36] sys: Add more types --- objc_sys/src/types.rs | 50 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/objc_sys/src/types.rs b/objc_sys/src/types.rs index 7ce4d650e..a6e93576a 100644 --- a/objc_sys/src/types.rs +++ b/objc_sys/src/types.rs @@ -1,5 +1,10 @@ +//! Objective-C types and type aliases. #![allow(non_camel_case_types)] +#[cfg(target_os = "macos")] +use core::ffi::c_void; +use std::os::raw::{c_char, c_int}; + /// The Objective-C `BOOL` type. /// /// To convert an Objective-C `BOOL` into a Rust [`bool`], compare it with [`NO`]. @@ -28,13 +33,13 @@ pub struct objc_selector { _priv: [u8; 0], } -/// A type that represents an Objective-C class. +/// An opaque type that represents an Objective-C class. #[repr(C)] pub struct objc_class { _priv: [u8; 0], } -/// A type that represents an instance of a class. +/// An opaque type that represents an instance of a class. #[repr(C)] pub struct objc_object { _priv: [u8; 0], @@ -52,12 +57,44 @@ pub struct objc_method { _priv: [u8; 0], } -/// Nonstandard naming, actually TODO ... +/// Nonstandard naming, actually... (TODO) #[repr(C)] pub struct objc_protocol { _priv: [u8; 0], } +#[repr(C)] +pub struct objc_property { + _priv: [u8; 0], +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_method_description { + pub name: *const objc_selector, + pub types: *mut c_char, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_property_attribute_t { + pub name: *const c_char, + pub value: *const c_char, +} + +/// Remember that this is non-null! +pub type objc_exception_preprocessor = unsafe extern "C" fn(exception: id) -> id; + +/// Remember that this is non-null! +pub type objc_exception_matcher = unsafe extern "C" fn(catch_type: Class, exception: id) -> c_int; + +/// Remember that this is non-null! +pub type objc_uncaught_exception_handler = unsafe extern "C" fn(exception: id); + +/// Remember that this is non-null! +#[cfg(target_os = "macos")] +pub type objc_exception_handler = unsafe extern "C" fn(unused: id, context: *mut c_void); + /// An immutable pointer to a selector. /// /// Type alias provided for convenience. @@ -88,8 +125,13 @@ pub type Method = *mut objc_method; /// Type alias provided for convenience. pub type Protocol = objc_protocol; +/// A mutable pointer to a property. +/// +/// Type alias provided for convenience. +pub type objc_property_t = *mut objc_property; + /// A pointer to the start of a method implementation. /// /// Remember that this is non-null! -/// Use `Option` where nullability is expected. +/// Use `Option` where nullability is expected. TODO pub type IMP = unsafe extern "C" fn(); From 915d582d4f3439ce590dc6aad8c347d2c80eabfa Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 02:03:26 +0200 Subject: [PATCH 05/36] sys: Mark opaque types as !Send, !Sync, !Unpin and so on --- objc_sys/src/types.rs | 47 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/objc_sys/src/types.rs b/objc_sys/src/types.rs index a6e93576a..415fc4391 100644 --- a/objc_sys/src/types.rs +++ b/objc_sys/src/types.rs @@ -1,20 +1,12 @@ //! Objective-C types and type aliases. #![allow(non_camel_case_types)] +use core::cell::UnsafeCell; #[cfg(target_os = "macos")] use core::ffi::c_void; +use core::marker::{PhantomData, PhantomPinned}; use std::os::raw::{c_char, c_int}; -/// The Objective-C `BOOL` type. -/// -/// To convert an Objective-C `BOOL` into a Rust [`bool`], compare it with [`NO`]. -#[cfg(all(target_vendor = "apple", not(target_arch = "aarch64")))] -pub type BOOL = i8; -#[cfg(all(not(target_vendor = "apple"), not(target_arch = "aarch64")))] -pub type BOOL = u8; -#[cfg(target_arch = "aarch64")] -pub type BOOL = bool; - /// The equivalent of true for Objective-C's [`BOOL`] type. #[cfg(not(target_arch = "aarch64"))] pub const YES: BOOL = 1; @@ -27,47 +19,70 @@ pub const NO: BOOL = 0; #[cfg(target_arch = "aarch64")] pub const NO: BOOL = false; +// Opaque types + +/// We don't know much about the actual structs, so better mark them `!Send`, +/// `!Sync`, `!Unpin` and as mutable behind shared references. Downstream +/// libraries can always manually opt in to these types afterwards. (It's +/// also less of a breaking change on our part if we re-add these later). +/// +/// TODO: Replace this with `extern type` to also mark it as unsized. +type OpaqueData = PhantomData<(UnsafeCell<*const ()>, PhantomPinned)>; + /// A type that represents a method selector. #[repr(C)] pub struct objc_selector { _priv: [u8; 0], + _p: OpaqueData, } /// An opaque type that represents an Objective-C class. #[repr(C)] pub struct objc_class { + // `isa` field is deprecated, so we don't expose it here. + // Use `class_getSuperclass` instead. _priv: [u8; 0], + _p: OpaqueData, } /// An opaque type that represents an instance of a class. #[repr(C)] pub struct objc_object { + // `isa` field is deprecated, so we don't expose it here. + // Use `object_getClass` instead. _priv: [u8; 0], + _p: OpaqueData, } /// A type that represents an instance variable. #[repr(C)] pub struct objc_ivar { _priv: [u8; 0], + _p: OpaqueData, } /// A type that represents a method in a class definition. #[repr(C)] pub struct objc_method { _priv: [u8; 0], + _p: OpaqueData, } /// Nonstandard naming, actually... (TODO) #[repr(C)] pub struct objc_protocol { _priv: [u8; 0], + _p: OpaqueData, } #[repr(C)] pub struct objc_property { _priv: [u8; 0], + _p: OpaqueData, } +// Data-carrying structs + #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct objc_method_description { @@ -82,6 +97,18 @@ pub struct objc_property_attribute_t { pub value: *const c_char, } +// Type aliases + +/// The Objective-C `BOOL` type. +/// +/// To convert an Objective-C `BOOL` into a Rust [`bool`], compare it with [`NO`]. +#[cfg(all(target_vendor = "apple", not(target_arch = "aarch64")))] +pub type BOOL = i8; +#[cfg(all(not(target_vendor = "apple"), not(target_arch = "aarch64")))] +pub type BOOL = u8; +#[cfg(target_arch = "aarch64")] +pub type BOOL = bool; + /// Remember that this is non-null! pub type objc_exception_preprocessor = unsafe extern "C" fn(exception: id) -> id; From 7d5ad7d6b2f48df6ea2bc24285aa20c1cfdeb283 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 02:13:54 +0200 Subject: [PATCH 06/36] sys: Add various constants (nil, Nil and OBJC_X defines) --- objc_sys/src/constants.rs | 40 +++++++++++++++++++++++++++++++++++++++ objc_sys/src/lib.rs | 2 ++ objc_sys/src/types.rs | 15 ++------------- 3 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 objc_sys/src/constants.rs diff --git a/objc_sys/src/constants.rs b/objc_sys/src/constants.rs new file mode 100644 index 000000000..f6dab68f3 --- /dev/null +++ b/objc_sys/src/constants.rs @@ -0,0 +1,40 @@ +//! Various common #defines and enum constants. + +use std::os::raw::c_int; + +use super::{id, Class, BOOL}; + +/// The equivalent of true for Objective-C's [`BOOL`][`super::BOOL`] type. +#[cfg(not(target_arch = "aarch64"))] +pub const YES: BOOL = 1; +#[cfg(target_arch = "aarch64")] +pub const YES: BOOL = true; + +/// The equivalent of false for Objective-C's [`BOOL`][`super::BOOL`] type. +#[cfg(not(target_arch = "aarch64"))] +pub const NO: BOOL = 0; +#[cfg(target_arch = "aarch64")] +pub const NO: BOOL = false; + +/// A quick alias for a [`null_mut`][`core::ptr::null_mut`] object / instance. +#[allow(non_upper_case_globals)] +pub const nil: id = 0 as *mut _; + +/// A quick alias for a [`null_mut`][`core::ptr::null_mut`] class. +#[allow(non_upper_case_globals)] +pub const Nil: Class = 0 as *mut _; + +#[allow(non_camel_case_types)] +pub type objc_AssociationPolicy = usize; +pub const OBJC_ASSOCIATION_ASSIGN: objc_AssociationPolicy = 0; +pub const OBJC_ASSOCIATION_RETAIN_NONATOMIC: objc_AssociationPolicy = 1; +pub const OBJC_ASSOCIATION_COPY_NONATOMIC: objc_AssociationPolicy = 3; +pub const OBJC_ASSOCIATION_RETAIN: objc_AssociationPolicy = 769; +pub const OBJC_ASSOCIATION_COPY: objc_AssociationPolicy = 771; + +pub const OBJC_SYNC_SUCCESS: c_int = 0; +pub const OBJC_SYNC_NOT_OWNING_THREAD_ERROR: c_int = -1; +/// Only relevant before macOS 10.13 +pub const OBJC_SYNC_TIMED_OUT: c_int = -2; +/// Only relevant before macOS 10.13 +pub const OBJC_SYNC_NOT_INITIALIZED: c_int = -3; diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index 5f133635c..0f87a93e0 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -15,8 +15,10 @@ extern crate std; use core::ffi::c_void; use std::os::raw::{c_char, c_int, c_uint}; +mod constants; mod types; +pub use constants::*; pub use types::*; #[link(name = "objc", kind = "dylib")] diff --git a/objc_sys/src/types.rs b/objc_sys/src/types.rs index 415fc4391..e79ff03cc 100644 --- a/objc_sys/src/types.rs +++ b/objc_sys/src/types.rs @@ -7,18 +7,6 @@ use core::ffi::c_void; use core::marker::{PhantomData, PhantomPinned}; use std::os::raw::{c_char, c_int}; -/// The equivalent of true for Objective-C's [`BOOL`] type. -#[cfg(not(target_arch = "aarch64"))] -pub const YES: BOOL = 1; -#[cfg(target_arch = "aarch64")] -pub const YES: BOOL = true; - -/// The equivalent of false for Objective-C's [`BOOL`] type. -#[cfg(not(target_arch = "aarch64"))] -pub const NO: BOOL = 0; -#[cfg(target_arch = "aarch64")] -pub const NO: BOOL = false; - // Opaque types /// We don't know much about the actual structs, so better mark them `!Send`, @@ -101,7 +89,8 @@ pub struct objc_property_attribute_t { /// The Objective-C `BOOL` type. /// -/// To convert an Objective-C `BOOL` into a Rust [`bool`], compare it with [`NO`]. +/// To convert an Objective-C `BOOL` into a Rust [`bool`], compare it with +/// [`NO`][`super::NO`]. #[cfg(all(target_vendor = "apple", not(target_arch = "aarch64")))] pub type BOOL = i8; #[cfg(all(not(target_vendor = "apple"), not(target_arch = "aarch64")))] From 316cf28b6649abf9fafbc97972a3dbae902898d5 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 15:36:59 +0200 Subject: [PATCH 07/36] sys: Add the `objc_msgSend` familiy of functions. --- objc/src/message/apple/arm.rs | 10 +------ objc/src/message/apple/arm64.rs | 9 ++---- objc/src/message/apple/mod.rs | 12 ++++---- objc/src/message/apple/x86.rs | 14 +++------ objc/src/message/apple/x86_64.rs | 11 ++----- objc/src/message/gnustep.rs | 11 +++---- objc/src/message/mod.rs | 9 ------ objc_block/src/lib.rs | 5 +--- objc_sys/src/constants.rs | 3 -- objc_sys/src/lib.rs | 8 +++++- objc_sys/src/message.rs | 49 ++++++++++++++++++++++++++++++++ objc_sys/src/types.rs | 1 - 12 files changed, 79 insertions(+), 63 deletions(-) create mode 100644 objc_sys/src/message.rs diff --git a/objc/src/message/apple/arm.rs b/objc/src/message/apple/arm.rs index c7ec6345d..370d7453a 100644 --- a/objc/src/message/apple/arm.rs +++ b/objc/src/message/apple/arm.rs @@ -1,18 +1,10 @@ use core::mem; +use objc_sys::{objc_msgSend, objc_msgSendSuper, objc_msgSendSuper_stret, objc_msgSend_stret}; use super::MsgSendFn; use crate::runtime::Imp; use crate::{Encode, Encoding}; -// TODO: C-unwind -extern "C" { - fn objc_msgSend(); - fn objc_msgSend_stret(); - - fn objc_msgSendSuper(); - fn objc_msgSendSuper_stret(); -} - /// Double-word sized fundamental data types don't use stret, but any /// composite type larger than 4 bytes does. /// diff --git a/objc/src/message/apple/arm64.rs b/objc/src/message/apple/arm64.rs index a8be08411..bd83d2d26 100644 --- a/objc/src/message/apple/arm64.rs +++ b/objc/src/message/apple/arm64.rs @@ -1,14 +1,9 @@ +use objc_sys::{objc_msgSend, objc_msgSendSuper}; + use super::MsgSendFn; use crate::runtime::Imp; use crate::Encode; -// TODO: C-unwind -extern "C" { - fn objc_msgSend(); - - fn objc_msgSendSuper(); -} - /// `objc_msgSend_stret` is not even available in arm64. /// /// diff --git a/objc/src/message/apple/mod.rs b/objc/src/message/apple/mod.rs index c0b7c1ced..792ef0659 100644 --- a/objc/src/message/apple/mod.rs +++ b/objc/src/message/apple/mod.rs @@ -1,4 +1,6 @@ -use super::{Encode, Message, MessageArguments, MessageError, Super}; +use objc_sys::objc_super; + +use super::{Encode, Message, MessageArguments, MessageError}; use crate::runtime::{Class, Imp, Object, Sel}; #[cfg(target_arch = "x86")] @@ -43,11 +45,11 @@ where A: MessageArguments, R: Encode, { - let sup = Super { - receiver: obj as *mut T as *mut Object, - superclass, + let sup = objc_super { + receiver: obj as *mut T as *mut Object as *mut _, + super_class: superclass as *const Class as *const _, }; - let receiver = &sup as *const Super as *mut Object; + 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) }) } diff --git a/objc/src/message/apple/x86.rs b/objc/src/message/apple/x86.rs index 3444863c0..9398acddf 100644 --- a/objc/src/message/apple/x86.rs +++ b/objc/src/message/apple/x86.rs @@ -1,19 +1,13 @@ use core::mem; +use objc_sys::{ + objc_msgSend, objc_msgSendSuper, objc_msgSendSuper_stret, objc_msgSend_fpret, + objc_msgSend_stret, +}; use super::MsgSendFn; use crate::runtime::Imp; use crate::{Encode, Encoding}; -// TODO: C-unwind -extern "C" { - fn objc_msgSend(); - fn objc_msgSend_fpret(); - fn objc_msgSend_stret(); - - fn objc_msgSendSuper(); - fn objc_msgSendSuper_stret(); -} - /// Structures 1 or 2 bytes in size are placed in EAX. /// Structures 4 or 8 bytes in size are placed in: EAX and EDX. /// Structures of other sizes are placed at the address supplied by the caller. diff --git a/objc/src/message/apple/x86_64.rs b/objc/src/message/apple/x86_64.rs index b8f333d89..fec88daa3 100644 --- a/objc/src/message/apple/x86_64.rs +++ b/objc/src/message/apple/x86_64.rs @@ -1,24 +1,17 @@ use core::mem; +use objc_sys::{objc_msgSend, objc_msgSendSuper, objc_msgSendSuper_stret, objc_msgSend_stret}; use super::MsgSendFn; use crate::runtime::Imp; use crate::Encode; -// TODO: C-unwind -extern "C" { - fn objc_msgSend(); - fn objc_msgSend_stret(); - - fn objc_msgSendSuper(); - fn objc_msgSendSuper_stret(); -} - /// If the size of an object is larger than two eightbytes, it has class /// MEMORY. If the type has class MEMORY, then the caller provides space for /// the return value and passes the address of this storage. /// /// impl MsgSendFn for T { + // TODO: Should we use objc_msgSend_fpret and objc_msgSend_fp2ret ? const MSG_SEND: Imp = { if mem::size_of::() <= 16 { objc_msgSend diff --git a/objc/src/message/gnustep.rs b/objc/src/message/gnustep.rs index fb901cb54..e20b31595 100644 --- a/objc/src/message/gnustep.rs +++ b/objc/src/message/gnustep.rs @@ -1,11 +1,12 @@ use core::mem; +use objc_sys::objc_super; -use super::{Encode, Message, MessageArguments, MessageError, Super}; +use super::{Encode, Message, MessageArguments, MessageError}; use crate::runtime::{Class, Imp, Object, Sel}; extern "C" { 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_super(sup: *const objc_super, sel: Sel) -> Imp; } pub unsafe fn send_unverified(obj: *const T, sel: Sel, args: A) -> Result @@ -35,9 +36,9 @@ where R: Encode, { let receiver = obj as *mut T as *mut Object; - let sup = Super { - receiver: receiver, - superclass: superclass, + 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); objc_try!({ A::invoke(msg_send_fn, receiver, sel, args) }) diff --git a/objc/src/message/mod.rs b/objc/src/message/mod.rs index 8a54f7b86..30e022a81 100644 --- a/objc/src/message/mod.rs +++ b/objc/src/message/mod.rs @@ -39,15 +39,6 @@ mod platform; use self::platform::{send_super_unverified, send_unverified}; use self::verify::{verify_message_signature, VerificationError}; -/// Specifies the superclass of an instance. -#[repr(C)] -struct Super { - /// Specifies an instance of a class. - pub receiver: *mut Object, - /// Specifies the particular superclass of the instance to message. - pub superclass: *const Class, -} - /// This trait marks types that can be sent Objective-C messages. /// /// Examples include objects, classes, and blocks. diff --git a/objc_block/src/lib.rs b/objc_block/src/lib.rs index 5a32810e6..7d71eaa03 100644 --- a/objc_block/src/lib.rs +++ b/objc_block/src/lib.rs @@ -69,10 +69,7 @@ struct ClassInternal { _priv: [u8; 0], } -#[cfg_attr( - target_vendor = "apple", - link(name = "System", kind = "dylib") -)] +#[cfg_attr(target_vendor = "apple", link(name = "System", kind = "dylib"))] #[cfg_attr( not(target_vendor = "apple"), link(name = "BlocksRuntime", kind = "dylib") diff --git a/objc_sys/src/constants.rs b/objc_sys/src/constants.rs index f6dab68f3..1dafc423d 100644 --- a/objc_sys/src/constants.rs +++ b/objc_sys/src/constants.rs @@ -17,14 +17,11 @@ pub const NO: BOOL = 0; pub const NO: BOOL = false; /// A quick alias for a [`null_mut`][`core::ptr::null_mut`] object / instance. -#[allow(non_upper_case_globals)] pub const nil: id = 0 as *mut _; /// A quick alias for a [`null_mut`][`core::ptr::null_mut`] class. -#[allow(non_upper_case_globals)] pub const Nil: Class = 0 as *mut _; -#[allow(non_camel_case_types)] pub type objc_AssociationPolicy = usize; pub const OBJC_ASSOCIATION_ASSIGN: objc_AssociationPolicy = 0; pub const OBJC_ASSOCIATION_RETAIN_NONATOMIC: objc_AssociationPolicy = 1; diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index 0f87a93e0..bdf14299a 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -6,9 +6,13 @@ //! better type safety. Their internal representation is the same, so the //! functionality is just a cast away. +// TODO: Replace `extern "C"` with `extern "C-unwind"`. + #![no_std] +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] // Update in Cargo.toml as well. -#![doc(html_root_url = "https://docs.rs/objc-encode/1.1.0")] +#![doc(html_root_url = "https://docs.rs/objc_sys/1.1.0")] extern crate std; @@ -16,9 +20,11 @@ use core::ffi::c_void; use std::os::raw::{c_char, c_int, c_uint}; mod constants; +mod message; mod types; pub use constants::*; +pub use message::*; pub use types::*; #[link(name = "objc", kind = "dylib")] diff --git a/objc_sys/src/message.rs b/objc_sys/src/message.rs new file mode 100644 index 000000000..15466a22b --- /dev/null +++ b/objc_sys/src/message.rs @@ -0,0 +1,49 @@ +//! The `objc_msgSend` familiy of functions. +//! +//! Most of these are `cfg`-gated, these configs are semver-stable. +use super::{objc_class, objc_object}; + +/// Specifies data used when sending messages to superclasses. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +// TODO: Does this belong in this file or in types.rs? +pub struct objc_super { + /// The object / instance to send a message to. + pub receiver: *mut objc_object, + /// The particular superclass of the instance to message. + pub super_class: *const objc_class, +} + +extern "C" { + pub fn objc_msgSend(); + pub fn objc_msgSendSuper(); + pub fn method_invoke(); + pub fn _objc_msgForward(); + pub fn class_getMethodImplementation(); +} + +#[cfg(not(target_arch = "aarch64"))] // __arm64__ +extern "C" { + /// Not available on `target_arch = "aarch64"` + pub fn objc_msgSend_stret(); + /// Not available on `target_arch = "aarch64"` + pub fn objc_msgSendSuper_stret(); + /// Not available on `target_arch = "aarch64"` + pub fn method_invoke_stret(); + /// Not available on `target_arch = "aarch64"` + pub fn _objc_msgForward_stret(); + /// Not available on `target_arch = "aarch64"` + pub fn class_getMethodImplementation_stret(); +} + +#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] // __x86_64__ and __i386__ +extern "C" { + /// Only available on `target_arch = "x86_64"` or `target_arch = "x86"` + pub fn objc_msgSend_fpret(); +} + +#[cfg(target_arch = "x86_64")] // __x86_64__ +extern "C" { + /// Only available on `target_arch = "x86_64"` + pub fn objc_msgSend_fp2ret(); +} diff --git a/objc_sys/src/types.rs b/objc_sys/src/types.rs index e79ff03cc..888f97244 100644 --- a/objc_sys/src/types.rs +++ b/objc_sys/src/types.rs @@ -1,5 +1,4 @@ //! Objective-C types and type aliases. -#![allow(non_camel_case_types)] use core::cell::UnsafeCell; #[cfg(target_os = "macos")] From 254a6ed950d507bdff532b954af89c6a909ac683 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 03:14:02 +0200 Subject: [PATCH 08/36] sys: Add helper scripts to generate function bindings to libobjc --- objc_sys/helper-scripts/gen-git.fish | 236 +++++++++++++++++++++++++++ objc_sys/helper-scripts/headers.h | 33 ++++ 2 files changed, 269 insertions(+) create mode 100755 objc_sys/helper-scripts/gen-git.fish create mode 100644 objc_sys/helper-scripts/headers.h diff --git a/objc_sys/helper-scripts/gen-git.fish b/objc_sys/helper-scripts/gen-git.fish new file mode 100755 index 000000000..1f64b28f1 --- /dev/null +++ b/objc_sys/helper-scripts/gen-git.fish @@ -0,0 +1,236 @@ +#!/usr/local/bin/fish + +# Yup, this is terrible, but was a great help in creating the correct implementations + +# Source repo should be a path to https://github.com/madsmtm/objc4.git +set source_repo $argv[1] +set to_repo $argv[2] + +git init $to_repo -b master + +cp headers.h $source_repo/runtime/headers.h + +set tags \ + # For these, headers.h needs to be set up differently + # macos-10.0 \ + # macos-10.1 \ + # macos-10.2 \ + # macos-10.3 \ + # macos-10.3.3 \ + # macos-10.4 \ + # macos-10.4.3 \ + # macos-10.4.4.x86 \ + # macos-10.4.6.ppc \ + macos-10.5 \ + macos-10.5.2 \ + macos-10.5.5 \ + macos-10.6 \ + macos-10.6.2 \ + macos-10.6.8 \ + # The actual minimum target we're interested in + macos-10.7 \ + macos-10.7.3 \ + macos-10.8 \ + macos-10.8.2 \ + macos-10.9 \ + macos-10.10 \ + macos-10.10.2 \ + macos-10.11 \ + macos-10.12 \ + macos-10.12.4 \ + macos-10.12.6 \ + macos-10.13 \ + macos-10.14 \ + macos-10.14.1 \ + macos-10.14.4 \ + macos-10.15 \ + macos-10.15.1 \ + macos-10.15.2 \ + macos-10.15.4 \ + macos-11.0.1 + +# Uncomment for easier debugging +# set tags master + +function bfn + echo "--blocklist-function=$argv[1]" +end + +function bty + echo "--blocklist-type=$argv[1]" +end + +function blocklisted + # Added in 10.8 + bfn objc_terminate + + # Added in 10.10 + bfn object_isClass + + # Removed in 10.11 + bfn objc_setFutureClass + + # Added in 10.12 + bfn object_setIvarWithStrongDefault + bfn object_setInstanceVariableWithStrongDefault + bfn protocol_copyPropertyList2 + + # Not present between 10.8 and 10.12, and declared OBJC_UNAVAILABLE + bty objc_objectptr_t + bfn objc_retainedObject + bfn objc_unretainedObject + bfn objc_unretainedPointer + + # Removed in 10.13 + bfn objc_sync_wait + bfn objc_sync_notify + bfn objc_sync_notifyAll + + # Added in 10.14 + bty objc_hook_getImageName + bfn objc_setHook_getImageName + + # Added in 10.14.4 + bty objc_hook_getClass + bfn objc_setHook_getClass + bfn _objc_realizeClassFromSwift + + # Added in 10.15, removed in 11.0.1 + bty objc_hook_setAssociatedObject + bfn objc_setHook_setAssociatedObject + + # Added in 10.15 + bty mach_header + bty objc_func_loadImage + bfn objc_addLoadImageFunc + + # Added in 11.0.1 + bty objc_hook_lazyClassNamer + bfn objc_setHook_lazyClassNamer +end + +# Marked with __[PLATFORM]_DEPRECATED +function deprecated + bfn class_setSuperclass # not recommended + bfn class_lookupMethod # use class_getMethodImplementation instead + bfn class_respondsToMethod # use class_respondsToSelector instead + bfn _objc_flush_caches # not recommended + + # Marked with OBJC_OSX_DEPRECATED_OTHERS_UNAVAILABLE + bfn object_copyFromZone # use object_copy instead + bfn class_createInstanceFromZone # use class_createInstance instead +end + +# Marked with OBJC_OSX_AVAILABLE_OTHERS_UNAVAILABLE +function macos_only + bty objc_exception_handler + bfn objc_addExceptionHandler + bfn objc_removeExceptionHandler +end + +# Protected by #if !(TARGET_OS_OSX && __i386__) block +function 64bit_only + bfn objc_setHook_getClass + bfn objc_setHook_lazyClassNamer + bfn _objc_swiftMetadataInitializer + bfn _objc_realizeClassFromSwift +end + +# Marked with OBJC2_UNAVAILABLE +function unavailable + # message.h + bty marg_list + bfn objc_msgSendv + bfn objc_msgSendv_stret + bfn objc_msgSendv_fpret + + # runtime.h + bfn object_realloc + bfn object_reallocFromZone + bfn objc_getClasses + bfn objc_addClass + bfn objc_setClassHandler + bfn objc_setMultithreaded + bfn class_addMethods + bfn class_removeMethods + bfn _objc_resolve_categories_for_class + bfn class_poseAs + bfn method_getSizeOfArguments + bfn method_getArgumentInfo + bfn objc_getOrigClass + bfn class_nextMethodList + + bty objc_method_list + + bfn _alloc + bfn _copy + bfn _realloc + bfn _dealloc + bfn _zoneAlloc + bfn _zoneRealloc + bfn _zoneCopy + bfn _error + + # Marked with OBJC_OSX_DEPRECATED_OTHERS_UNAVAILABLE + bfn object_copyFromZone # use object_copy instead + bfn class_createInstanceFromZone # use class_createInstance instead +end + +# Marked with OBJC_ARC_UNAVAILABLE +function arc_unavailable + bfn object_copy + bfn object_dispose + bfn object_setInstanceVariable + bfn object_setInstanceVariableWithStrongDefault + bfn object_getInstanceVariable + bfn objc_getFutureClass + bfn objc_constructInstance + bfn objc_destructInstance +end + +function custom + echo "--raw-line=use crate::*;" + + # Defined in types.rs + bty BOOL + bty objc_class + bty objc_ivar + bty objc_method + bty objc_object + bty objc_property + bty objc_selector + + # Defined in message.rs + bfn class_getMethodImplementation + bfn class_getMethodImplementation_stret + + # Not used anywhere + bty objc_category +end + + +for tag in $tags + git -C $source_repo checkout $tag + + bindgen $source_repo/runtime/headers.h -o $to_repo/bindings.rs \ + --no-layout-tests \ + --no-doc-comments \ + --size_t-is-usize \ + --allowlist-function="(sel|object|class|objc|method|protocol|ivar|property|imp|_objc|_)_.*" \ + --blocklist-type=__darwin_size_t \ + --generate="functions" \ + (blocklisted) \ + (deprecated) \ + (macos_only) \ + (64bit_only) \ + (unavailable) \ + (arc_unavailable) \ + (custom) + + # --allowlist-var=".*OBJC.*" \ + + git -C $to_repo add bindings.rs + git -C $to_repo commit -a -m "From $tag" +end + +rm $source_repo/runtime/headers.h diff --git a/objc_sys/helper-scripts/headers.h b/objc_sys/helper-scripts/headers.h new file mode 100644 index 000000000..751790650 --- /dev/null +++ b/objc_sys/helper-scripts/headers.h @@ -0,0 +1,33 @@ +// Generate bindings for Objective-C version 2 +#define __OBJC2__ 1 + +// Make the objc_msgSend family not variadic +// +// See https://developer.apple.com/documentation/objectivec/objc_old_dispatch_prototypes?language=objc +#define OBJC_OLD_DISPATCH_PROTOTYPES 0 + + +// Public headers +// The order of these is important + +#include "objc-api.h" +#include "objc.h" +#include "runtime.h" +#include "objc-exception.h" +#include "objc-sync.h" + +// All of these are custom-defined in message.rs because of complex cfgs +// #include "message.h" + +// Not used, contains old GC stuff +// Could also be removed with #define OBJC_NO_GC_API 1 +// #include "objc-auto.h" + + +// Private headers + +// Contains debug objc_msgSend + some Property stuff +// #include "objc-abi.h" + +// Contains internals + ARC +// #include "objc-internal.h" From 96a80f0296e51ded378fe7b8f1fc9868a0e63dd9 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 03:22:44 +0200 Subject: [PATCH 09/36] sys: Add autogenerated bindings --- objc_sys/src/bindings.rs | 429 +++++++++++++++++++++++++++++++++++++++ objc_sys/src/lib.rs | 1 + 2 files changed, 430 insertions(+) create mode 100644 objc_sys/src/bindings.rs diff --git a/objc_sys/src/bindings.rs b/objc_sys/src/bindings.rs new file mode 100644 index 000000000..4332f39c3 --- /dev/null +++ b/objc_sys/src/bindings.rs @@ -0,0 +1,429 @@ +/* automatically generated by rust-bindgen 0.59.1 */ + +use crate::*; + +extern "C" { + pub fn sel_getName(sel: SEL) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn sel_registerName(str_: *const ::std::os::raw::c_char) -> SEL; +} +extern "C" { + pub fn object_getClassName(obj: id) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn object_getIndexedIvars(obj: id) -> *mut ::std::os::raw::c_void; +} +extern "C" { + pub fn sel_isMapped(sel: SEL) -> BOOL; +} +extern "C" { + pub fn sel_getUid(str_: *const ::std::os::raw::c_char) -> SEL; +} +extern "C" { + pub fn object_getClass(obj: id) -> Class; +} +extern "C" { + pub fn object_setClass(obj: id, cls: Class) -> Class; +} +extern "C" { + pub fn object_getIvar(obj: id, ivar: Ivar) -> id; +} +extern "C" { + pub fn object_setIvar(obj: id, ivar: Ivar, value: id); +} +extern "C" { + pub fn objc_getClass(name: *const ::std::os::raw::c_char) -> Class; +} +extern "C" { + pub fn objc_getMetaClass(name: *const ::std::os::raw::c_char) -> Class; +} +extern "C" { + pub fn objc_lookUpClass(name: *const ::std::os::raw::c_char) -> Class; +} +extern "C" { + pub fn objc_getRequiredClass(name: *const ::std::os::raw::c_char) -> Class; +} +extern "C" { + pub fn objc_getClassList( + buffer: *mut Class, + bufferCount: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn objc_copyClassList(outCount: *mut ::std::os::raw::c_uint) -> *mut Class; +} +extern "C" { + pub fn class_getName(cls: Class) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn class_isMetaClass(cls: Class) -> BOOL; +} +extern "C" { + pub fn class_getSuperclass(cls: Class) -> Class; +} +extern "C" { + pub fn class_getVersion(cls: Class) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn class_setVersion(cls: Class, version: ::std::os::raw::c_int); +} +extern "C" { + pub fn class_getInstanceSize(cls: Class) -> usize; +} +extern "C" { + pub fn class_getInstanceVariable(cls: Class, name: *const ::std::os::raw::c_char) -> Ivar; +} +extern "C" { + pub fn class_getClassVariable(cls: Class, name: *const ::std::os::raw::c_char) -> Ivar; +} +extern "C" { + pub fn class_copyIvarList(cls: Class, outCount: *mut ::std::os::raw::c_uint) -> *mut Ivar; +} +extern "C" { + pub fn class_getInstanceMethod(cls: Class, name: SEL) -> Method; +} +extern "C" { + pub fn class_getClassMethod(cls: Class, name: SEL) -> Method; +} +extern "C" { + pub fn class_respondsToSelector(cls: Class, sel: SEL) -> BOOL; +} +extern "C" { + pub fn class_copyMethodList(cls: Class, outCount: *mut ::std::os::raw::c_uint) -> *mut Method; +} +extern "C" { + pub fn class_conformsToProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; +} +extern "C" { + pub fn class_copyProtocolList( + cls: Class, + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut *mut Protocol; +} +extern "C" { + pub fn class_getProperty(cls: Class, name: *const ::std::os::raw::c_char) -> objc_property_t; +} +extern "C" { + pub fn class_copyPropertyList( + cls: Class, + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut objc_property_t; +} +extern "C" { + pub fn class_getIvarLayout(cls: Class) -> *const u8; +} +extern "C" { + pub fn class_getWeakIvarLayout(cls: Class) -> *const u8; +} +extern "C" { + pub fn class_addMethod( + cls: Class, + name: SEL, + imp: IMP, + types: *const ::std::os::raw::c_char, + ) -> BOOL; +} +extern "C" { + pub fn class_replaceMethod( + cls: Class, + name: SEL, + imp: IMP, + types: *const ::std::os::raw::c_char, + ) -> IMP; +} +extern "C" { + pub fn class_addIvar( + cls: Class, + name: *const ::std::os::raw::c_char, + size: usize, + alignment: u8, + types: *const ::std::os::raw::c_char, + ) -> BOOL; +} +extern "C" { + pub fn class_addProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; +} +extern "C" { + pub fn class_addProperty( + cls: Class, + name: *const ::std::os::raw::c_char, + attributes: *const objc_property_attribute_t, + attributeCount: ::std::os::raw::c_uint, + ) -> BOOL; +} +extern "C" { + pub fn class_replaceProperty( + cls: Class, + name: *const ::std::os::raw::c_char, + attributes: *const objc_property_attribute_t, + attributeCount: ::std::os::raw::c_uint, + ); +} +extern "C" { + pub fn class_setIvarLayout(cls: Class, layout: *const u8); +} +extern "C" { + pub fn class_setWeakIvarLayout(cls: Class, layout: *const u8); +} +extern "C" { + pub fn class_createInstance(cls: Class, extraBytes: usize) -> id; +} +extern "C" { + pub fn objc_allocateClassPair( + superclass: Class, + name: *const ::std::os::raw::c_char, + extraBytes: usize, + ) -> Class; +} +extern "C" { + pub fn objc_registerClassPair(cls: Class); +} +extern "C" { + pub fn objc_duplicateClass( + original: Class, + name: *const ::std::os::raw::c_char, + extraBytes: usize, + ) -> Class; +} +extern "C" { + pub fn objc_disposeClassPair(cls: Class); +} +extern "C" { + pub fn method_getName(m: Method) -> SEL; +} +extern "C" { + pub fn method_getImplementation(m: Method) -> IMP; +} +extern "C" { + pub fn method_getTypeEncoding(m: Method) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn method_getNumberOfArguments(m: Method) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn method_copyReturnType(m: Method) -> *mut ::std::os::raw::c_char; +} +extern "C" { + pub fn method_copyArgumentType( + m: Method, + index: ::std::os::raw::c_uint, + ) -> *mut ::std::os::raw::c_char; +} +extern "C" { + pub fn method_getReturnType(m: Method, dst: *mut ::std::os::raw::c_char, dst_len: usize); +} +extern "C" { + pub fn method_getArgumentType( + m: Method, + index: ::std::os::raw::c_uint, + dst: *mut ::std::os::raw::c_char, + dst_len: usize, + ); +} +extern "C" { + pub fn method_getDescription(m: Method) -> *mut objc_method_description; +} +extern "C" { + pub fn method_setImplementation(m: Method, imp: IMP) -> IMP; +} +extern "C" { + pub fn method_exchangeImplementations(m1: Method, m2: Method); +} +extern "C" { + pub fn ivar_getName(v: Ivar) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn ivar_getTypeEncoding(v: Ivar) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn ivar_getOffset(v: Ivar) -> isize; +} +extern "C" { + pub fn property_getName(property: objc_property_t) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn property_getAttributes(property: objc_property_t) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn property_copyAttributeList( + property: objc_property_t, + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut objc_property_attribute_t; +} +extern "C" { + pub fn property_copyAttributeValue( + property: objc_property_t, + attributeName: *const ::std::os::raw::c_char, + ) -> *mut ::std::os::raw::c_char; +} +extern "C" { + pub fn objc_getProtocol(name: *const ::std::os::raw::c_char) -> *mut Protocol; +} +extern "C" { + pub fn objc_copyProtocolList(outCount: *mut ::std::os::raw::c_uint) -> *mut *mut Protocol; +} +extern "C" { + pub fn protocol_conformsToProtocol(proto: *mut Protocol, other: *mut Protocol) -> BOOL; +} +extern "C" { + pub fn protocol_isEqual(proto: *mut Protocol, other: *mut Protocol) -> BOOL; +} +extern "C" { + pub fn protocol_getName(proto: *mut Protocol) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn protocol_getMethodDescription( + proto: *mut Protocol, + aSel: SEL, + isRequiredMethod: BOOL, + isInstanceMethod: BOOL, + ) -> objc_method_description; +} +extern "C" { + pub fn protocol_copyMethodDescriptionList( + proto: *mut Protocol, + isRequiredMethod: BOOL, + isInstanceMethod: BOOL, + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut objc_method_description; +} +extern "C" { + pub fn protocol_getProperty( + proto: *mut Protocol, + name: *const ::std::os::raw::c_char, + isRequiredProperty: BOOL, + isInstanceProperty: BOOL, + ) -> objc_property_t; +} +extern "C" { + pub fn protocol_copyPropertyList( + proto: *mut Protocol, + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut objc_property_t; +} +extern "C" { + pub fn protocol_copyProtocolList( + proto: *mut Protocol, + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut *mut Protocol; +} +extern "C" { + pub fn objc_allocateProtocol(name: *const ::std::os::raw::c_char) -> *mut Protocol; +} +extern "C" { + pub fn objc_registerProtocol(proto: *mut Protocol); +} +extern "C" { + pub fn protocol_addMethodDescription( + proto: *mut Protocol, + name: SEL, + types: *const ::std::os::raw::c_char, + isRequiredMethod: BOOL, + isInstanceMethod: BOOL, + ); +} +extern "C" { + pub fn protocol_addProtocol(proto: *mut Protocol, addition: *mut Protocol); +} +extern "C" { + pub fn protocol_addProperty( + proto: *mut Protocol, + name: *const ::std::os::raw::c_char, + attributes: *const objc_property_attribute_t, + attributeCount: ::std::os::raw::c_uint, + isRequiredProperty: BOOL, + isInstanceProperty: BOOL, + ); +} +extern "C" { + pub fn objc_copyImageNames( + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut *const ::std::os::raw::c_char; +} +extern "C" { + pub fn class_getImageName(cls: Class) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn objc_copyClassNamesForImage( + image: *const ::std::os::raw::c_char, + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut *const ::std::os::raw::c_char; +} +extern "C" { + pub fn sel_isEqual(lhs: SEL, rhs: SEL) -> BOOL; +} +extern "C" { + pub fn objc_enumerationMutation(obj: id); +} +extern "C" { + pub fn objc_setEnumerationMutationHandler( + handler: ::std::option::Option, + ); +} +extern "C" { + pub fn objc_setForwardHandler( + fwd: *mut ::std::os::raw::c_void, + fwd_stret: *mut ::std::os::raw::c_void, + ); +} +extern "C" { + pub fn imp_implementationWithBlock(block: id) -> IMP; +} +extern "C" { + pub fn imp_getBlock(anImp: IMP) -> id; +} +extern "C" { + pub fn imp_removeBlock(anImp: IMP) -> BOOL; +} +extern "C" { + pub fn objc_loadWeak(location: *mut id) -> id; +} +extern "C" { + pub fn objc_storeWeak(location: *mut id, obj: id) -> id; +} +extern "C" { + pub fn objc_setAssociatedObject( + object: id, + key: *const ::std::os::raw::c_void, + value: id, + policy: objc_AssociationPolicy, + ); +} +extern "C" { + pub fn objc_getAssociatedObject(object: id, key: *const ::std::os::raw::c_void) -> id; +} +extern "C" { + pub fn objc_removeAssociatedObjects(object: id); +} +extern "C" { + pub fn objc_exception_throw(exception: id); +} +extern "C" { + pub fn objc_exception_rethrow(); +} +extern "C" { + pub fn objc_begin_catch(exc_buf: *mut ::std::os::raw::c_void) -> id; +} +extern "C" { + pub fn objc_end_catch(); +} +extern "C" { + pub fn objc_setExceptionPreprocessor( + fn_: objc_exception_preprocessor, + ) -> objc_exception_preprocessor; +} +extern "C" { + pub fn objc_setExceptionMatcher(fn_: objc_exception_matcher) -> objc_exception_matcher; +} +extern "C" { + pub fn objc_setUncaughtExceptionHandler( + fn_: objc_uncaught_exception_handler, + ) -> objc_uncaught_exception_handler; +} +extern "C" { + pub fn objc_sync_enter(obj: id) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn objc_sync_exit(obj: id) -> ::std::os::raw::c_int; +} diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index bdf14299a..547247fe0 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -22,6 +22,7 @@ use std::os::raw::{c_char, c_int, c_uint}; mod constants; mod message; mod types; +mod bindings; pub use constants::*; pub use message::*; From 052bcd697a08286a8f416d78c5a38d19765ce952 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 03:41:57 +0200 Subject: [PATCH 10/36] sys: Move ARC functions to their own file, and add missing declarations --- objc_sys/src/bindings.rs | 6 ----- objc_sys/src/lib.rs | 20 +++------------- objc_sys/src/rc.rs | 51 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 23 deletions(-) create mode 100644 objc_sys/src/rc.rs diff --git a/objc_sys/src/bindings.rs b/objc_sys/src/bindings.rs index 4332f39c3..d173182c2 100644 --- a/objc_sys/src/bindings.rs +++ b/objc_sys/src/bindings.rs @@ -376,12 +376,6 @@ extern "C" { extern "C" { pub fn imp_removeBlock(anImp: IMP) -> BOOL; } -extern "C" { - pub fn objc_loadWeak(location: *mut id) -> id; -} -extern "C" { - pub fn objc_storeWeak(location: *mut id, obj: id) -> id; -} extern "C" { pub fn objc_setAssociatedObject( object: id, diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index 547247fe0..f37d08885 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -16,16 +16,17 @@ extern crate std; -use core::ffi::c_void; use std::os::raw::{c_char, c_int, c_uint}; +mod bindings; mod constants; mod message; +mod rc; mod types; -mod bindings; pub use constants::*; pub use message::*; +pub use rc::*; pub use types::*; #[link(name = "objc", kind = "dylib")] @@ -92,9 +93,6 @@ extern "C" { pub fn objc_allocateProtocol(name: *const c_char) -> *mut objc_protocol; pub fn objc_registerProtocol(proto: *mut objc_protocol); - pub fn objc_autoreleasePoolPush() -> *mut c_void; - pub fn objc_autoreleasePoolPop(context: *mut c_void); - pub fn protocol_addMethodDescription( proto: *mut objc_protocol, name: *const objc_selector, @@ -125,16 +123,4 @@ extern "C" { pub fn method_getNumberOfArguments(method: *const objc_method) -> c_uint; pub fn method_setImplementation(method: *mut objc_method, imp: IMP) -> IMP; pub fn method_exchangeImplementations(m1: *mut objc_method, m2: *mut objc_method); - - pub fn objc_retain(obj: *mut objc_object) -> *mut objc_object; - pub fn objc_release(obj: *mut objc_object); - pub fn objc_autorelease(obj: *mut objc_object); - - pub fn objc_loadWeakRetained(location: *mut *mut objc_object) -> *mut objc_object; - pub fn objc_initWeak( - location: *mut *mut objc_object, - obj: *mut objc_object, - ) -> *mut objc_object; - pub fn objc_destroyWeak(location: *mut *mut objc_object); - pub fn objc_copyWeak(to: *mut *mut objc_object, from: *mut *mut objc_object); } diff --git a/objc_sys/src/rc.rs b/objc_sys/src/rc.rs new file mode 100644 index 000000000..3b9d60838 --- /dev/null +++ b/objc_sys/src/rc.rs @@ -0,0 +1,51 @@ +//! ARC functions. +//! +//! All available since macOS `10.7`. +//! +//! Defined in `objc-internal.h`, but is available in Clang's +//! [documentation][ARC] so these are safe to rely on. +//! +//! [ARC]: https://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime-support> +use core::ffi::c_void; + +use crate::objc_object; + +extern "C" { + // Autorelease + + pub fn objc_autorelease(value: *mut objc_object) -> *mut objc_object; + pub fn objc_autoreleasePoolPop(pool: *mut c_void); + pub fn objc_autoreleasePoolPush() -> *mut c_void; + pub fn objc_autoreleaseReturnValue(value: *mut objc_object) -> *mut objc_object; + + // Weak pointers + + pub fn objc_copyWeak(to: *mut *mut objc_object, from: *mut *mut objc_object); + pub fn objc_destroyWeak(location: *mut *mut objc_object); + pub fn objc_initWeak( + location: *mut *mut objc_object, + value: *mut objc_object, + ) -> *mut objc_object; + // Defined in runtime.h + pub fn objc_loadWeak(location: *mut *mut objc_object) -> *mut objc_object; + pub fn objc_loadWeakRetained(location: *mut *mut objc_object) -> *mut objc_object; + pub fn objc_moveWeak(to: *mut *mut objc_object, from: *mut *mut objc_object); + + // Retain / release + + pub fn objc_release(value: *mut objc_object); + pub fn objc_retain(value: *mut objc_object) -> *mut objc_object; + pub fn objc_retainAutorelease(value: *mut objc_object) -> *mut objc_object; + pub fn objc_retainAutoreleasedReturnValue(value: *mut objc_object) -> *mut objc_object; + // Defined in objc-abi.h + pub fn objc_retainBlock(value: *mut objc_object) -> *mut objc_object; + + // Storing values + + pub fn objc_storeStrong(location: *mut *mut objc_object, value: *mut objc_object); + // Defined in runtime.h + pub fn objc_storeWeak( + location: *mut *mut objc_object, + value: *mut objc_object, + ) -> *mut objc_object; +} From cbad530d96cfa7f375d69cf1bbf45d0b1aba1bc9 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 04:01:12 +0200 Subject: [PATCH 11/36] sys: Remove extra extern "C" from bindings --- objc_sys/src/bindings.rs | 204 --------------------------------------- 1 file changed, 204 deletions(-) diff --git a/objc_sys/src/bindings.rs b/objc_sys/src/bindings.rs index d173182c2..dc6ae5621 100644 --- a/objc_sys/src/bindings.rs +++ b/objc_sys/src/bindings.rs @@ -4,135 +4,61 @@ use crate::*; extern "C" { pub fn sel_getName(sel: SEL) -> *const ::std::os::raw::c_char; -} -extern "C" { pub fn sel_registerName(str_: *const ::std::os::raw::c_char) -> SEL; -} -extern "C" { pub fn object_getClassName(obj: id) -> *const ::std::os::raw::c_char; -} -extern "C" { pub fn object_getIndexedIvars(obj: id) -> *mut ::std::os::raw::c_void; -} -extern "C" { pub fn sel_isMapped(sel: SEL) -> BOOL; -} -extern "C" { pub fn sel_getUid(str_: *const ::std::os::raw::c_char) -> SEL; -} -extern "C" { pub fn object_getClass(obj: id) -> Class; -} -extern "C" { pub fn object_setClass(obj: id, cls: Class) -> Class; -} -extern "C" { pub fn object_getIvar(obj: id, ivar: Ivar) -> id; -} -extern "C" { pub fn object_setIvar(obj: id, ivar: Ivar, value: id); -} -extern "C" { pub fn objc_getClass(name: *const ::std::os::raw::c_char) -> Class; -} -extern "C" { pub fn objc_getMetaClass(name: *const ::std::os::raw::c_char) -> Class; -} -extern "C" { pub fn objc_lookUpClass(name: *const ::std::os::raw::c_char) -> Class; -} -extern "C" { pub fn objc_getRequiredClass(name: *const ::std::os::raw::c_char) -> Class; -} -extern "C" { pub fn objc_getClassList( buffer: *mut Class, bufferCount: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; -} -extern "C" { pub fn objc_copyClassList(outCount: *mut ::std::os::raw::c_uint) -> *mut Class; -} -extern "C" { pub fn class_getName(cls: Class) -> *const ::std::os::raw::c_char; -} -extern "C" { pub fn class_isMetaClass(cls: Class) -> BOOL; -} -extern "C" { pub fn class_getSuperclass(cls: Class) -> Class; -} -extern "C" { pub fn class_getVersion(cls: Class) -> ::std::os::raw::c_int; -} -extern "C" { pub fn class_setVersion(cls: Class, version: ::std::os::raw::c_int); -} -extern "C" { pub fn class_getInstanceSize(cls: Class) -> usize; -} -extern "C" { pub fn class_getInstanceVariable(cls: Class, name: *const ::std::os::raw::c_char) -> Ivar; -} -extern "C" { pub fn class_getClassVariable(cls: Class, name: *const ::std::os::raw::c_char) -> Ivar; -} -extern "C" { pub fn class_copyIvarList(cls: Class, outCount: *mut ::std::os::raw::c_uint) -> *mut Ivar; -} -extern "C" { pub fn class_getInstanceMethod(cls: Class, name: SEL) -> Method; -} -extern "C" { pub fn class_getClassMethod(cls: Class, name: SEL) -> Method; -} -extern "C" { pub fn class_respondsToSelector(cls: Class, sel: SEL) -> BOOL; -} -extern "C" { pub fn class_copyMethodList(cls: Class, outCount: *mut ::std::os::raw::c_uint) -> *mut Method; -} -extern "C" { pub fn class_conformsToProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; -} -extern "C" { pub fn class_copyProtocolList( cls: Class, outCount: *mut ::std::os::raw::c_uint, ) -> *mut *mut Protocol; -} -extern "C" { pub fn class_getProperty(cls: Class, name: *const ::std::os::raw::c_char) -> objc_property_t; -} -extern "C" { pub fn class_copyPropertyList( cls: Class, outCount: *mut ::std::os::raw::c_uint, ) -> *mut objc_property_t; -} -extern "C" { pub fn class_getIvarLayout(cls: Class) -> *const u8; -} -extern "C" { pub fn class_getWeakIvarLayout(cls: Class) -> *const u8; -} -extern "C" { pub fn class_addMethod( cls: Class, name: SEL, imp: IMP, types: *const ::std::os::raw::c_char, ) -> BOOL; -} -extern "C" { pub fn class_replaceMethod( cls: Class, name: SEL, imp: IMP, types: *const ::std::os::raw::c_char, ) -> IMP; -} -extern "C" { pub fn class_addIvar( cls: Class, name: *const ::std::os::raw::c_char, @@ -140,181 +66,99 @@ extern "C" { alignment: u8, types: *const ::std::os::raw::c_char, ) -> BOOL; -} -extern "C" { pub fn class_addProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; -} -extern "C" { pub fn class_addProperty( cls: Class, name: *const ::std::os::raw::c_char, attributes: *const objc_property_attribute_t, attributeCount: ::std::os::raw::c_uint, ) -> BOOL; -} -extern "C" { pub fn class_replaceProperty( cls: Class, name: *const ::std::os::raw::c_char, attributes: *const objc_property_attribute_t, attributeCount: ::std::os::raw::c_uint, ); -} -extern "C" { pub fn class_setIvarLayout(cls: Class, layout: *const u8); -} -extern "C" { pub fn class_setWeakIvarLayout(cls: Class, layout: *const u8); -} -extern "C" { pub fn class_createInstance(cls: Class, extraBytes: usize) -> id; -} -extern "C" { pub fn objc_allocateClassPair( superclass: Class, name: *const ::std::os::raw::c_char, extraBytes: usize, ) -> Class; -} -extern "C" { pub fn objc_registerClassPair(cls: Class); -} -extern "C" { pub fn objc_duplicateClass( original: Class, name: *const ::std::os::raw::c_char, extraBytes: usize, ) -> Class; -} -extern "C" { pub fn objc_disposeClassPair(cls: Class); -} -extern "C" { pub fn method_getName(m: Method) -> SEL; -} -extern "C" { pub fn method_getImplementation(m: Method) -> IMP; -} -extern "C" { pub fn method_getTypeEncoding(m: Method) -> *const ::std::os::raw::c_char; -} -extern "C" { pub fn method_getNumberOfArguments(m: Method) -> ::std::os::raw::c_uint; -} -extern "C" { pub fn method_copyReturnType(m: Method) -> *mut ::std::os::raw::c_char; -} -extern "C" { pub fn method_copyArgumentType( m: Method, index: ::std::os::raw::c_uint, ) -> *mut ::std::os::raw::c_char; -} -extern "C" { pub fn method_getReturnType(m: Method, dst: *mut ::std::os::raw::c_char, dst_len: usize); -} -extern "C" { pub fn method_getArgumentType( m: Method, index: ::std::os::raw::c_uint, dst: *mut ::std::os::raw::c_char, dst_len: usize, ); -} -extern "C" { pub fn method_getDescription(m: Method) -> *mut objc_method_description; -} -extern "C" { pub fn method_setImplementation(m: Method, imp: IMP) -> IMP; -} -extern "C" { pub fn method_exchangeImplementations(m1: Method, m2: Method); -} -extern "C" { pub fn ivar_getName(v: Ivar) -> *const ::std::os::raw::c_char; -} -extern "C" { pub fn ivar_getTypeEncoding(v: Ivar) -> *const ::std::os::raw::c_char; -} -extern "C" { pub fn ivar_getOffset(v: Ivar) -> isize; -} -extern "C" { pub fn property_getName(property: objc_property_t) -> *const ::std::os::raw::c_char; -} -extern "C" { pub fn property_getAttributes(property: objc_property_t) -> *const ::std::os::raw::c_char; -} -extern "C" { pub fn property_copyAttributeList( property: objc_property_t, outCount: *mut ::std::os::raw::c_uint, ) -> *mut objc_property_attribute_t; -} -extern "C" { pub fn property_copyAttributeValue( property: objc_property_t, attributeName: *const ::std::os::raw::c_char, ) -> *mut ::std::os::raw::c_char; -} -extern "C" { pub fn objc_getProtocol(name: *const ::std::os::raw::c_char) -> *mut Protocol; -} -extern "C" { pub fn objc_copyProtocolList(outCount: *mut ::std::os::raw::c_uint) -> *mut *mut Protocol; -} -extern "C" { pub fn protocol_conformsToProtocol(proto: *mut Protocol, other: *mut Protocol) -> BOOL; -} -extern "C" { pub fn protocol_isEqual(proto: *mut Protocol, other: *mut Protocol) -> BOOL; -} -extern "C" { pub fn protocol_getName(proto: *mut Protocol) -> *const ::std::os::raw::c_char; -} -extern "C" { pub fn protocol_getMethodDescription( proto: *mut Protocol, aSel: SEL, isRequiredMethod: BOOL, isInstanceMethod: BOOL, ) -> objc_method_description; -} -extern "C" { pub fn protocol_copyMethodDescriptionList( proto: *mut Protocol, isRequiredMethod: BOOL, isInstanceMethod: BOOL, outCount: *mut ::std::os::raw::c_uint, ) -> *mut objc_method_description; -} -extern "C" { pub fn protocol_getProperty( proto: *mut Protocol, name: *const ::std::os::raw::c_char, isRequiredProperty: BOOL, isInstanceProperty: BOOL, ) -> objc_property_t; -} -extern "C" { pub fn protocol_copyPropertyList( proto: *mut Protocol, outCount: *mut ::std::os::raw::c_uint, ) -> *mut objc_property_t; -} -extern "C" { pub fn protocol_copyProtocolList( proto: *mut Protocol, outCount: *mut ::std::os::raw::c_uint, ) -> *mut *mut Protocol; -} -extern "C" { pub fn objc_allocateProtocol(name: *const ::std::os::raw::c_char) -> *mut Protocol; -} -extern "C" { pub fn objc_registerProtocol(proto: *mut Protocol); -} -extern "C" { pub fn protocol_addMethodDescription( proto: *mut Protocol, name: SEL, @@ -322,11 +166,7 @@ extern "C" { isRequiredMethod: BOOL, isInstanceMethod: BOOL, ); -} -extern "C" { pub fn protocol_addProtocol(proto: *mut Protocol, addition: *mut Protocol); -} -extern "C" { pub fn protocol_addProperty( proto: *mut Protocol, name: *const ::std::os::raw::c_char, @@ -335,89 +175,45 @@ extern "C" { isRequiredProperty: BOOL, isInstanceProperty: BOOL, ); -} -extern "C" { pub fn objc_copyImageNames( outCount: *mut ::std::os::raw::c_uint, ) -> *mut *const ::std::os::raw::c_char; -} -extern "C" { pub fn class_getImageName(cls: Class) -> *const ::std::os::raw::c_char; -} -extern "C" { pub fn objc_copyClassNamesForImage( image: *const ::std::os::raw::c_char, outCount: *mut ::std::os::raw::c_uint, ) -> *mut *const ::std::os::raw::c_char; -} -extern "C" { pub fn sel_isEqual(lhs: SEL, rhs: SEL) -> BOOL; -} -extern "C" { pub fn objc_enumerationMutation(obj: id); -} -extern "C" { pub fn objc_setEnumerationMutationHandler( handler: ::std::option::Option, ); -} -extern "C" { pub fn objc_setForwardHandler( fwd: *mut ::std::os::raw::c_void, fwd_stret: *mut ::std::os::raw::c_void, ); -} -extern "C" { pub fn imp_implementationWithBlock(block: id) -> IMP; -} -extern "C" { pub fn imp_getBlock(anImp: IMP) -> id; -} -extern "C" { pub fn imp_removeBlock(anImp: IMP) -> BOOL; -} -extern "C" { pub fn objc_setAssociatedObject( object: id, key: *const ::std::os::raw::c_void, value: id, policy: objc_AssociationPolicy, ); -} -extern "C" { pub fn objc_getAssociatedObject(object: id, key: *const ::std::os::raw::c_void) -> id; -} -extern "C" { pub fn objc_removeAssociatedObjects(object: id); -} -extern "C" { pub fn objc_exception_throw(exception: id); -} -extern "C" { pub fn objc_exception_rethrow(); -} -extern "C" { pub fn objc_begin_catch(exc_buf: *mut ::std::os::raw::c_void) -> id; -} -extern "C" { pub fn objc_end_catch(); -} -extern "C" { pub fn objc_setExceptionPreprocessor( fn_: objc_exception_preprocessor, ) -> objc_exception_preprocessor; -} -extern "C" { pub fn objc_setExceptionMatcher(fn_: objc_exception_matcher) -> objc_exception_matcher; -} -extern "C" { pub fn objc_setUncaughtExceptionHandler( fn_: objc_uncaught_exception_handler, ) -> objc_uncaught_exception_handler; -} -extern "C" { pub fn objc_sync_enter(obj: id) -> ::std::os::raw::c_int; -} -extern "C" { pub fn objc_sync_exit(obj: id) -> ::std::os::raw::c_int; } From cbba5125b7c95599bdfb200f6d507898e7b7de85 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 04:06:55 +0200 Subject: [PATCH 12/36] sys: Sort bindings alphabetically --- objc_sys/src/bindings.rs | 292 +++++++++++++++++++-------------------- 1 file changed, 146 insertions(+), 146 deletions(-) diff --git a/objc_sys/src/bindings.rs b/objc_sys/src/bindings.rs index dc6ae5621..f2d513177 100644 --- a/objc_sys/src/bindings.rs +++ b/objc_sys/src/bindings.rs @@ -3,107 +3,79 @@ use crate::*; extern "C" { - pub fn sel_getName(sel: SEL) -> *const ::std::os::raw::c_char; - pub fn sel_registerName(str_: *const ::std::os::raw::c_char) -> SEL; - pub fn object_getClassName(obj: id) -> *const ::std::os::raw::c_char; - pub fn object_getIndexedIvars(obj: id) -> *mut ::std::os::raw::c_void; - pub fn sel_isMapped(sel: SEL) -> BOOL; - pub fn sel_getUid(str_: *const ::std::os::raw::c_char) -> SEL; - pub fn object_getClass(obj: id) -> Class; - pub fn object_setClass(obj: id, cls: Class) -> Class; - pub fn object_getIvar(obj: id, ivar: Ivar) -> id; - pub fn object_setIvar(obj: id, ivar: Ivar, value: id); - pub fn objc_getClass(name: *const ::std::os::raw::c_char) -> Class; - pub fn objc_getMetaClass(name: *const ::std::os::raw::c_char) -> Class; - pub fn objc_lookUpClass(name: *const ::std::os::raw::c_char) -> Class; - pub fn objc_getRequiredClass(name: *const ::std::os::raw::c_char) -> Class; - pub fn objc_getClassList( - buffer: *mut Class, - bufferCount: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; - pub fn objc_copyClassList(outCount: *mut ::std::os::raw::c_uint) -> *mut Class; - pub fn class_getName(cls: Class) -> *const ::std::os::raw::c_char; - pub fn class_isMetaClass(cls: Class) -> BOOL; - pub fn class_getSuperclass(cls: Class) -> Class; - pub fn class_getVersion(cls: Class) -> ::std::os::raw::c_int; - pub fn class_setVersion(cls: Class, version: ::std::os::raw::c_int); - pub fn class_getInstanceSize(cls: Class) -> usize; - pub fn class_getInstanceVariable(cls: Class, name: *const ::std::os::raw::c_char) -> Ivar; - pub fn class_getClassVariable(cls: Class, name: *const ::std::os::raw::c_char) -> Ivar; - pub fn class_copyIvarList(cls: Class, outCount: *mut ::std::os::raw::c_uint) -> *mut Ivar; - pub fn class_getInstanceMethod(cls: Class, name: SEL) -> Method; - pub fn class_getClassMethod(cls: Class, name: SEL) -> Method; - pub fn class_respondsToSelector(cls: Class, sel: SEL) -> BOOL; - pub fn class_copyMethodList(cls: Class, outCount: *mut ::std::os::raw::c_uint) -> *mut Method; - pub fn class_conformsToProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; - pub fn class_copyProtocolList( - cls: Class, - outCount: *mut ::std::os::raw::c_uint, - ) -> *mut *mut Protocol; - pub fn class_getProperty(cls: Class, name: *const ::std::os::raw::c_char) -> objc_property_t; - pub fn class_copyPropertyList( - cls: Class, - outCount: *mut ::std::os::raw::c_uint, - ) -> *mut objc_property_t; - pub fn class_getIvarLayout(cls: Class) -> *const u8; - pub fn class_getWeakIvarLayout(cls: Class) -> *const u8; - pub fn class_addMethod( + pub fn class_addIvar( cls: Class, - name: SEL, - imp: IMP, + name: *const ::std::os::raw::c_char, + size: usize, + alignment: u8, types: *const ::std::os::raw::c_char, ) -> BOOL; - pub fn class_replaceMethod( + pub fn class_addMethod( cls: Class, name: SEL, imp: IMP, types: *const ::std::os::raw::c_char, - ) -> IMP; - pub fn class_addIvar( - cls: Class, - name: *const ::std::os::raw::c_char, - size: usize, - alignment: u8, - types: *const ::std::os::raw::c_char, ) -> BOOL; - pub fn class_addProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; pub fn class_addProperty( cls: Class, name: *const ::std::os::raw::c_char, attributes: *const objc_property_attribute_t, attributeCount: ::std::os::raw::c_uint, ) -> BOOL; + pub fn class_addProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; + pub fn class_conformsToProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; + pub fn class_copyIvarList(cls: Class, outCount: *mut ::std::os::raw::c_uint) -> *mut Ivar; + pub fn class_copyMethodList(cls: Class, outCount: *mut ::std::os::raw::c_uint) -> *mut Method; + pub fn class_copyPropertyList( + cls: Class, + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut objc_property_t; + pub fn class_copyProtocolList( + cls: Class, + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut *mut Protocol; + pub fn class_createInstance(cls: Class, extraBytes: usize) -> id; + pub fn class_getClassMethod(cls: Class, name: SEL) -> Method; + pub fn class_getClassVariable(cls: Class, name: *const ::std::os::raw::c_char) -> Ivar; + pub fn class_getImageName(cls: Class) -> *const ::std::os::raw::c_char; + pub fn class_getInstanceMethod(cls: Class, name: SEL) -> Method; + pub fn class_getInstanceSize(cls: Class) -> usize; + pub fn class_getInstanceVariable(cls: Class, name: *const ::std::os::raw::c_char) -> Ivar; + pub fn class_getIvarLayout(cls: Class) -> *const u8; + pub fn class_getName(cls: Class) -> *const ::std::os::raw::c_char; + pub fn class_getProperty(cls: Class, name: *const ::std::os::raw::c_char) -> objc_property_t; + pub fn class_getSuperclass(cls: Class) -> Class; + pub fn class_getVersion(cls: Class) -> ::std::os::raw::c_int; + pub fn class_getWeakIvarLayout(cls: Class) -> *const u8; + pub fn class_isMetaClass(cls: Class) -> BOOL; + pub fn class_replaceMethod( + cls: Class, + name: SEL, + imp: IMP, + types: *const ::std::os::raw::c_char, + ) -> IMP; pub fn class_replaceProperty( cls: Class, name: *const ::std::os::raw::c_char, attributes: *const objc_property_attribute_t, attributeCount: ::std::os::raw::c_uint, ); + pub fn class_respondsToSelector(cls: Class, sel: SEL) -> BOOL; pub fn class_setIvarLayout(cls: Class, layout: *const u8); + pub fn class_setVersion(cls: Class, version: ::std::os::raw::c_int); pub fn class_setWeakIvarLayout(cls: Class, layout: *const u8); - pub fn class_createInstance(cls: Class, extraBytes: usize) -> id; - pub fn objc_allocateClassPair( - superclass: Class, - name: *const ::std::os::raw::c_char, - extraBytes: usize, - ) -> Class; - pub fn objc_registerClassPair(cls: Class); - pub fn objc_duplicateClass( - original: Class, - name: *const ::std::os::raw::c_char, - extraBytes: usize, - ) -> Class; - pub fn objc_disposeClassPair(cls: Class); - pub fn method_getName(m: Method) -> SEL; - pub fn method_getImplementation(m: Method) -> IMP; - pub fn method_getTypeEncoding(m: Method) -> *const ::std::os::raw::c_char; - pub fn method_getNumberOfArguments(m: Method) -> ::std::os::raw::c_uint; - pub fn method_copyReturnType(m: Method) -> *mut ::std::os::raw::c_char; + pub fn imp_getBlock(anImp: IMP) -> id; + pub fn imp_implementationWithBlock(block: id) -> IMP; + pub fn imp_removeBlock(anImp: IMP) -> BOOL; + pub fn ivar_getName(v: Ivar) -> *const ::std::os::raw::c_char; + pub fn ivar_getOffset(v: Ivar) -> isize; + pub fn ivar_getTypeEncoding(v: Ivar) -> *const ::std::os::raw::c_char; pub fn method_copyArgumentType( m: Method, index: ::std::os::raw::c_uint, ) -> *mut ::std::os::raw::c_char; - pub fn method_getReturnType(m: Method, dst: *mut ::std::os::raw::c_char, dst_len: usize); + pub fn method_copyReturnType(m: Method) -> *mut ::std::os::raw::c_char; + pub fn method_exchangeImplementations(m1: Method, m2: Method); pub fn method_getArgumentType( m: Method, index: ::std::os::raw::c_uint, @@ -111,13 +83,79 @@ extern "C" { dst_len: usize, ); pub fn method_getDescription(m: Method) -> *mut objc_method_description; + pub fn method_getImplementation(m: Method) -> IMP; + pub fn method_getName(m: Method) -> SEL; + pub fn method_getNumberOfArguments(m: Method) -> ::std::os::raw::c_uint; + pub fn method_getReturnType(m: Method, dst: *mut ::std::os::raw::c_char, dst_len: usize); + pub fn method_getTypeEncoding(m: Method) -> *const ::std::os::raw::c_char; pub fn method_setImplementation(m: Method, imp: IMP) -> IMP; - pub fn method_exchangeImplementations(m1: Method, m2: Method); - pub fn ivar_getName(v: Ivar) -> *const ::std::os::raw::c_char; - pub fn ivar_getTypeEncoding(v: Ivar) -> *const ::std::os::raw::c_char; - pub fn ivar_getOffset(v: Ivar) -> isize; - pub fn property_getName(property: objc_property_t) -> *const ::std::os::raw::c_char; - pub fn property_getAttributes(property: objc_property_t) -> *const ::std::os::raw::c_char; + pub fn objc_allocateClassPair( + superclass: Class, + name: *const ::std::os::raw::c_char, + extraBytes: usize, + ) -> Class; + pub fn objc_allocateProtocol(name: *const ::std::os::raw::c_char) -> *mut Protocol; + pub fn objc_begin_catch(exc_buf: *mut ::std::os::raw::c_void) -> id; + pub fn objc_copyClassList(outCount: *mut ::std::os::raw::c_uint) -> *mut Class; + pub fn objc_copyClassNamesForImage( + image: *const ::std::os::raw::c_char, + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut *const ::std::os::raw::c_char; + pub fn objc_copyImageNames( + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut *const ::std::os::raw::c_char; + pub fn objc_copyProtocolList(outCount: *mut ::std::os::raw::c_uint) -> *mut *mut Protocol; + pub fn objc_disposeClassPair(cls: Class); + pub fn objc_duplicateClass( + original: Class, + name: *const ::std::os::raw::c_char, + extraBytes: usize, + ) -> Class; + pub fn objc_end_catch(); + pub fn objc_enumerationMutation(obj: id); + pub fn objc_exception_rethrow(); + pub fn objc_exception_throw(exception: id); + pub fn objc_getAssociatedObject(object: id, key: *const ::std::os::raw::c_void) -> id; + pub fn objc_getClass(name: *const ::std::os::raw::c_char) -> Class; + pub fn objc_getClassList( + buffer: *mut Class, + bufferCount: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; + pub fn objc_getMetaClass(name: *const ::std::os::raw::c_char) -> Class; + pub fn objc_getProtocol(name: *const ::std::os::raw::c_char) -> *mut Protocol; + pub fn objc_getRequiredClass(name: *const ::std::os::raw::c_char) -> Class; + pub fn objc_lookUpClass(name: *const ::std::os::raw::c_char) -> Class; + pub fn objc_registerClassPair(cls: Class); + pub fn objc_registerProtocol(proto: *mut Protocol); + pub fn objc_removeAssociatedObjects(object: id); + pub fn objc_setAssociatedObject( + object: id, + key: *const ::std::os::raw::c_void, + value: id, + policy: objc_AssociationPolicy, + ); + pub fn objc_setEnumerationMutationHandler( + handler: ::std::option::Option, + ); + pub fn objc_setExceptionMatcher(fn_: objc_exception_matcher) -> objc_exception_matcher; + pub fn objc_setExceptionPreprocessor( + fn_: objc_exception_preprocessor, + ) -> objc_exception_preprocessor; + pub fn objc_setForwardHandler( + fwd: *mut ::std::os::raw::c_void, + fwd_stret: *mut ::std::os::raw::c_void, + ); + pub fn objc_setUncaughtExceptionHandler( + fn_: objc_uncaught_exception_handler, + ) -> objc_uncaught_exception_handler; + pub fn objc_sync_enter(obj: id) -> ::std::os::raw::c_int; + pub fn objc_sync_exit(obj: id) -> ::std::os::raw::c_int; + pub fn object_getClass(obj: id) -> Class; + pub fn object_getClassName(obj: id) -> *const ::std::os::raw::c_char; + pub fn object_getIndexedIvars(obj: id) -> *mut ::std::os::raw::c_void; + pub fn object_getIvar(obj: id, ivar: Ivar) -> id; + pub fn object_setClass(obj: id, cls: Class) -> Class; + pub fn object_setIvar(obj: id, ivar: Ivar, value: id); pub fn property_copyAttributeList( property: objc_property_t, outCount: *mut ::std::os::raw::c_uint, @@ -126,29 +164,31 @@ extern "C" { property: objc_property_t, attributeName: *const ::std::os::raw::c_char, ) -> *mut ::std::os::raw::c_char; - pub fn objc_getProtocol(name: *const ::std::os::raw::c_char) -> *mut Protocol; - pub fn objc_copyProtocolList(outCount: *mut ::std::os::raw::c_uint) -> *mut *mut Protocol; - pub fn protocol_conformsToProtocol(proto: *mut Protocol, other: *mut Protocol) -> BOOL; - pub fn protocol_isEqual(proto: *mut Protocol, other: *mut Protocol) -> BOOL; - pub fn protocol_getName(proto: *mut Protocol) -> *const ::std::os::raw::c_char; - pub fn protocol_getMethodDescription( + pub fn property_getAttributes(property: objc_property_t) -> *const ::std::os::raw::c_char; + pub fn property_getName(property: objc_property_t) -> *const ::std::os::raw::c_char; + pub fn protocol_addMethodDescription( proto: *mut Protocol, - aSel: SEL, + name: SEL, + types: *const ::std::os::raw::c_char, isRequiredMethod: BOOL, isInstanceMethod: BOOL, - ) -> objc_method_description; + ); + pub fn protocol_addProperty( + proto: *mut Protocol, + name: *const ::std::os::raw::c_char, + attributes: *const objc_property_attribute_t, + attributeCount: ::std::os::raw::c_uint, + isRequiredProperty: BOOL, + isInstanceProperty: BOOL, + ); + pub fn protocol_addProtocol(proto: *mut Protocol, addition: *mut Protocol); + pub fn protocol_conformsToProtocol(proto: *mut Protocol, other: *mut Protocol) -> BOOL; pub fn protocol_copyMethodDescriptionList( proto: *mut Protocol, isRequiredMethod: BOOL, isInstanceMethod: BOOL, outCount: *mut ::std::os::raw::c_uint, ) -> *mut objc_method_description; - pub fn protocol_getProperty( - proto: *mut Protocol, - name: *const ::std::os::raw::c_char, - isRequiredProperty: BOOL, - isInstanceProperty: BOOL, - ) -> objc_property_t; pub fn protocol_copyPropertyList( proto: *mut Protocol, outCount: *mut ::std::os::raw::c_uint, @@ -157,63 +197,23 @@ extern "C" { proto: *mut Protocol, outCount: *mut ::std::os::raw::c_uint, ) -> *mut *mut Protocol; - pub fn objc_allocateProtocol(name: *const ::std::os::raw::c_char) -> *mut Protocol; - pub fn objc_registerProtocol(proto: *mut Protocol); - pub fn protocol_addMethodDescription( + pub fn protocol_getMethodDescription( proto: *mut Protocol, - name: SEL, - types: *const ::std::os::raw::c_char, + aSel: SEL, isRequiredMethod: BOOL, isInstanceMethod: BOOL, - ); - pub fn protocol_addProtocol(proto: *mut Protocol, addition: *mut Protocol); - pub fn protocol_addProperty( + ) -> objc_method_description; + pub fn protocol_getName(proto: *mut Protocol) -> *const ::std::os::raw::c_char; + pub fn protocol_getProperty( proto: *mut Protocol, name: *const ::std::os::raw::c_char, - attributes: *const objc_property_attribute_t, - attributeCount: ::std::os::raw::c_uint, isRequiredProperty: BOOL, isInstanceProperty: BOOL, - ); - pub fn objc_copyImageNames( - outCount: *mut ::std::os::raw::c_uint, - ) -> *mut *const ::std::os::raw::c_char; - pub fn class_getImageName(cls: Class) -> *const ::std::os::raw::c_char; - pub fn objc_copyClassNamesForImage( - image: *const ::std::os::raw::c_char, - outCount: *mut ::std::os::raw::c_uint, - ) -> *mut *const ::std::os::raw::c_char; + ) -> objc_property_t; + pub fn protocol_isEqual(proto: *mut Protocol, other: *mut Protocol) -> BOOL; + pub fn sel_getName(sel: SEL) -> *const ::std::os::raw::c_char; + pub fn sel_getUid(str_: *const ::std::os::raw::c_char) -> SEL; pub fn sel_isEqual(lhs: SEL, rhs: SEL) -> BOOL; - pub fn objc_enumerationMutation(obj: id); - pub fn objc_setEnumerationMutationHandler( - handler: ::std::option::Option, - ); - pub fn objc_setForwardHandler( - fwd: *mut ::std::os::raw::c_void, - fwd_stret: *mut ::std::os::raw::c_void, - ); - pub fn imp_implementationWithBlock(block: id) -> IMP; - pub fn imp_getBlock(anImp: IMP) -> id; - pub fn imp_removeBlock(anImp: IMP) -> BOOL; - pub fn objc_setAssociatedObject( - object: id, - key: *const ::std::os::raw::c_void, - value: id, - policy: objc_AssociationPolicy, - ); - pub fn objc_getAssociatedObject(object: id, key: *const ::std::os::raw::c_void) -> id; - pub fn objc_removeAssociatedObjects(object: id); - pub fn objc_exception_throw(exception: id); - pub fn objc_exception_rethrow(); - pub fn objc_begin_catch(exc_buf: *mut ::std::os::raw::c_void) -> id; - pub fn objc_end_catch(); - pub fn objc_setExceptionPreprocessor( - fn_: objc_exception_preprocessor, - ) -> objc_exception_preprocessor; - pub fn objc_setExceptionMatcher(fn_: objc_exception_matcher) -> objc_exception_matcher; - pub fn objc_setUncaughtExceptionHandler( - fn_: objc_uncaught_exception_handler, - ) -> objc_uncaught_exception_handler; - pub fn objc_sync_enter(obj: id) -> ::std::os::raw::c_int; - pub fn objc_sync_exit(obj: id) -> ::std::os::raw::c_int; + pub fn sel_isMapped(sel: SEL) -> BOOL; + pub fn sel_registerName(str_: *const ::std::os::raw::c_char) -> SEL; } From fc4f4f799e43c515f4ba22a66f30d4bad6b797a6 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 04:09:57 +0200 Subject: [PATCH 13/36] sys: Simplify bindings by including std types --- objc_sys/src/bindings.rs | 175 +++++++++++++++------------------------ 1 file changed, 69 insertions(+), 106 deletions(-) diff --git a/objc_sys/src/bindings.rs b/objc_sys/src/bindings.rs index f2d513177..c32289e47 100644 --- a/objc_sys/src/bindings.rs +++ b/objc_sys/src/bindings.rs @@ -1,183 +1,146 @@ -/* automatically generated by rust-bindgen 0.59.1 */ +use core::ffi::c_void; +use std::os::raw::{c_char, c_int, c_uint}; use crate::*; extern "C" { pub fn class_addIvar( cls: Class, - name: *const ::std::os::raw::c_char, + name: *const c_char, size: usize, alignment: u8, - types: *const ::std::os::raw::c_char, - ) -> BOOL; - pub fn class_addMethod( - cls: Class, - name: SEL, - imp: IMP, - types: *const ::std::os::raw::c_char, + types: *const c_char, ) -> BOOL; + pub fn class_addMethod(cls: Class, name: SEL, imp: IMP, types: *const c_char) -> BOOL; pub fn class_addProperty( cls: Class, - name: *const ::std::os::raw::c_char, + name: *const c_char, attributes: *const objc_property_attribute_t, - attributeCount: ::std::os::raw::c_uint, + attributeCount: c_uint, ) -> BOOL; pub fn class_addProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; pub fn class_conformsToProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; - pub fn class_copyIvarList(cls: Class, outCount: *mut ::std::os::raw::c_uint) -> *mut Ivar; - pub fn class_copyMethodList(cls: Class, outCount: *mut ::std::os::raw::c_uint) -> *mut Method; - pub fn class_copyPropertyList( - cls: Class, - outCount: *mut ::std::os::raw::c_uint, - ) -> *mut objc_property_t; - pub fn class_copyProtocolList( - cls: Class, - outCount: *mut ::std::os::raw::c_uint, - ) -> *mut *mut Protocol; + pub fn class_copyIvarList(cls: Class, outCount: *mut c_uint) -> *mut Ivar; + pub fn class_copyMethodList(cls: Class, outCount: *mut c_uint) -> *mut Method; + pub fn class_copyPropertyList(cls: Class, outCount: *mut c_uint) -> *mut objc_property_t; + pub fn class_copyProtocolList(cls: Class, outCount: *mut c_uint) -> *mut *mut Protocol; pub fn class_createInstance(cls: Class, extraBytes: usize) -> id; pub fn class_getClassMethod(cls: Class, name: SEL) -> Method; - pub fn class_getClassVariable(cls: Class, name: *const ::std::os::raw::c_char) -> Ivar; - pub fn class_getImageName(cls: Class) -> *const ::std::os::raw::c_char; + pub fn class_getClassVariable(cls: Class, name: *const c_char) -> Ivar; + pub fn class_getImageName(cls: Class) -> *const c_char; pub fn class_getInstanceMethod(cls: Class, name: SEL) -> Method; pub fn class_getInstanceSize(cls: Class) -> usize; - pub fn class_getInstanceVariable(cls: Class, name: *const ::std::os::raw::c_char) -> Ivar; + pub fn class_getInstanceVariable(cls: Class, name: *const c_char) -> Ivar; pub fn class_getIvarLayout(cls: Class) -> *const u8; - pub fn class_getName(cls: Class) -> *const ::std::os::raw::c_char; - pub fn class_getProperty(cls: Class, name: *const ::std::os::raw::c_char) -> objc_property_t; + pub fn class_getName(cls: Class) -> *const c_char; + pub fn class_getProperty(cls: Class, name: *const c_char) -> objc_property_t; pub fn class_getSuperclass(cls: Class) -> Class; - pub fn class_getVersion(cls: Class) -> ::std::os::raw::c_int; + pub fn class_getVersion(cls: Class) -> c_int; pub fn class_getWeakIvarLayout(cls: Class) -> *const u8; pub fn class_isMetaClass(cls: Class) -> BOOL; - pub fn class_replaceMethod( - cls: Class, - name: SEL, - imp: IMP, - types: *const ::std::os::raw::c_char, - ) -> IMP; + pub fn class_replaceMethod(cls: Class, name: SEL, imp: IMP, types: *const c_char) -> IMP; pub fn class_replaceProperty( cls: Class, - name: *const ::std::os::raw::c_char, + name: *const c_char, attributes: *const objc_property_attribute_t, - attributeCount: ::std::os::raw::c_uint, + attributeCount: c_uint, ); pub fn class_respondsToSelector(cls: Class, sel: SEL) -> BOOL; pub fn class_setIvarLayout(cls: Class, layout: *const u8); - pub fn class_setVersion(cls: Class, version: ::std::os::raw::c_int); + pub fn class_setVersion(cls: Class, version: c_int); pub fn class_setWeakIvarLayout(cls: Class, layout: *const u8); pub fn imp_getBlock(anImp: IMP) -> id; pub fn imp_implementationWithBlock(block: id) -> IMP; pub fn imp_removeBlock(anImp: IMP) -> BOOL; - pub fn ivar_getName(v: Ivar) -> *const ::std::os::raw::c_char; + pub fn ivar_getName(v: Ivar) -> *const c_char; pub fn ivar_getOffset(v: Ivar) -> isize; - pub fn ivar_getTypeEncoding(v: Ivar) -> *const ::std::os::raw::c_char; - pub fn method_copyArgumentType( - m: Method, - index: ::std::os::raw::c_uint, - ) -> *mut ::std::os::raw::c_char; - pub fn method_copyReturnType(m: Method) -> *mut ::std::os::raw::c_char; + pub fn ivar_getTypeEncoding(v: Ivar) -> *const c_char; + pub fn method_copyArgumentType(m: Method, index: c_uint) -> *mut c_char; + pub fn method_copyReturnType(m: Method) -> *mut c_char; pub fn method_exchangeImplementations(m1: Method, m2: Method); - pub fn method_getArgumentType( - m: Method, - index: ::std::os::raw::c_uint, - dst: *mut ::std::os::raw::c_char, - dst_len: usize, - ); + pub fn method_getArgumentType(m: Method, index: c_uint, dst: *mut c_char, dst_len: usize); pub fn method_getDescription(m: Method) -> *mut objc_method_description; pub fn method_getImplementation(m: Method) -> IMP; pub fn method_getName(m: Method) -> SEL; - pub fn method_getNumberOfArguments(m: Method) -> ::std::os::raw::c_uint; - pub fn method_getReturnType(m: Method, dst: *mut ::std::os::raw::c_char, dst_len: usize); - pub fn method_getTypeEncoding(m: Method) -> *const ::std::os::raw::c_char; + pub fn method_getNumberOfArguments(m: Method) -> c_uint; + pub fn method_getReturnType(m: Method, dst: *mut c_char, dst_len: usize); + pub fn method_getTypeEncoding(m: Method) -> *const c_char; pub fn method_setImplementation(m: Method, imp: IMP) -> IMP; pub fn objc_allocateClassPair( superclass: Class, - name: *const ::std::os::raw::c_char, + name: *const c_char, extraBytes: usize, ) -> Class; - pub fn objc_allocateProtocol(name: *const ::std::os::raw::c_char) -> *mut Protocol; - pub fn objc_begin_catch(exc_buf: *mut ::std::os::raw::c_void) -> id; - pub fn objc_copyClassList(outCount: *mut ::std::os::raw::c_uint) -> *mut Class; + pub fn objc_allocateProtocol(name: *const c_char) -> *mut Protocol; + pub fn objc_begin_catch(exc_buf: *mut c_void) -> id; + pub fn objc_copyClassList(outCount: *mut c_uint) -> *mut Class; pub fn objc_copyClassNamesForImage( - image: *const ::std::os::raw::c_char, - outCount: *mut ::std::os::raw::c_uint, - ) -> *mut *const ::std::os::raw::c_char; - pub fn objc_copyImageNames( - outCount: *mut ::std::os::raw::c_uint, - ) -> *mut *const ::std::os::raw::c_char; - pub fn objc_copyProtocolList(outCount: *mut ::std::os::raw::c_uint) -> *mut *mut Protocol; + image: *const c_char, + outCount: *mut c_uint, + ) -> *mut *const c_char; + pub fn objc_copyImageNames(outCount: *mut c_uint) -> *mut *const c_char; + pub fn objc_copyProtocolList(outCount: *mut c_uint) -> *mut *mut Protocol; pub fn objc_disposeClassPair(cls: Class); - pub fn objc_duplicateClass( - original: Class, - name: *const ::std::os::raw::c_char, - extraBytes: usize, - ) -> Class; + pub fn objc_duplicateClass(original: Class, name: *const c_char, extraBytes: usize) -> Class; pub fn objc_end_catch(); pub fn objc_enumerationMutation(obj: id); pub fn objc_exception_rethrow(); pub fn objc_exception_throw(exception: id); - pub fn objc_getAssociatedObject(object: id, key: *const ::std::os::raw::c_void) -> id; - pub fn objc_getClass(name: *const ::std::os::raw::c_char) -> Class; - pub fn objc_getClassList( - buffer: *mut Class, - bufferCount: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; - pub fn objc_getMetaClass(name: *const ::std::os::raw::c_char) -> Class; - pub fn objc_getProtocol(name: *const ::std::os::raw::c_char) -> *mut Protocol; - pub fn objc_getRequiredClass(name: *const ::std::os::raw::c_char) -> Class; - pub fn objc_lookUpClass(name: *const ::std::os::raw::c_char) -> Class; + pub fn objc_getAssociatedObject(object: id, key: *const c_void) -> id; + pub fn objc_getClass(name: *const c_char) -> Class; + pub fn objc_getClassList(buffer: *mut Class, bufferCount: c_int) -> c_int; + pub fn objc_getMetaClass(name: *const c_char) -> Class; + pub fn objc_getProtocol(name: *const c_char) -> *mut Protocol; + pub fn objc_getRequiredClass(name: *const c_char) -> Class; + pub fn objc_lookUpClass(name: *const c_char) -> Class; pub fn objc_registerClassPair(cls: Class); pub fn objc_registerProtocol(proto: *mut Protocol); pub fn objc_removeAssociatedObjects(object: id); pub fn objc_setAssociatedObject( object: id, - key: *const ::std::os::raw::c_void, + key: *const c_void, value: id, policy: objc_AssociationPolicy, ); - pub fn objc_setEnumerationMutationHandler( - handler: ::std::option::Option, - ); + pub fn objc_setEnumerationMutationHandler(handler: Option); pub fn objc_setExceptionMatcher(fn_: objc_exception_matcher) -> objc_exception_matcher; pub fn objc_setExceptionPreprocessor( fn_: objc_exception_preprocessor, ) -> objc_exception_preprocessor; - pub fn objc_setForwardHandler( - fwd: *mut ::std::os::raw::c_void, - fwd_stret: *mut ::std::os::raw::c_void, - ); + pub fn objc_setForwardHandler(fwd: *mut c_void, fwd_stret: *mut c_void); pub fn objc_setUncaughtExceptionHandler( fn_: objc_uncaught_exception_handler, ) -> objc_uncaught_exception_handler; - pub fn objc_sync_enter(obj: id) -> ::std::os::raw::c_int; - pub fn objc_sync_exit(obj: id) -> ::std::os::raw::c_int; + pub fn objc_sync_enter(obj: id) -> c_int; + pub fn objc_sync_exit(obj: id) -> c_int; pub fn object_getClass(obj: id) -> Class; - pub fn object_getClassName(obj: id) -> *const ::std::os::raw::c_char; - pub fn object_getIndexedIvars(obj: id) -> *mut ::std::os::raw::c_void; + pub fn object_getClassName(obj: id) -> *const c_char; + pub fn object_getIndexedIvars(obj: id) -> *mut c_void; pub fn object_getIvar(obj: id, ivar: Ivar) -> id; pub fn object_setClass(obj: id, cls: Class) -> Class; pub fn object_setIvar(obj: id, ivar: Ivar, value: id); pub fn property_copyAttributeList( property: objc_property_t, - outCount: *mut ::std::os::raw::c_uint, + outCount: *mut c_uint, ) -> *mut objc_property_attribute_t; pub fn property_copyAttributeValue( property: objc_property_t, - attributeName: *const ::std::os::raw::c_char, - ) -> *mut ::std::os::raw::c_char; - pub fn property_getAttributes(property: objc_property_t) -> *const ::std::os::raw::c_char; - pub fn property_getName(property: objc_property_t) -> *const ::std::os::raw::c_char; + attributeName: *const c_char, + ) -> *mut c_char; + pub fn property_getAttributes(property: objc_property_t) -> *const c_char; + pub fn property_getName(property: objc_property_t) -> *const c_char; pub fn protocol_addMethodDescription( proto: *mut Protocol, name: SEL, - types: *const ::std::os::raw::c_char, + types: *const c_char, isRequiredMethod: BOOL, isInstanceMethod: BOOL, ); pub fn protocol_addProperty( proto: *mut Protocol, - name: *const ::std::os::raw::c_char, + name: *const c_char, attributes: *const objc_property_attribute_t, - attributeCount: ::std::os::raw::c_uint, + attributeCount: c_uint, isRequiredProperty: BOOL, isInstanceProperty: BOOL, ); @@ -187,15 +150,15 @@ extern "C" { proto: *mut Protocol, isRequiredMethod: BOOL, isInstanceMethod: BOOL, - outCount: *mut ::std::os::raw::c_uint, + outCount: *mut c_uint, ) -> *mut objc_method_description; pub fn protocol_copyPropertyList( proto: *mut Protocol, - outCount: *mut ::std::os::raw::c_uint, + outCount: *mut c_uint, ) -> *mut objc_property_t; pub fn protocol_copyProtocolList( proto: *mut Protocol, - outCount: *mut ::std::os::raw::c_uint, + outCount: *mut c_uint, ) -> *mut *mut Protocol; pub fn protocol_getMethodDescription( proto: *mut Protocol, @@ -203,17 +166,17 @@ extern "C" { isRequiredMethod: BOOL, isInstanceMethod: BOOL, ) -> objc_method_description; - pub fn protocol_getName(proto: *mut Protocol) -> *const ::std::os::raw::c_char; + pub fn protocol_getName(proto: *mut Protocol) -> *const c_char; pub fn protocol_getProperty( proto: *mut Protocol, - name: *const ::std::os::raw::c_char, + name: *const c_char, isRequiredProperty: BOOL, isInstanceProperty: BOOL, ) -> objc_property_t; pub fn protocol_isEqual(proto: *mut Protocol, other: *mut Protocol) -> BOOL; - pub fn sel_getName(sel: SEL) -> *const ::std::os::raw::c_char; - pub fn sel_getUid(str_: *const ::std::os::raw::c_char) -> SEL; + pub fn sel_getName(sel: SEL) -> *const c_char; + pub fn sel_getUid(str_: *const c_char) -> SEL; pub fn sel_isEqual(lhs: SEL, rhs: SEL) -> BOOL; pub fn sel_isMapped(sel: SEL) -> BOOL; - pub fn sel_registerName(str_: *const ::std::os::raw::c_char) -> SEL; + pub fn sel_registerName(str_: *const c_char) -> SEL; } From 5446efaf52829c23baf8c52742c91dcd915b5561 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 04:15:36 +0200 Subject: [PATCH 14/36] sys: Use preferred types in bindings Makes it possible to assign which pointers are mutable and which are immutable. --- objc_sys/src/bindings.rs | 240 +++++++++++++++++++++++---------------- 1 file changed, 144 insertions(+), 96 deletions(-) diff --git a/objc_sys/src/bindings.rs b/objc_sys/src/bindings.rs index c32289e47..6e9e36159 100644 --- a/objc_sys/src/bindings.rs +++ b/objc_sys/src/bindings.rs @@ -1,108 +1,153 @@ use core::ffi::c_void; use std::os::raw::{c_char, c_int, c_uint}; -use crate::*; +use crate::{ + objc_AssociationPolicy, objc_class, objc_exception_matcher, objc_exception_preprocessor, + objc_ivar, objc_method, objc_method_description, objc_object, objc_property_attribute_t, + objc_property_t, objc_protocol, objc_selector, objc_uncaught_exception_handler, BOOL, IMP, +}; extern "C" { pub fn class_addIvar( - cls: Class, + cls: *mut objc_class, name: *const c_char, size: usize, alignment: u8, types: *const c_char, ) -> BOOL; - pub fn class_addMethod(cls: Class, name: SEL, imp: IMP, types: *const c_char) -> BOOL; + pub fn class_addMethod( + cls: *mut objc_class, + name: *const objc_selector, + imp: IMP, + types: *const c_char, + ) -> BOOL; pub fn class_addProperty( - cls: Class, + cls: *mut objc_class, name: *const c_char, attributes: *const objc_property_attribute_t, attributeCount: c_uint, ) -> BOOL; - pub fn class_addProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; - pub fn class_conformsToProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; - pub fn class_copyIvarList(cls: Class, outCount: *mut c_uint) -> *mut Ivar; - pub fn class_copyMethodList(cls: Class, outCount: *mut c_uint) -> *mut Method; - pub fn class_copyPropertyList(cls: Class, outCount: *mut c_uint) -> *mut objc_property_t; - pub fn class_copyProtocolList(cls: Class, outCount: *mut c_uint) -> *mut *mut Protocol; - pub fn class_createInstance(cls: Class, extraBytes: usize) -> id; - pub fn class_getClassMethod(cls: Class, name: SEL) -> Method; - pub fn class_getClassVariable(cls: Class, name: *const c_char) -> Ivar; - pub fn class_getImageName(cls: Class) -> *const c_char; - pub fn class_getInstanceMethod(cls: Class, name: SEL) -> Method; - pub fn class_getInstanceSize(cls: Class) -> usize; - pub fn class_getInstanceVariable(cls: Class, name: *const c_char) -> Ivar; - pub fn class_getIvarLayout(cls: Class) -> *const u8; - pub fn class_getName(cls: Class) -> *const c_char; - pub fn class_getProperty(cls: Class, name: *const c_char) -> objc_property_t; - pub fn class_getSuperclass(cls: Class) -> Class; - pub fn class_getVersion(cls: Class) -> c_int; - pub fn class_getWeakIvarLayout(cls: Class) -> *const u8; - pub fn class_isMetaClass(cls: Class) -> BOOL; - pub fn class_replaceMethod(cls: Class, name: SEL, imp: IMP, types: *const c_char) -> IMP; + pub fn class_addProtocol(cls: *mut objc_class, protocol: *mut objc_protocol) -> BOOL; + pub fn class_conformsToProtocol(cls: *mut objc_class, protocol: *mut objc_protocol) -> BOOL; + pub fn class_copyIvarList(cls: *mut objc_class, outCount: *mut c_uint) + -> *mut *const objc_ivar; + pub fn class_copyMethodList( + cls: *mut objc_class, + outCount: *mut c_uint, + ) -> *mut *mut objc_method; + pub fn class_copyPropertyList( + cls: *mut objc_class, + outCount: *mut c_uint, + ) -> *mut objc_property_t; + pub fn class_copyProtocolList( + cls: *mut objc_class, + outCount: *mut c_uint, + ) -> *mut *mut objc_protocol; + pub fn class_createInstance(cls: *mut objc_class, extraBytes: usize) -> *mut objc_object; + pub fn class_getClassMethod( + cls: *mut objc_class, + name: *const objc_selector, + ) -> *mut objc_method; + pub fn class_getClassVariable(cls: *mut objc_class, name: *const c_char) -> *const objc_ivar; + pub fn class_getImageName(cls: *mut objc_class) -> *const c_char; + pub fn class_getInstanceMethod( + cls: *mut objc_class, + name: *const objc_selector, + ) -> *mut objc_method; + pub fn class_getInstanceSize(cls: *mut objc_class) -> usize; + pub fn class_getInstanceVariable(cls: *mut objc_class, name: *const c_char) + -> *const objc_ivar; + pub fn class_getIvarLayout(cls: *mut objc_class) -> *const u8; + pub fn class_getName(cls: *mut objc_class) -> *const c_char; + pub fn class_getProperty(cls: *mut objc_class, name: *const c_char) -> objc_property_t; + pub fn class_getSuperclass(cls: *mut objc_class) -> *mut objc_class; + pub fn class_getVersion(cls: *mut objc_class) -> c_int; + pub fn class_getWeakIvarLayout(cls: *mut objc_class) -> *const u8; + pub fn class_isMetaClass(cls: *mut objc_class) -> BOOL; + pub fn class_replaceMethod( + cls: *mut objc_class, + name: *const objc_selector, + imp: IMP, + types: *const c_char, + ) -> IMP; pub fn class_replaceProperty( - cls: Class, + cls: *mut objc_class, name: *const c_char, attributes: *const objc_property_attribute_t, attributeCount: c_uint, ); - pub fn class_respondsToSelector(cls: Class, sel: SEL) -> BOOL; - pub fn class_setIvarLayout(cls: Class, layout: *const u8); - pub fn class_setVersion(cls: Class, version: c_int); - pub fn class_setWeakIvarLayout(cls: Class, layout: *const u8); - pub fn imp_getBlock(anImp: IMP) -> id; - pub fn imp_implementationWithBlock(block: id) -> IMP; + pub fn class_respondsToSelector(cls: *mut objc_class, sel: *const objc_selector) -> BOOL; + pub fn class_setIvarLayout(cls: *mut objc_class, layout: *const u8); + pub fn class_setVersion(cls: *mut objc_class, version: c_int); + pub fn class_setWeakIvarLayout(cls: *mut objc_class, layout: *const u8); + pub fn imp_getBlock(anImp: IMP) -> *mut objc_object; + pub fn imp_implementationWithBlock(block: *mut objc_object) -> IMP; pub fn imp_removeBlock(anImp: IMP) -> BOOL; - pub fn ivar_getName(v: Ivar) -> *const c_char; - pub fn ivar_getOffset(v: Ivar) -> isize; - pub fn ivar_getTypeEncoding(v: Ivar) -> *const c_char; - pub fn method_copyArgumentType(m: Method, index: c_uint) -> *mut c_char; - pub fn method_copyReturnType(m: Method) -> *mut c_char; - pub fn method_exchangeImplementations(m1: Method, m2: Method); - pub fn method_getArgumentType(m: Method, index: c_uint, dst: *mut c_char, dst_len: usize); - pub fn method_getDescription(m: Method) -> *mut objc_method_description; - pub fn method_getImplementation(m: Method) -> IMP; - pub fn method_getName(m: Method) -> SEL; - pub fn method_getNumberOfArguments(m: Method) -> c_uint; - pub fn method_getReturnType(m: Method, dst: *mut c_char, dst_len: usize); - pub fn method_getTypeEncoding(m: Method) -> *const c_char; - pub fn method_setImplementation(m: Method, imp: IMP) -> IMP; + pub fn ivar_getName(v: *const objc_ivar) -> *const c_char; + pub fn ivar_getOffset(v: *const objc_ivar) -> isize; + pub fn ivar_getTypeEncoding(v: *const objc_ivar) -> *const c_char; + pub fn method_copyArgumentType(m: *mut objc_method, index: c_uint) -> *mut c_char; + pub fn method_copyReturnType(m: *mut objc_method) -> *mut c_char; + pub fn method_exchangeImplementations(m1: *mut objc_method, m2: *mut objc_method); + pub fn method_getArgumentType( + m: *mut objc_method, + index: c_uint, + dst: *mut c_char, + dst_len: usize, + ); + pub fn method_getDescription(m: *mut objc_method) -> *mut objc_method_description; + pub fn method_getImplementation(m: *mut objc_method) -> IMP; + pub fn method_getName(m: *mut objc_method) -> *const objc_selector; + pub fn method_getNumberOfArguments(m: *mut objc_method) -> c_uint; + pub fn method_getReturnType(m: *mut objc_method, dst: *mut c_char, dst_len: usize); + pub fn method_getTypeEncoding(m: *mut objc_method) -> *const c_char; + pub fn method_setImplementation(m: *mut objc_method, imp: IMP) -> IMP; pub fn objc_allocateClassPair( - superclass: Class, + superclass: *mut objc_class, name: *const c_char, extraBytes: usize, - ) -> Class; - pub fn objc_allocateProtocol(name: *const c_char) -> *mut Protocol; - pub fn objc_begin_catch(exc_buf: *mut c_void) -> id; - pub fn objc_copyClassList(outCount: *mut c_uint) -> *mut Class; + ) -> *mut objc_class; + pub fn objc_allocateProtocol(name: *const c_char) -> *mut objc_protocol; + pub fn objc_begin_catch(exc_buf: *mut c_void) -> *mut objc_object; + pub fn objc_copyClassList(outCount: *mut c_uint) -> *mut *mut objc_class; pub fn objc_copyClassNamesForImage( image: *const c_char, outCount: *mut c_uint, ) -> *mut *const c_char; pub fn objc_copyImageNames(outCount: *mut c_uint) -> *mut *const c_char; - pub fn objc_copyProtocolList(outCount: *mut c_uint) -> *mut *mut Protocol; - pub fn objc_disposeClassPair(cls: Class); - pub fn objc_duplicateClass(original: Class, name: *const c_char, extraBytes: usize) -> Class; + pub fn objc_copyProtocolList(outCount: *mut c_uint) -> *mut *mut objc_protocol; + pub fn objc_disposeClassPair(cls: *mut objc_class); + pub fn objc_duplicateClass( + original: *mut objc_class, + name: *const c_char, + extraBytes: usize, + ) -> *mut objc_class; pub fn objc_end_catch(); - pub fn objc_enumerationMutation(obj: id); + pub fn objc_enumerationMutation(obj: *mut objc_object); pub fn objc_exception_rethrow(); - pub fn objc_exception_throw(exception: id); - pub fn objc_getAssociatedObject(object: id, key: *const c_void) -> id; - pub fn objc_getClass(name: *const c_char) -> Class; - pub fn objc_getClassList(buffer: *mut Class, bufferCount: c_int) -> c_int; - pub fn objc_getMetaClass(name: *const c_char) -> Class; - pub fn objc_getProtocol(name: *const c_char) -> *mut Protocol; - pub fn objc_getRequiredClass(name: *const c_char) -> Class; - pub fn objc_lookUpClass(name: *const c_char) -> Class; - pub fn objc_registerClassPair(cls: Class); - pub fn objc_registerProtocol(proto: *mut Protocol); - pub fn objc_removeAssociatedObjects(object: id); + pub fn objc_exception_throw(exception: *mut objc_object); + pub fn objc_getAssociatedObject( + object: *mut objc_object, + key: *const c_void, + ) -> *mut objc_object; + pub fn objc_getClass(name: *const c_char) -> *mut objc_class; + pub fn objc_getClassList(buffer: *mut *mut objc_class, bufferCount: c_int) -> c_int; + pub fn objc_getMetaClass(name: *const c_char) -> *mut objc_class; + pub fn objc_getProtocol(name: *const c_char) -> *mut objc_protocol; + pub fn objc_getRequiredClass(name: *const c_char) -> *mut objc_class; + pub fn objc_lookUpClass(name: *const c_char) -> *mut objc_class; + pub fn objc_registerClassPair(cls: *mut objc_class); + pub fn objc_registerProtocol(proto: *mut objc_protocol); + pub fn objc_removeAssociatedObjects(object: *mut objc_object); pub fn objc_setAssociatedObject( - object: id, + object: *mut objc_object, key: *const c_void, - value: id, + value: *mut objc_object, policy: objc_AssociationPolicy, ); - pub fn objc_setEnumerationMutationHandler(handler: Option); + pub fn objc_setEnumerationMutationHandler( + handler: Option, + ); pub fn objc_setExceptionMatcher(fn_: objc_exception_matcher) -> objc_exception_matcher; pub fn objc_setExceptionPreprocessor( fn_: objc_exception_preprocessor, @@ -111,14 +156,14 @@ extern "C" { pub fn objc_setUncaughtExceptionHandler( fn_: objc_uncaught_exception_handler, ) -> objc_uncaught_exception_handler; - pub fn objc_sync_enter(obj: id) -> c_int; - pub fn objc_sync_exit(obj: id) -> c_int; - pub fn object_getClass(obj: id) -> Class; - pub fn object_getClassName(obj: id) -> *const c_char; - pub fn object_getIndexedIvars(obj: id) -> *mut c_void; - pub fn object_getIvar(obj: id, ivar: Ivar) -> id; - pub fn object_setClass(obj: id, cls: Class) -> Class; - pub fn object_setIvar(obj: id, ivar: Ivar, value: id); + pub fn objc_sync_enter(obj: *mut objc_object) -> c_int; + pub fn objc_sync_exit(obj: *mut objc_object) -> c_int; + pub fn object_getClass(obj: *mut objc_object) -> *mut objc_class; + pub fn object_getClassName(obj: *mut objc_object) -> *const c_char; + pub fn object_getIndexedIvars(obj: *mut objc_object) -> *mut c_void; + pub fn object_getIvar(obj: *mut objc_object, ivar: *const objc_ivar) -> *mut objc_object; + pub fn object_setClass(obj: *mut objc_object, cls: *mut objc_class) -> *mut objc_class; + pub fn object_setIvar(obj: *mut objc_object, ivar: *const objc_ivar, value: *mut objc_object); pub fn property_copyAttributeList( property: objc_property_t, outCount: *mut c_uint, @@ -130,53 +175,56 @@ extern "C" { pub fn property_getAttributes(property: objc_property_t) -> *const c_char; pub fn property_getName(property: objc_property_t) -> *const c_char; pub fn protocol_addMethodDescription( - proto: *mut Protocol, - name: SEL, + proto: *mut objc_protocol, + name: *const objc_selector, types: *const c_char, isRequiredMethod: BOOL, isInstanceMethod: BOOL, ); pub fn protocol_addProperty( - proto: *mut Protocol, + proto: *mut objc_protocol, name: *const c_char, attributes: *const objc_property_attribute_t, attributeCount: c_uint, isRequiredProperty: BOOL, isInstanceProperty: BOOL, ); - pub fn protocol_addProtocol(proto: *mut Protocol, addition: *mut Protocol); - pub fn protocol_conformsToProtocol(proto: *mut Protocol, other: *mut Protocol) -> BOOL; + pub fn protocol_addProtocol(proto: *mut objc_protocol, addition: *mut objc_protocol); + pub fn protocol_conformsToProtocol( + proto: *mut objc_protocol, + other: *mut objc_protocol, + ) -> BOOL; pub fn protocol_copyMethodDescriptionList( - proto: *mut Protocol, + proto: *mut objc_protocol, isRequiredMethod: BOOL, isInstanceMethod: BOOL, outCount: *mut c_uint, ) -> *mut objc_method_description; pub fn protocol_copyPropertyList( - proto: *mut Protocol, + proto: *mut objc_protocol, outCount: *mut c_uint, ) -> *mut objc_property_t; pub fn protocol_copyProtocolList( - proto: *mut Protocol, + proto: *mut objc_protocol, outCount: *mut c_uint, - ) -> *mut *mut Protocol; + ) -> *mut *mut objc_protocol; pub fn protocol_getMethodDescription( - proto: *mut Protocol, - aSel: SEL, + proto: *mut objc_protocol, + aSel: *const objc_selector, isRequiredMethod: BOOL, isInstanceMethod: BOOL, ) -> objc_method_description; - pub fn protocol_getName(proto: *mut Protocol) -> *const c_char; + pub fn protocol_getName(proto: *mut objc_protocol) -> *const c_char; pub fn protocol_getProperty( - proto: *mut Protocol, + proto: *mut objc_protocol, name: *const c_char, isRequiredProperty: BOOL, isInstanceProperty: BOOL, ) -> objc_property_t; - pub fn protocol_isEqual(proto: *mut Protocol, other: *mut Protocol) -> BOOL; - pub fn sel_getName(sel: SEL) -> *const c_char; - pub fn sel_getUid(str_: *const c_char) -> SEL; - pub fn sel_isEqual(lhs: SEL, rhs: SEL) -> BOOL; - pub fn sel_isMapped(sel: SEL) -> BOOL; - pub fn sel_registerName(str_: *const c_char) -> SEL; + pub fn protocol_isEqual(proto: *mut objc_protocol, other: *mut objc_protocol) -> BOOL; + pub fn sel_getName(sel: *const objc_selector) -> *const c_char; + pub fn sel_getUid(str_: *const c_char) -> *const objc_selector; + pub fn sel_isEqual(lhs: *const objc_selector, rhs: *const objc_selector) -> BOOL; + pub fn sel_isMapped(sel: *const objc_selector) -> BOOL; + pub fn sel_registerName(str_: *const c_char) -> *const objc_selector; } From 75d42b4e366808ae993b040f0daca2ac992191f0 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 04:43:48 +0200 Subject: [PATCH 15/36] sys: Split bindings.rs into separate files --- objc_sys/src/bindings.rs | 230 -------------------------------------- objc_sys/src/class.rs | 101 +++++++++++++++++ objc_sys/src/exception.rs | 24 ++++ objc_sys/src/lib.rs | 17 ++- objc_sys/src/method.rs | 22 ++++ objc_sys/src/object.rs | 13 +++ objc_sys/src/property.rs | 16 +++ objc_sys/src/protocol.rs | 63 +++++++++++ objc_sys/src/selector.rs | 11 ++ objc_sys/src/various.rs | 38 +++++++ 10 files changed, 304 insertions(+), 231 deletions(-) delete mode 100644 objc_sys/src/bindings.rs create mode 100644 objc_sys/src/class.rs create mode 100644 objc_sys/src/exception.rs create mode 100644 objc_sys/src/method.rs create mode 100644 objc_sys/src/object.rs create mode 100644 objc_sys/src/property.rs create mode 100644 objc_sys/src/protocol.rs create mode 100644 objc_sys/src/selector.rs create mode 100644 objc_sys/src/various.rs diff --git a/objc_sys/src/bindings.rs b/objc_sys/src/bindings.rs deleted file mode 100644 index 6e9e36159..000000000 --- a/objc_sys/src/bindings.rs +++ /dev/null @@ -1,230 +0,0 @@ -use core::ffi::c_void; -use std::os::raw::{c_char, c_int, c_uint}; - -use crate::{ - objc_AssociationPolicy, objc_class, objc_exception_matcher, objc_exception_preprocessor, - objc_ivar, objc_method, objc_method_description, objc_object, objc_property_attribute_t, - objc_property_t, objc_protocol, objc_selector, objc_uncaught_exception_handler, BOOL, IMP, -}; - -extern "C" { - pub fn class_addIvar( - cls: *mut objc_class, - name: *const c_char, - size: usize, - alignment: u8, - types: *const c_char, - ) -> BOOL; - pub fn class_addMethod( - cls: *mut objc_class, - name: *const objc_selector, - imp: IMP, - types: *const c_char, - ) -> BOOL; - pub fn class_addProperty( - cls: *mut objc_class, - name: *const c_char, - attributes: *const objc_property_attribute_t, - attributeCount: c_uint, - ) -> BOOL; - pub fn class_addProtocol(cls: *mut objc_class, protocol: *mut objc_protocol) -> BOOL; - pub fn class_conformsToProtocol(cls: *mut objc_class, protocol: *mut objc_protocol) -> BOOL; - pub fn class_copyIvarList(cls: *mut objc_class, outCount: *mut c_uint) - -> *mut *const objc_ivar; - pub fn class_copyMethodList( - cls: *mut objc_class, - outCount: *mut c_uint, - ) -> *mut *mut objc_method; - pub fn class_copyPropertyList( - cls: *mut objc_class, - outCount: *mut c_uint, - ) -> *mut objc_property_t; - pub fn class_copyProtocolList( - cls: *mut objc_class, - outCount: *mut c_uint, - ) -> *mut *mut objc_protocol; - pub fn class_createInstance(cls: *mut objc_class, extraBytes: usize) -> *mut objc_object; - pub fn class_getClassMethod( - cls: *mut objc_class, - name: *const objc_selector, - ) -> *mut objc_method; - pub fn class_getClassVariable(cls: *mut objc_class, name: *const c_char) -> *const objc_ivar; - pub fn class_getImageName(cls: *mut objc_class) -> *const c_char; - pub fn class_getInstanceMethod( - cls: *mut objc_class, - name: *const objc_selector, - ) -> *mut objc_method; - pub fn class_getInstanceSize(cls: *mut objc_class) -> usize; - pub fn class_getInstanceVariable(cls: *mut objc_class, name: *const c_char) - -> *const objc_ivar; - pub fn class_getIvarLayout(cls: *mut objc_class) -> *const u8; - pub fn class_getName(cls: *mut objc_class) -> *const c_char; - pub fn class_getProperty(cls: *mut objc_class, name: *const c_char) -> objc_property_t; - pub fn class_getSuperclass(cls: *mut objc_class) -> *mut objc_class; - pub fn class_getVersion(cls: *mut objc_class) -> c_int; - pub fn class_getWeakIvarLayout(cls: *mut objc_class) -> *const u8; - pub fn class_isMetaClass(cls: *mut objc_class) -> BOOL; - pub fn class_replaceMethod( - cls: *mut objc_class, - name: *const objc_selector, - imp: IMP, - types: *const c_char, - ) -> IMP; - pub fn class_replaceProperty( - cls: *mut objc_class, - name: *const c_char, - attributes: *const objc_property_attribute_t, - attributeCount: c_uint, - ); - pub fn class_respondsToSelector(cls: *mut objc_class, sel: *const objc_selector) -> BOOL; - pub fn class_setIvarLayout(cls: *mut objc_class, layout: *const u8); - pub fn class_setVersion(cls: *mut objc_class, version: c_int); - pub fn class_setWeakIvarLayout(cls: *mut objc_class, layout: *const u8); - pub fn imp_getBlock(anImp: IMP) -> *mut objc_object; - pub fn imp_implementationWithBlock(block: *mut objc_object) -> IMP; - pub fn imp_removeBlock(anImp: IMP) -> BOOL; - pub fn ivar_getName(v: *const objc_ivar) -> *const c_char; - pub fn ivar_getOffset(v: *const objc_ivar) -> isize; - pub fn ivar_getTypeEncoding(v: *const objc_ivar) -> *const c_char; - pub fn method_copyArgumentType(m: *mut objc_method, index: c_uint) -> *mut c_char; - pub fn method_copyReturnType(m: *mut objc_method) -> *mut c_char; - pub fn method_exchangeImplementations(m1: *mut objc_method, m2: *mut objc_method); - pub fn method_getArgumentType( - m: *mut objc_method, - index: c_uint, - dst: *mut c_char, - dst_len: usize, - ); - pub fn method_getDescription(m: *mut objc_method) -> *mut objc_method_description; - pub fn method_getImplementation(m: *mut objc_method) -> IMP; - pub fn method_getName(m: *mut objc_method) -> *const objc_selector; - pub fn method_getNumberOfArguments(m: *mut objc_method) -> c_uint; - pub fn method_getReturnType(m: *mut objc_method, dst: *mut c_char, dst_len: usize); - pub fn method_getTypeEncoding(m: *mut objc_method) -> *const c_char; - pub fn method_setImplementation(m: *mut objc_method, imp: IMP) -> IMP; - pub fn objc_allocateClassPair( - superclass: *mut objc_class, - name: *const c_char, - extraBytes: usize, - ) -> *mut objc_class; - pub fn objc_allocateProtocol(name: *const c_char) -> *mut objc_protocol; - pub fn objc_begin_catch(exc_buf: *mut c_void) -> *mut objc_object; - pub fn objc_copyClassList(outCount: *mut c_uint) -> *mut *mut objc_class; - pub fn objc_copyClassNamesForImage( - image: *const c_char, - outCount: *mut c_uint, - ) -> *mut *const c_char; - pub fn objc_copyImageNames(outCount: *mut c_uint) -> *mut *const c_char; - pub fn objc_copyProtocolList(outCount: *mut c_uint) -> *mut *mut objc_protocol; - pub fn objc_disposeClassPair(cls: *mut objc_class); - pub fn objc_duplicateClass( - original: *mut objc_class, - name: *const c_char, - extraBytes: usize, - ) -> *mut objc_class; - pub fn objc_end_catch(); - pub fn objc_enumerationMutation(obj: *mut objc_object); - pub fn objc_exception_rethrow(); - pub fn objc_exception_throw(exception: *mut objc_object); - pub fn objc_getAssociatedObject( - object: *mut objc_object, - key: *const c_void, - ) -> *mut objc_object; - pub fn objc_getClass(name: *const c_char) -> *mut objc_class; - pub fn objc_getClassList(buffer: *mut *mut objc_class, bufferCount: c_int) -> c_int; - pub fn objc_getMetaClass(name: *const c_char) -> *mut objc_class; - pub fn objc_getProtocol(name: *const c_char) -> *mut objc_protocol; - pub fn objc_getRequiredClass(name: *const c_char) -> *mut objc_class; - pub fn objc_lookUpClass(name: *const c_char) -> *mut objc_class; - pub fn objc_registerClassPair(cls: *mut objc_class); - pub fn objc_registerProtocol(proto: *mut objc_protocol); - pub fn objc_removeAssociatedObjects(object: *mut objc_object); - pub fn objc_setAssociatedObject( - object: *mut objc_object, - key: *const c_void, - value: *mut objc_object, - policy: objc_AssociationPolicy, - ); - pub fn objc_setEnumerationMutationHandler( - handler: Option, - ); - pub fn objc_setExceptionMatcher(fn_: objc_exception_matcher) -> objc_exception_matcher; - pub fn objc_setExceptionPreprocessor( - fn_: objc_exception_preprocessor, - ) -> objc_exception_preprocessor; - pub fn objc_setForwardHandler(fwd: *mut c_void, fwd_stret: *mut c_void); - pub fn objc_setUncaughtExceptionHandler( - fn_: objc_uncaught_exception_handler, - ) -> objc_uncaught_exception_handler; - pub fn objc_sync_enter(obj: *mut objc_object) -> c_int; - pub fn objc_sync_exit(obj: *mut objc_object) -> c_int; - pub fn object_getClass(obj: *mut objc_object) -> *mut objc_class; - pub fn object_getClassName(obj: *mut objc_object) -> *const c_char; - pub fn object_getIndexedIvars(obj: *mut objc_object) -> *mut c_void; - pub fn object_getIvar(obj: *mut objc_object, ivar: *const objc_ivar) -> *mut objc_object; - pub fn object_setClass(obj: *mut objc_object, cls: *mut objc_class) -> *mut objc_class; - pub fn object_setIvar(obj: *mut objc_object, ivar: *const objc_ivar, value: *mut objc_object); - pub fn property_copyAttributeList( - property: objc_property_t, - outCount: *mut c_uint, - ) -> *mut objc_property_attribute_t; - pub fn property_copyAttributeValue( - property: objc_property_t, - attributeName: *const c_char, - ) -> *mut c_char; - pub fn property_getAttributes(property: objc_property_t) -> *const c_char; - pub fn property_getName(property: objc_property_t) -> *const c_char; - pub fn protocol_addMethodDescription( - proto: *mut objc_protocol, - name: *const objc_selector, - types: *const c_char, - isRequiredMethod: BOOL, - isInstanceMethod: BOOL, - ); - pub fn protocol_addProperty( - proto: *mut objc_protocol, - name: *const c_char, - attributes: *const objc_property_attribute_t, - attributeCount: c_uint, - isRequiredProperty: BOOL, - isInstanceProperty: BOOL, - ); - pub fn protocol_addProtocol(proto: *mut objc_protocol, addition: *mut objc_protocol); - pub fn protocol_conformsToProtocol( - proto: *mut objc_protocol, - other: *mut objc_protocol, - ) -> BOOL; - pub fn protocol_copyMethodDescriptionList( - proto: *mut objc_protocol, - isRequiredMethod: BOOL, - isInstanceMethod: BOOL, - outCount: *mut c_uint, - ) -> *mut objc_method_description; - pub fn protocol_copyPropertyList( - proto: *mut objc_protocol, - outCount: *mut c_uint, - ) -> *mut objc_property_t; - pub fn protocol_copyProtocolList( - proto: *mut objc_protocol, - outCount: *mut c_uint, - ) -> *mut *mut objc_protocol; - pub fn protocol_getMethodDescription( - proto: *mut objc_protocol, - aSel: *const objc_selector, - isRequiredMethod: BOOL, - isInstanceMethod: BOOL, - ) -> objc_method_description; - pub fn protocol_getName(proto: *mut objc_protocol) -> *const c_char; - pub fn protocol_getProperty( - proto: *mut objc_protocol, - name: *const c_char, - isRequiredProperty: BOOL, - isInstanceProperty: BOOL, - ) -> objc_property_t; - pub fn protocol_isEqual(proto: *mut objc_protocol, other: *mut objc_protocol) -> BOOL; - pub fn sel_getName(sel: *const objc_selector) -> *const c_char; - pub fn sel_getUid(str_: *const c_char) -> *const objc_selector; - pub fn sel_isEqual(lhs: *const objc_selector, rhs: *const objc_selector) -> BOOL; - pub fn sel_isMapped(sel: *const objc_selector) -> BOOL; - pub fn sel_registerName(str_: *const c_char) -> *const objc_selector; -} diff --git a/objc_sys/src/class.rs b/objc_sys/src/class.rs new file mode 100644 index 000000000..e7988d571 --- /dev/null +++ b/objc_sys/src/class.rs @@ -0,0 +1,101 @@ +use std::os::raw::{c_char, c_int, c_uint}; + +use crate::{ + objc_class, objc_ivar, objc_method, objc_object, objc_property_attribute_t, objc_property_t, + objc_protocol, objc_selector, BOOL, IMP, +}; + +extern "C" { + pub fn objc_getClass(name: *const c_char) -> *const objc_class; + pub fn objc_getRequiredClass(name: *const c_char) -> *mut objc_class; + pub fn objc_lookUpClass(name: *const c_char) -> *mut objc_class; + pub fn objc_getMetaClass(name: *const c_char) -> *mut objc_class; + pub fn objc_copyClassList(outCount: *mut c_uint) -> *mut *const objc_class; + pub fn objc_getClassList(buffer: *mut *const objc_class, bufferCount: c_int) -> c_int; + + pub fn objc_allocateClassPair( + superclass: *mut objc_class, + name: *const c_char, + extraBytes: usize, + ) -> *mut objc_class; + pub fn objc_duplicateClass( + original: *mut objc_class, + name: *const c_char, + extraBytes: usize, + ) -> *mut objc_class; + pub fn objc_disposeClassPair(cls: *mut objc_class); + pub fn objc_registerClassPair(cls: *mut objc_class); + + pub fn class_addIvar( + cls: *mut objc_class, + name: *const c_char, + size: usize, + alignment: u8, + types: *const c_char, + ) -> BOOL; + pub fn class_addMethod( + cls: *mut objc_class, + name: *const objc_selector, + imp: IMP, + types: *const c_char, + ) -> BOOL; + pub fn class_addProperty( + cls: *mut objc_class, + name: *const c_char, + attributes: *const objc_property_attribute_t, + attributeCount: c_uint, + ) -> BOOL; + pub fn class_addProtocol(cls: *mut objc_class, protocol: *mut objc_protocol) -> BOOL; + pub fn class_conformsToProtocol(cls: *mut objc_class, protocol: *mut objc_protocol) -> BOOL; + pub fn class_copyIvarList(cls: *mut objc_class, outCount: *mut c_uint) + -> *mut *const objc_ivar; + pub fn class_copyMethodList( + cls: *mut objc_class, + outCount: *mut c_uint, + ) -> *mut *mut objc_method; + pub fn class_copyPropertyList( + cls: *mut objc_class, + outCount: *mut c_uint, + ) -> *mut objc_property_t; + pub fn class_copyProtocolList( + cls: *mut objc_class, + outCount: *mut c_uint, + ) -> *mut *mut objc_protocol; + pub fn class_createInstance(cls: *mut objc_class, extraBytes: usize) -> *mut objc_object; + pub fn class_getClassMethod( + cls: *mut objc_class, + name: *const objc_selector, + ) -> *mut objc_method; + pub fn class_getClassVariable(cls: *mut objc_class, name: *const c_char) -> *const objc_ivar; + pub fn class_getImageName(cls: *mut objc_class) -> *const c_char; + pub fn class_getInstanceMethod( + cls: *mut objc_class, + name: *const objc_selector, + ) -> *mut objc_method; + pub fn class_getInstanceSize(cls: *mut objc_class) -> usize; + pub fn class_getInstanceVariable(cls: *mut objc_class, name: *const c_char) + -> *const objc_ivar; + pub fn class_getIvarLayout(cls: *mut objc_class) -> *const u8; + pub fn class_getName(cls: *mut objc_class) -> *const c_char; + pub fn class_getProperty(cls: *mut objc_class, name: *const c_char) -> objc_property_t; + pub fn class_getSuperclass(cls: *mut objc_class) -> *mut objc_class; + pub fn class_getVersion(cls: *mut objc_class) -> c_int; + pub fn class_getWeakIvarLayout(cls: *mut objc_class) -> *const u8; + pub fn class_isMetaClass(cls: *mut objc_class) -> BOOL; + pub fn class_replaceMethod( + cls: *mut objc_class, + name: *const objc_selector, + imp: IMP, + types: *const c_char, + ) -> IMP; + pub fn class_replaceProperty( + cls: *mut objc_class, + name: *const c_char, + attributes: *const objc_property_attribute_t, + attributeCount: c_uint, + ); + pub fn class_respondsToSelector(cls: *mut objc_class, sel: *const objc_selector) -> BOOL; + pub fn class_setIvarLayout(cls: *mut objc_class, layout: *const u8); + pub fn class_setVersion(cls: *mut objc_class, version: c_int); + pub fn class_setWeakIvarLayout(cls: *mut objc_class, layout: *const u8); +} diff --git a/objc_sys/src/exception.rs b/objc_sys/src/exception.rs new file mode 100644 index 000000000..f9c3210ab --- /dev/null +++ b/objc_sys/src/exception.rs @@ -0,0 +1,24 @@ +use core::ffi::c_void; + +use crate::{ + objc_exception_matcher, objc_exception_preprocessor, objc_object, + objc_uncaught_exception_handler, +}; + +extern "C" { + pub fn objc_begin_catch(exc_buf: *mut c_void) -> *mut objc_object; + pub fn objc_end_catch(); + pub fn objc_exception_throw(exception: *mut objc_object); + pub fn objc_exception_rethrow(); + + pub fn objc_setEnumerationMutationHandler( + handler: Option, + ); + pub fn objc_setExceptionMatcher(fn_: objc_exception_matcher) -> objc_exception_matcher; + pub fn objc_setExceptionPreprocessor( + fn_: objc_exception_preprocessor, + ) -> objc_exception_preprocessor; + pub fn objc_setUncaughtExceptionHandler( + fn_: objc_uncaught_exception_handler, + ) -> objc_uncaught_exception_handler; +} diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index f37d08885..994a13b1b 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -18,16 +18,31 @@ extern crate std; use std::os::raw::{c_char, c_int, c_uint}; -mod bindings; +mod class; mod constants; +mod exception; mod message; +mod method; +mod object; +mod property; +mod protocol; mod rc; +mod selector; mod types; +mod various; +pub use class::*; pub use constants::*; +pub use exception::*; pub use message::*; +pub use method::*; +pub use object::*; +pub use property::*; +pub use protocol::*; pub use rc::*; +pub use selector::*; pub use types::*; +pub use various::*; #[link(name = "objc", kind = "dylib")] extern "C" { diff --git a/objc_sys/src/method.rs b/objc_sys/src/method.rs new file mode 100644 index 000000000..db7a61d3d --- /dev/null +++ b/objc_sys/src/method.rs @@ -0,0 +1,22 @@ +use std::os::raw::{c_char, c_uint}; + +use crate::{objc_method, objc_method_description, objc_selector, IMP}; + +extern "C" { + pub fn method_copyArgumentType(m: *mut objc_method, index: c_uint) -> *mut c_char; + pub fn method_copyReturnType(m: *mut objc_method) -> *mut c_char; + pub fn method_exchangeImplementations(m1: *mut objc_method, m2: *mut objc_method); + pub fn method_getArgumentType( + m: *mut objc_method, + index: c_uint, + dst: *mut c_char, + dst_len: usize, + ); + pub fn method_getDescription(m: *mut objc_method) -> *mut objc_method_description; + pub fn method_getImplementation(m: *mut objc_method) -> IMP; + pub fn method_getName(m: *mut objc_method) -> *const objc_selector; + pub fn method_getNumberOfArguments(m: *mut objc_method) -> c_uint; + pub fn method_getReturnType(m: *mut objc_method, dst: *mut c_char, dst_len: usize); + pub fn method_getTypeEncoding(m: *mut objc_method) -> *const c_char; + pub fn method_setImplementation(m: *mut objc_method, imp: IMP) -> IMP; +} diff --git a/objc_sys/src/object.rs b/objc_sys/src/object.rs new file mode 100644 index 000000000..4ca8648ad --- /dev/null +++ b/objc_sys/src/object.rs @@ -0,0 +1,13 @@ +use core::ffi::c_void; +use std::os::raw::c_char; + +use crate::{objc_class, objc_ivar, objc_object}; + +extern "C" { + pub fn object_getClass(obj: *mut objc_object) -> *mut objc_class; + pub fn object_getClassName(obj: *mut objc_object) -> *const c_char; + pub fn object_getIndexedIvars(obj: *mut objc_object) -> *mut c_void; + pub fn object_getIvar(obj: *mut objc_object, ivar: *const objc_ivar) -> *mut objc_object; + pub fn object_setClass(obj: *mut objc_object, cls: *mut objc_class) -> *mut objc_class; + pub fn object_setIvar(obj: *mut objc_object, ivar: *const objc_ivar, value: *mut objc_object); +} diff --git a/objc_sys/src/property.rs b/objc_sys/src/property.rs new file mode 100644 index 000000000..565ddfebe --- /dev/null +++ b/objc_sys/src/property.rs @@ -0,0 +1,16 @@ +use std::os::raw::{c_char, c_uint}; + +use crate::{objc_property_attribute_t, objc_property_t}; + +extern "C" { + pub fn property_copyAttributeList( + property: objc_property_t, + outCount: *mut c_uint, + ) -> *mut objc_property_attribute_t; + pub fn property_copyAttributeValue( + property: objc_property_t, + attributeName: *const c_char, + ) -> *mut c_char; + pub fn property_getAttributes(property: objc_property_t) -> *const c_char; + pub fn property_getName(property: objc_property_t) -> *const c_char; +} diff --git a/objc_sys/src/protocol.rs b/objc_sys/src/protocol.rs new file mode 100644 index 000000000..cb7697d95 --- /dev/null +++ b/objc_sys/src/protocol.rs @@ -0,0 +1,63 @@ +use std::os::raw::{c_char, c_uint}; + +use crate::{ + objc_method_description, objc_property_attribute_t, objc_property_t, objc_protocol, + objc_selector, BOOL, +}; + +extern "C" { + pub fn objc_getProtocol(name: *const c_char) -> *mut objc_protocol; + pub fn objc_copyProtocolList(outCount: *mut c_uint) -> *mut *mut objc_protocol; + + pub fn objc_allocateProtocol(name: *const c_char) -> *mut objc_protocol; + pub fn objc_registerProtocol(proto: *mut objc_protocol); + + pub fn protocol_addMethodDescription( + proto: *mut objc_protocol, + name: *const objc_selector, + types: *const c_char, + isRequiredMethod: BOOL, + isInstanceMethod: BOOL, + ); + pub fn protocol_addProperty( + proto: *mut objc_protocol, + name: *const c_char, + attributes: *const objc_property_attribute_t, + attributeCount: c_uint, + isRequiredProperty: BOOL, + isInstanceProperty: BOOL, + ); + pub fn protocol_addProtocol(proto: *mut objc_protocol, addition: *mut objc_protocol); + pub fn protocol_conformsToProtocol( + proto: *mut objc_protocol, + other: *mut objc_protocol, + ) -> BOOL; + pub fn protocol_copyMethodDescriptionList( + proto: *mut objc_protocol, + isRequiredMethod: BOOL, + isInstanceMethod: BOOL, + outCount: *mut c_uint, + ) -> *mut objc_method_description; + pub fn protocol_copyPropertyList( + proto: *mut objc_protocol, + outCount: *mut c_uint, + ) -> *mut objc_property_t; + pub fn protocol_copyProtocolList( + proto: *mut objc_protocol, + outCount: *mut c_uint, + ) -> *mut *mut objc_protocol; + pub fn protocol_getMethodDescription( + proto: *mut objc_protocol, + aSel: *const objc_selector, + isRequiredMethod: BOOL, + isInstanceMethod: BOOL, + ) -> objc_method_description; + pub fn protocol_getName(proto: *mut objc_protocol) -> *const c_char; + pub fn protocol_getProperty( + proto: *mut objc_protocol, + name: *const c_char, + isRequiredProperty: BOOL, + isInstanceProperty: BOOL, + ) -> objc_property_t; + pub fn protocol_isEqual(proto: *mut objc_protocol, other: *mut objc_protocol) -> BOOL; +} diff --git a/objc_sys/src/selector.rs b/objc_sys/src/selector.rs new file mode 100644 index 000000000..d2d75b777 --- /dev/null +++ b/objc_sys/src/selector.rs @@ -0,0 +1,11 @@ +use std::os::raw::c_char; + +use crate::{objc_selector, BOOL}; + +extern "C" { + pub fn sel_getName(sel: *const objc_selector) -> *const c_char; + pub fn sel_getUid(str_: *const c_char) -> *const objc_selector; + pub fn sel_isEqual(lhs: *const objc_selector, rhs: *const objc_selector) -> BOOL; + pub fn sel_isMapped(sel: *const objc_selector) -> BOOL; + pub fn sel_registerName(str_: *const c_char) -> *const objc_selector; +} diff --git a/objc_sys/src/various.rs b/objc_sys/src/various.rs new file mode 100644 index 000000000..661d49154 --- /dev/null +++ b/objc_sys/src/various.rs @@ -0,0 +1,38 @@ +use core::ffi::c_void; +use std::os::raw::{c_char, c_int, c_uint}; + +use crate::{objc_AssociationPolicy, objc_ivar, objc_object, BOOL, IMP}; + +extern "C" { + pub fn imp_getBlock(anImp: IMP) -> *mut objc_object; + pub fn imp_implementationWithBlock(block: *mut objc_object) -> IMP; + pub fn imp_removeBlock(anImp: IMP) -> BOOL; + + pub fn ivar_getName(v: *const objc_ivar) -> *const c_char; + pub fn ivar_getOffset(v: *const objc_ivar) -> isize; + pub fn ivar_getTypeEncoding(v: *const objc_ivar) -> *const c_char; + + pub fn objc_copyClassNamesForImage( + image: *const c_char, + outCount: *mut c_uint, + ) -> *mut *const c_char; + pub fn objc_copyImageNames(outCount: *mut c_uint) -> *mut *const c_char; + + pub fn objc_enumerationMutation(obj: *mut objc_object); + + pub fn objc_getAssociatedObject( + object: *mut objc_object, + key: *const c_void, + ) -> *mut objc_object; + pub fn objc_setAssociatedObject( + object: *mut objc_object, + key: *const c_void, + value: *mut objc_object, + policy: objc_AssociationPolicy, + ); + pub fn objc_removeAssociatedObjects(object: *mut objc_object); + + pub fn objc_setForwardHandler(fwd: *mut c_void, fwd_stret: *mut c_void); + pub fn objc_sync_enter(obj: *mut objc_object) -> c_int; + pub fn objc_sync_exit(obj: *mut objc_object) -> c_int; +} From b736cb57737c064ad9a7a71ac35529294abd4b99 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 04:56:58 +0200 Subject: [PATCH 16/36] sys: Move classes into their respective files --- objc_sys/src/class.rs | 13 ++++- objc_sys/src/exception.rs | 24 +++++++-- objc_sys/src/lib.rs | 10 ++++ objc_sys/src/method.rs | 16 +++++- objc_sys/src/object.rs | 11 +++- objc_sys/src/property.rs | 23 ++++++-- objc_sys/src/protocol.rs | 15 ++++-- objc_sys/src/selector.rs | 9 +++- objc_sys/src/types.rs | 109 ++------------------------------------ objc_sys/src/various.rs | 15 +++++- 10 files changed, 121 insertions(+), 124 deletions(-) diff --git a/objc_sys/src/class.rs b/objc_sys/src/class.rs index e7988d571..81386f03c 100644 --- a/objc_sys/src/class.rs +++ b/objc_sys/src/class.rs @@ -1,10 +1,19 @@ use std::os::raw::{c_char, c_int, c_uint}; use crate::{ - objc_class, objc_ivar, objc_method, objc_object, objc_property_attribute_t, objc_property_t, - objc_protocol, objc_selector, BOOL, IMP, + objc_ivar, objc_method, objc_object, objc_property_attribute_t, objc_property_t, objc_protocol, + objc_selector, OpaqueData, BOOL, IMP, }; +/// An opaque type that represents an Objective-C class. +#[repr(C)] +pub struct objc_class { + // `isa` field is deprecated, so we don't expose it here. + // Use `class_getSuperclass` instead. + _priv: [u8; 0], + _p: OpaqueData, +} + extern "C" { pub fn objc_getClass(name: *const c_char) -> *const objc_class; pub fn objc_getRequiredClass(name: *const c_char) -> *mut objc_class; diff --git a/objc_sys/src/exception.rs b/objc_sys/src/exception.rs index f9c3210ab..7464f94d5 100644 --- a/objc_sys/src/exception.rs +++ b/objc_sys/src/exception.rs @@ -1,9 +1,25 @@ use core::ffi::c_void; +use std::os::raw::c_int; -use crate::{ - objc_exception_matcher, objc_exception_preprocessor, objc_object, - objc_uncaught_exception_handler, -}; +use crate::{objc_class, objc_object}; + +/// Remember that this is non-null! +pub type objc_exception_matcher = + unsafe extern "C" fn(catch_type: *mut objc_class, exception: *mut objc_object) -> c_int; + +/// Remember that this is non-null! +pub type objc_exception_preprocessor = + unsafe extern "C" fn(exception: *mut objc_object) -> *mut objc_object; + +/// Remember that this is non-null! +pub type objc_uncaught_exception_handler = unsafe extern "C" fn(exception: *mut objc_object); + +/// Only available on macOS. +/// +/// Remember that this is non-null! +#[cfg(target_os = "macos")] +pub type objc_exception_handler = + unsafe extern "C" fn(unused: *mut objc_object, context: *mut c_void); extern "C" { pub fn objc_begin_catch(exc_buf: *mut c_void) -> *mut objc_object; diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index 994a13b1b..7f89fd61d 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -16,6 +16,8 @@ extern crate std; +use core::cell::UnsafeCell; +use core::marker::{PhantomData, PhantomPinned}; use std::os::raw::{c_char, c_int, c_uint}; mod class; @@ -44,6 +46,14 @@ pub use selector::*; pub use types::*; pub use various::*; +/// We don't know much about the actual structs, so better mark them `!Send`, +/// `!Sync`, `!Unpin` and as mutable behind shared references. Downstream +/// libraries can always manually opt in to these types afterwards. (It's +/// also less of a breaking change on our part if we re-add these later). +/// +/// TODO: Replace this with `extern type` to also mark it as unsized. +type OpaqueData = PhantomData<(UnsafeCell<*const ()>, PhantomPinned)>; + #[link(name = "objc", kind = "dylib")] extern "C" { pub fn sel_registerName(name: *const c_char) -> *const objc_selector; diff --git a/objc_sys/src/method.rs b/objc_sys/src/method.rs index db7a61d3d..5b16356c9 100644 --- a/objc_sys/src/method.rs +++ b/objc_sys/src/method.rs @@ -1,6 +1,20 @@ use std::os::raw::{c_char, c_uint}; -use crate::{objc_method, objc_method_description, objc_selector, IMP}; +use crate::{objc_selector, OpaqueData, IMP}; + +/// A type that represents a method in a class definition. +#[repr(C)] +pub struct objc_method { + _priv: [u8; 0], + _p: OpaqueData, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_method_description { + pub name: *const objc_selector, + pub types: *mut c_char, +} extern "C" { pub fn method_copyArgumentType(m: *mut objc_method, index: c_uint) -> *mut c_char; diff --git a/objc_sys/src/object.rs b/objc_sys/src/object.rs index 4ca8648ad..3a69d31dc 100644 --- a/objc_sys/src/object.rs +++ b/objc_sys/src/object.rs @@ -1,7 +1,16 @@ use core::ffi::c_void; use std::os::raw::c_char; -use crate::{objc_class, objc_ivar, objc_object}; +use crate::{objc_class, objc_ivar, OpaqueData}; + +/// An opaque type that represents an instance of a class. +#[repr(C)] +pub struct objc_object { + // `isa` field is deprecated, so we don't expose it here. + // Use `object_getClass` instead. + _priv: [u8; 0], + _p: OpaqueData, +} extern "C" { pub fn object_getClass(obj: *mut objc_object) -> *mut objc_class; diff --git a/objc_sys/src/property.rs b/objc_sys/src/property.rs index 565ddfebe..32a574ecc 100644 --- a/objc_sys/src/property.rs +++ b/objc_sys/src/property.rs @@ -1,16 +1,29 @@ use std::os::raw::{c_char, c_uint}; -use crate::{objc_property_attribute_t, objc_property_t}; +use crate::OpaqueData; + +#[repr(C)] +pub struct objc_property { + _priv: [u8; 0], + _p: OpaqueData, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_property_attribute_t { + pub name: *const c_char, + pub value: *const c_char, +} extern "C" { pub fn property_copyAttributeList( - property: objc_property_t, + property: *const objc_property, outCount: *mut c_uint, ) -> *mut objc_property_attribute_t; pub fn property_copyAttributeValue( - property: objc_property_t, + property: *const objc_property, attributeName: *const c_char, ) -> *mut c_char; - pub fn property_getAttributes(property: objc_property_t) -> *const c_char; - pub fn property_getName(property: objc_property_t) -> *const c_char; + pub fn property_getAttributes(property: *const objc_property) -> *const c_char; + pub fn property_getName(property: *const objc_property) -> *const c_char; } diff --git a/objc_sys/src/protocol.rs b/objc_sys/src/protocol.rs index cb7697d95..f66c3b07c 100644 --- a/objc_sys/src/protocol.rs +++ b/objc_sys/src/protocol.rs @@ -1,10 +1,17 @@ use std::os::raw::{c_char, c_uint}; use crate::{ - objc_method_description, objc_property_attribute_t, objc_property_t, objc_protocol, - objc_selector, BOOL, + objc_method_description, objc_property, objc_property_attribute_t, objc_selector, OpaqueData, + BOOL, }; +/// Nonstandard naming, actually... (TODO) +#[repr(C)] +pub struct objc_protocol { + _priv: [u8; 0], + _p: OpaqueData, +} + extern "C" { pub fn objc_getProtocol(name: *const c_char) -> *mut objc_protocol; pub fn objc_copyProtocolList(outCount: *mut c_uint) -> *mut *mut objc_protocol; @@ -41,7 +48,7 @@ extern "C" { pub fn protocol_copyPropertyList( proto: *mut objc_protocol, outCount: *mut c_uint, - ) -> *mut objc_property_t; + ) -> *mut *const objc_property; pub fn protocol_copyProtocolList( proto: *mut objc_protocol, outCount: *mut c_uint, @@ -58,6 +65,6 @@ extern "C" { name: *const c_char, isRequiredProperty: BOOL, isInstanceProperty: BOOL, - ) -> objc_property_t; + ) -> *mut objc_property; pub fn protocol_isEqual(proto: *mut objc_protocol, other: *mut objc_protocol) -> BOOL; } diff --git a/objc_sys/src/selector.rs b/objc_sys/src/selector.rs index d2d75b777..8869e1163 100644 --- a/objc_sys/src/selector.rs +++ b/objc_sys/src/selector.rs @@ -1,6 +1,13 @@ use std::os::raw::c_char; -use crate::{objc_selector, BOOL}; +use crate::{OpaqueData, BOOL}; + +/// A type that represents a method selector. +#[repr(C)] +pub struct objc_selector { + _priv: [u8; 0], + _p: OpaqueData, +} extern "C" { pub fn sel_getName(sel: *const objc_selector) -> *const c_char; diff --git a/objc_sys/src/types.rs b/objc_sys/src/types.rs index 888f97244..b8fb91d99 100644 --- a/objc_sys/src/types.rs +++ b/objc_sys/src/types.rs @@ -1,90 +1,8 @@ -//! Objective-C types and type aliases. +//! Objective-C type aliases. -use core::cell::UnsafeCell; -#[cfg(target_os = "macos")] -use core::ffi::c_void; -use core::marker::{PhantomData, PhantomPinned}; -use std::os::raw::{c_char, c_int}; - -// Opaque types - -/// We don't know much about the actual structs, so better mark them `!Send`, -/// `!Sync`, `!Unpin` and as mutable behind shared references. Downstream -/// libraries can always manually opt in to these types afterwards. (It's -/// also less of a breaking change on our part if we re-add these later). -/// -/// TODO: Replace this with `extern type` to also mark it as unsized. -type OpaqueData = PhantomData<(UnsafeCell<*const ()>, PhantomPinned)>; - -/// A type that represents a method selector. -#[repr(C)] -pub struct objc_selector { - _priv: [u8; 0], - _p: OpaqueData, -} - -/// An opaque type that represents an Objective-C class. -#[repr(C)] -pub struct objc_class { - // `isa` field is deprecated, so we don't expose it here. - // Use `class_getSuperclass` instead. - _priv: [u8; 0], - _p: OpaqueData, -} - -/// An opaque type that represents an instance of a class. -#[repr(C)] -pub struct objc_object { - // `isa` field is deprecated, so we don't expose it here. - // Use `object_getClass` instead. - _priv: [u8; 0], - _p: OpaqueData, -} - -/// A type that represents an instance variable. -#[repr(C)] -pub struct objc_ivar { - _priv: [u8; 0], - _p: OpaqueData, -} - -/// A type that represents a method in a class definition. -#[repr(C)] -pub struct objc_method { - _priv: [u8; 0], - _p: OpaqueData, -} - -/// Nonstandard naming, actually... (TODO) -#[repr(C)] -pub struct objc_protocol { - _priv: [u8; 0], - _p: OpaqueData, -} - -#[repr(C)] -pub struct objc_property { - _priv: [u8; 0], - _p: OpaqueData, -} - -// Data-carrying structs - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_method_description { - pub name: *const objc_selector, - pub types: *mut c_char, -} - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_property_attribute_t { - pub name: *const c_char, - pub value: *const c_char, -} - -// Type aliases +use crate::{ + objc_class, objc_ivar, objc_method, objc_object, objc_property, objc_protocol, objc_selector, +}; /// The Objective-C `BOOL` type. /// @@ -97,19 +15,6 @@ pub type BOOL = u8; #[cfg(target_arch = "aarch64")] pub type BOOL = bool; -/// Remember that this is non-null! -pub type objc_exception_preprocessor = unsafe extern "C" fn(exception: id) -> id; - -/// Remember that this is non-null! -pub type objc_exception_matcher = unsafe extern "C" fn(catch_type: Class, exception: id) -> c_int; - -/// Remember that this is non-null! -pub type objc_uncaught_exception_handler = unsafe extern "C" fn(exception: id); - -/// Remember that this is non-null! -#[cfg(target_os = "macos")] -pub type objc_exception_handler = unsafe extern "C" fn(unused: id, context: *mut c_void); - /// An immutable pointer to a selector. /// /// Type alias provided for convenience. @@ -144,9 +49,3 @@ pub type Protocol = objc_protocol; /// /// Type alias provided for convenience. pub type objc_property_t = *mut objc_property; - -/// A pointer to the start of a method implementation. -/// -/// Remember that this is non-null! -/// Use `Option` where nullability is expected. TODO -pub type IMP = unsafe extern "C" fn(); diff --git a/objc_sys/src/various.rs b/objc_sys/src/various.rs index 661d49154..dc7836462 100644 --- a/objc_sys/src/various.rs +++ b/objc_sys/src/various.rs @@ -1,7 +1,20 @@ use core::ffi::c_void; use std::os::raw::{c_char, c_int, c_uint}; -use crate::{objc_AssociationPolicy, objc_ivar, objc_object, BOOL, IMP}; +use crate::{objc_AssociationPolicy, objc_object, OpaqueData, BOOL}; + +/// A type that represents an instance variable. +#[repr(C)] +pub struct objc_ivar { + _priv: [u8; 0], + _p: OpaqueData, +} + +/// A pointer to the start of a method implementation. +/// +/// Remember that this is non-null! +/// Use `Option` where nullability is expected. TODO +pub type IMP = unsafe extern "C" fn(); extern "C" { pub fn imp_getBlock(anImp: IMP) -> *mut objc_object; From 6cf189ae5fa36497aae36eeafb466117a7f5384e Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 05:31:11 +0200 Subject: [PATCH 17/36] sys: Update variable names and const-ness Also remove redundant (the original) function definitions --- objc_sys/src/class.rs | 92 +++++++++++++++++++++------------------ objc_sys/src/exception.rs | 3 -- objc_sys/src/lib.rs | 92 --------------------------------------- objc_sys/src/method.rs | 24 +++++----- objc_sys/src/object.rs | 11 ++--- objc_sys/src/property.rs | 4 +- objc_sys/src/protocol.rs | 44 +++++++++---------- objc_sys/src/selector.rs | 4 +- objc_sys/src/various.rs | 21 +++++---- 9 files changed, 105 insertions(+), 190 deletions(-) diff --git a/objc_sys/src/class.rs b/objc_sys/src/class.rs index 81386f03c..6ea16a8c5 100644 --- a/objc_sys/src/class.rs +++ b/objc_sys/src/class.rs @@ -1,7 +1,7 @@ use std::os::raw::{c_char, c_int, c_uint}; use crate::{ - objc_ivar, objc_method, objc_object, objc_property_attribute_t, objc_property_t, objc_protocol, + objc_ivar, objc_method, objc_object, objc_property, objc_property_attribute_t, objc_protocol, objc_selector, OpaqueData, BOOL, IMP, }; @@ -16,21 +16,21 @@ pub struct objc_class { extern "C" { pub fn objc_getClass(name: *const c_char) -> *const objc_class; - pub fn objc_getRequiredClass(name: *const c_char) -> *mut objc_class; - pub fn objc_lookUpClass(name: *const c_char) -> *mut objc_class; - pub fn objc_getMetaClass(name: *const c_char) -> *mut objc_class; - pub fn objc_copyClassList(outCount: *mut c_uint) -> *mut *const objc_class; - pub fn objc_getClassList(buffer: *mut *const objc_class, bufferCount: c_int) -> c_int; + pub fn objc_getRequiredClass(name: *const c_char) -> *const objc_class; + pub fn objc_lookUpClass(name: *const c_char) -> *const objc_class; + pub fn objc_getMetaClass(name: *const c_char) -> *const objc_class; + pub fn objc_copyClassList(out_len: *mut c_uint) -> *mut *const objc_class; + pub fn objc_getClassList(buffer: *mut *const objc_class, buffer_len: c_int) -> c_int; pub fn objc_allocateClassPair( - superclass: *mut objc_class, + superclass: *const objc_class, name: *const c_char, - extraBytes: usize, + extra_bytes: usize, ) -> *mut objc_class; pub fn objc_duplicateClass( - original: *mut objc_class, + original: *const objc_class, name: *const c_char, - extraBytes: usize, + extra_bytes: usize, ) -> *mut objc_class; pub fn objc_disposeClassPair(cls: *mut objc_class); pub fn objc_registerClassPair(cls: *mut objc_class); @@ -52,45 +52,51 @@ extern "C" { cls: *mut objc_class, name: *const c_char, attributes: *const objc_property_attribute_t, - attributeCount: c_uint, + attributes_count: c_uint, ) -> BOOL; - pub fn class_addProtocol(cls: *mut objc_class, protocol: *mut objc_protocol) -> BOOL; - pub fn class_conformsToProtocol(cls: *mut objc_class, protocol: *mut objc_protocol) -> BOOL; - pub fn class_copyIvarList(cls: *mut objc_class, outCount: *mut c_uint) - -> *mut *const objc_ivar; + pub fn class_addProtocol(cls: *mut objc_class, protocol: *const objc_protocol) -> BOOL; + pub fn class_conformsToProtocol(cls: *const objc_class, protocol: *const objc_protocol) + -> BOOL; + pub fn class_copyIvarList( + cls: *const objc_class, + out_len: *mut c_uint, + ) -> *mut *const objc_ivar; pub fn class_copyMethodList( - cls: *mut objc_class, - outCount: *mut c_uint, - ) -> *mut *mut objc_method; + cls: *const objc_class, + out_len: *mut c_uint, + ) -> *mut *const objc_method; pub fn class_copyPropertyList( - cls: *mut objc_class, - outCount: *mut c_uint, - ) -> *mut objc_property_t; + cls: *const objc_class, + out_len: *mut c_uint, + ) -> *mut *const objc_property; pub fn class_copyProtocolList( - cls: *mut objc_class, - outCount: *mut c_uint, - ) -> *mut *mut objc_protocol; - pub fn class_createInstance(cls: *mut objc_class, extraBytes: usize) -> *mut objc_object; + cls: *const objc_class, + out_len: *mut c_uint, + ) -> *mut *const objc_protocol; + + pub fn class_createInstance(cls: *const objc_class, extra_bytes: usize) -> *mut objc_object; pub fn class_getClassMethod( - cls: *mut objc_class, + cls: *const objc_class, name: *const objc_selector, - ) -> *mut objc_method; - pub fn class_getClassVariable(cls: *mut objc_class, name: *const c_char) -> *const objc_ivar; - pub fn class_getImageName(cls: *mut objc_class) -> *const c_char; + ) -> *const objc_method; + pub fn class_getClassVariable(cls: *const objc_class, name: *const c_char) -> *const objc_ivar; + pub fn class_getImageName(cls: *const objc_class) -> *const c_char; pub fn class_getInstanceMethod( - cls: *mut objc_class, + cls: *const objc_class, name: *const objc_selector, - ) -> *mut objc_method; - pub fn class_getInstanceSize(cls: *mut objc_class) -> usize; - pub fn class_getInstanceVariable(cls: *mut objc_class, name: *const c_char) - -> *const objc_ivar; - pub fn class_getIvarLayout(cls: *mut objc_class) -> *const u8; - pub fn class_getName(cls: *mut objc_class) -> *const c_char; - pub fn class_getProperty(cls: *mut objc_class, name: *const c_char) -> objc_property_t; - pub fn class_getSuperclass(cls: *mut objc_class) -> *mut objc_class; - pub fn class_getVersion(cls: *mut objc_class) -> c_int; - pub fn class_getWeakIvarLayout(cls: *mut objc_class) -> *const u8; - pub fn class_isMetaClass(cls: *mut objc_class) -> BOOL; + ) -> *const objc_method; + pub fn class_getInstanceSize(cls: *const objc_class) -> usize; + pub fn class_getInstanceVariable( + cls: *const objc_class, + name: *const c_char, + ) -> *const objc_ivar; + pub fn class_getIvarLayout(cls: *const objc_class) -> *const u8; + pub fn class_getName(cls: *const objc_class) -> *const c_char; + pub fn class_getProperty(cls: *const objc_class, name: *const c_char) -> *const objc_property; + pub fn class_getSuperclass(cls: *const objc_class) -> *const objc_class; + pub fn class_getVersion(cls: *const objc_class) -> c_int; + pub fn class_getWeakIvarLayout(cls: *const objc_class) -> *const u8; + pub fn class_isMetaClass(cls: *const objc_class) -> BOOL; pub fn class_replaceMethod( cls: *mut objc_class, name: *const objc_selector, @@ -101,9 +107,9 @@ extern "C" { cls: *mut objc_class, name: *const c_char, attributes: *const objc_property_attribute_t, - attributeCount: c_uint, + attributes_len: c_uint, ); - pub fn class_respondsToSelector(cls: *mut objc_class, sel: *const objc_selector) -> BOOL; + pub fn class_respondsToSelector(cls: *const objc_class, sel: *const objc_selector) -> BOOL; pub fn class_setIvarLayout(cls: *mut objc_class, layout: *const u8); pub fn class_setVersion(cls: *mut objc_class, version: c_int); pub fn class_setWeakIvarLayout(cls: *mut objc_class, layout: *const u8); diff --git a/objc_sys/src/exception.rs b/objc_sys/src/exception.rs index 7464f94d5..a65861a81 100644 --- a/objc_sys/src/exception.rs +++ b/objc_sys/src/exception.rs @@ -27,9 +27,6 @@ extern "C" { pub fn objc_exception_throw(exception: *mut objc_object); pub fn objc_exception_rethrow(); - pub fn objc_setEnumerationMutationHandler( - handler: Option, - ); pub fn objc_setExceptionMatcher(fn_: objc_exception_matcher) -> objc_exception_matcher; pub fn objc_setExceptionPreprocessor( fn_: objc_exception_preprocessor, diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index 7f89fd61d..c7d263191 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -18,7 +18,6 @@ extern crate std; use core::cell::UnsafeCell; use core::marker::{PhantomData, PhantomPinned}; -use std::os::raw::{c_char, c_int, c_uint}; mod class; mod constants; @@ -56,96 +55,5 @@ type OpaqueData = PhantomData<(UnsafeCell<*const ()>, PhantomPinned)>; #[link(name = "objc", kind = "dylib")] extern "C" { - pub fn sel_registerName(name: *const c_char) -> *const objc_selector; - pub fn sel_getName(sel: *const objc_selector) -> *const c_char; - - pub fn class_getName(cls: *const objc_class) -> *const c_char; - pub fn class_getSuperclass(cls: *const objc_class) -> *const objc_class; - pub fn class_getInstanceSize(cls: *const objc_class) -> usize; - pub fn class_getInstanceMethod( - cls: *const objc_class, - sel: *const objc_selector, - ) -> *const objc_method; - pub fn class_getInstanceVariable( - cls: *const objc_class, - name: *const c_char, - ) -> *const objc_ivar; - pub fn class_copyMethodList( - cls: *const objc_class, - outCount: *mut c_uint, - ) -> *mut *const objc_method; - pub fn class_copyIvarList( - cls: *const objc_class, - outCount: *mut c_uint, - ) -> *mut *const objc_ivar; - pub fn class_addMethod( - cls: *mut objc_class, - name: *const objc_selector, - imp: IMP, - types: *const c_char, - ) -> BOOL; - pub fn class_addIvar( - cls: *mut objc_class, - name: *const c_char, - size: usize, - alignment: u8, - types: *const c_char, - ) -> BOOL; - pub fn class_addProtocol(cls: *mut objc_class, proto: *const objc_protocol) -> BOOL; - pub fn class_conformsToProtocol(cls: *const objc_class, proto: *const objc_protocol) -> BOOL; - pub fn class_copyProtocolList( - cls: *const objc_class, - outCount: *mut c_uint, - ) -> *mut *const objc_protocol; - - pub fn objc_allocateClassPair( - superclass: *const objc_class, - name: *const c_char, - extraBytes: usize, - ) -> *mut objc_class; - pub fn objc_disposeClassPair(cls: *mut objc_class); - pub fn objc_registerClassPair(cls: *mut objc_class); - - pub fn class_createInstance(cls: *const objc_class, extraBytes: usize) -> *mut objc_object; pub fn object_dispose(obj: *mut objc_object) -> *mut objc_object; - pub fn object_getClass(obj: *const objc_object) -> *const objc_class; - - pub fn objc_getClassList(buffer: *mut *const objc_class, bufferLen: c_int) -> c_int; - pub fn objc_copyClassList(outCount: *mut c_uint) -> *mut *const objc_class; - pub fn objc_getClass(name: *const c_char) -> *const objc_class; - pub fn objc_getProtocol(name: *const c_char) -> *const objc_protocol; - pub fn objc_copyProtocolList(outCount: *mut c_uint) -> *mut *const objc_protocol; - pub fn objc_allocateProtocol(name: *const c_char) -> *mut objc_protocol; - pub fn objc_registerProtocol(proto: *mut objc_protocol); - - pub fn protocol_addMethodDescription( - proto: *mut objc_protocol, - name: *const objc_selector, - types: *const c_char, - isRequiredMethod: BOOL, - isInstanceMethod: BOOL, - ); - pub fn protocol_addProtocol(proto: *mut objc_protocol, addition: *const objc_protocol); - pub fn protocol_getName(proto: *const objc_protocol) -> *const c_char; - pub fn protocol_isEqual(proto: *const objc_protocol, other: *const objc_protocol) -> BOOL; - pub fn protocol_copyProtocolList( - proto: *const objc_protocol, - outCount: *mut c_uint, - ) -> *mut *const objc_protocol; - pub fn protocol_conformsToProtocol( - proto: *const objc_protocol, - other: *const objc_protocol, - ) -> BOOL; - - pub fn ivar_getName(ivar: *const objc_ivar) -> *const c_char; - pub fn ivar_getOffset(ivar: *const objc_ivar) -> isize; - pub fn ivar_getTypeEncoding(ivar: *const objc_ivar) -> *const c_char; - - pub fn method_getName(method: *const objc_method) -> *const objc_selector; - pub fn method_getImplementation(method: *const objc_method) -> IMP; - pub fn method_copyReturnType(method: *const objc_method) -> *mut c_char; - pub fn method_copyArgumentType(method: *const objc_method, index: c_uint) -> *mut c_char; - pub fn method_getNumberOfArguments(method: *const objc_method) -> c_uint; - pub fn method_setImplementation(method: *mut objc_method, imp: IMP) -> IMP; - pub fn method_exchangeImplementations(m1: *mut objc_method, m2: *mut objc_method); } diff --git a/objc_sys/src/method.rs b/objc_sys/src/method.rs index 5b16356c9..766fc74ca 100644 --- a/objc_sys/src/method.rs +++ b/objc_sys/src/method.rs @@ -13,24 +13,24 @@ pub struct objc_method { #[derive(Debug, Copy, Clone)] pub struct objc_method_description { pub name: *const objc_selector, - pub types: *mut c_char, + pub types: *const c_char, } extern "C" { - pub fn method_copyArgumentType(m: *mut objc_method, index: c_uint) -> *mut c_char; - pub fn method_copyReturnType(m: *mut objc_method) -> *mut c_char; - pub fn method_exchangeImplementations(m1: *mut objc_method, m2: *mut objc_method); + pub fn method_copyArgumentType(method: *const objc_method, index: c_uint) -> *mut c_char; + pub fn method_copyReturnType(method: *const objc_method) -> *mut c_char; + pub fn method_exchangeImplementations(method1: *mut objc_method, method2: *mut objc_method); pub fn method_getArgumentType( - m: *mut objc_method, + method: *const objc_method, index: c_uint, dst: *mut c_char, dst_len: usize, ); - pub fn method_getDescription(m: *mut objc_method) -> *mut objc_method_description; - pub fn method_getImplementation(m: *mut objc_method) -> IMP; - pub fn method_getName(m: *mut objc_method) -> *const objc_selector; - pub fn method_getNumberOfArguments(m: *mut objc_method) -> c_uint; - pub fn method_getReturnType(m: *mut objc_method, dst: *mut c_char, dst_len: usize); - pub fn method_getTypeEncoding(m: *mut objc_method) -> *const c_char; - pub fn method_setImplementation(m: *mut objc_method, imp: IMP) -> IMP; + pub fn method_getDescription(m: *const objc_method) -> *const objc_method_description; + pub fn method_getImplementation(method: *const objc_method) -> IMP; + pub fn method_getName(method: *const objc_method) -> *const objc_selector; + pub fn method_getNumberOfArguments(method: *const objc_method) -> c_uint; + pub fn method_getReturnType(method: *const objc_method, dst: *mut c_char, dst_len: usize); + pub fn method_getTypeEncoding(method: *const objc_method) -> *const c_char; + pub fn method_setImplementation(method: *const objc_method, imp: IMP) -> IMP; } diff --git a/objc_sys/src/object.rs b/objc_sys/src/object.rs index 3a69d31dc..ddb1c52d8 100644 --- a/objc_sys/src/object.rs +++ b/objc_sys/src/object.rs @@ -13,10 +13,11 @@ pub struct objc_object { } extern "C" { - pub fn object_getClass(obj: *mut objc_object) -> *mut objc_class; - pub fn object_getClassName(obj: *mut objc_object) -> *const c_char; - pub fn object_getIndexedIvars(obj: *mut objc_object) -> *mut c_void; - pub fn object_getIvar(obj: *mut objc_object, ivar: *const objc_ivar) -> *mut objc_object; - pub fn object_setClass(obj: *mut objc_object, cls: *mut objc_class) -> *mut objc_class; + pub fn object_getClass(obj: *const objc_object) -> *const objc_class; + pub fn object_getClassName(obj: *const objc_object) -> *const c_char; + pub fn object_getIndexedIvars(obj: *const objc_object) -> *const c_void; + pub fn object_getIvar(obj: *const objc_object, ivar: *const objc_ivar) -> *const objc_object; + + pub fn object_setClass(obj: *mut objc_object, cls: *const objc_class) -> *const objc_class; pub fn object_setIvar(obj: *mut objc_object, ivar: *const objc_ivar, value: *mut objc_object); } diff --git a/objc_sys/src/property.rs b/objc_sys/src/property.rs index 32a574ecc..3be35d048 100644 --- a/objc_sys/src/property.rs +++ b/objc_sys/src/property.rs @@ -18,11 +18,11 @@ pub struct objc_property_attribute_t { extern "C" { pub fn property_copyAttributeList( property: *const objc_property, - outCount: *mut c_uint, + out_len: *mut c_uint, ) -> *mut objc_property_attribute_t; pub fn property_copyAttributeValue( property: *const objc_property, - attributeName: *const c_char, + attribute_name: *const c_char, ) -> *mut c_char; pub fn property_getAttributes(property: *const objc_property) -> *const c_char; pub fn property_getName(property: *const objc_property) -> *const c_char; diff --git a/objc_sys/src/protocol.rs b/objc_sys/src/protocol.rs index f66c3b07c..f72904167 100644 --- a/objc_sys/src/protocol.rs +++ b/objc_sys/src/protocol.rs @@ -13,8 +13,8 @@ pub struct objc_protocol { } extern "C" { - pub fn objc_getProtocol(name: *const c_char) -> *mut objc_protocol; - pub fn objc_copyProtocolList(outCount: *mut c_uint) -> *mut *mut objc_protocol; + pub fn objc_getProtocol(name: *const c_char) -> *const objc_protocol; + pub fn objc_copyProtocolList(out_len: *mut c_uint) -> *mut *const objc_protocol; pub fn objc_allocateProtocol(name: *const c_char) -> *mut objc_protocol; pub fn objc_registerProtocol(proto: *mut objc_protocol); @@ -30,41 +30,41 @@ extern "C" { proto: *mut objc_protocol, name: *const c_char, attributes: *const objc_property_attribute_t, - attributeCount: c_uint, - isRequiredProperty: BOOL, - isInstanceProperty: BOOL, + attributes_len: c_uint, + is_required_property: BOOL, + is_instance_property: BOOL, ); - pub fn protocol_addProtocol(proto: *mut objc_protocol, addition: *mut objc_protocol); + pub fn protocol_addProtocol(proto: *mut objc_protocol, addition: *const objc_protocol); pub fn protocol_conformsToProtocol( - proto: *mut objc_protocol, - other: *mut objc_protocol, + proto: *const objc_protocol, + other: *const objc_protocol, ) -> BOOL; pub fn protocol_copyMethodDescriptionList( - proto: *mut objc_protocol, - isRequiredMethod: BOOL, - isInstanceMethod: BOOL, - outCount: *mut c_uint, + proto: *const objc_protocol, + is_required_method: BOOL, + is_instance_method: BOOL, + out_len: *mut c_uint, ) -> *mut objc_method_description; pub fn protocol_copyPropertyList( - proto: *mut objc_protocol, - outCount: *mut c_uint, + proto: *const objc_protocol, + out_len: *mut c_uint, ) -> *mut *const objc_property; pub fn protocol_copyProtocolList( - proto: *mut objc_protocol, - outCount: *mut c_uint, - ) -> *mut *mut objc_protocol; + proto: *const objc_protocol, + out_len: *mut c_uint, + ) -> *mut *const objc_protocol; pub fn protocol_getMethodDescription( - proto: *mut objc_protocol, + proto: *const objc_protocol, aSel: *const objc_selector, isRequiredMethod: BOOL, isInstanceMethod: BOOL, ) -> objc_method_description; - pub fn protocol_getName(proto: *mut objc_protocol) -> *const c_char; + pub fn protocol_getName(proto: *const objc_protocol) -> *const c_char; pub fn protocol_getProperty( - proto: *mut objc_protocol, + proto: *const objc_protocol, name: *const c_char, isRequiredProperty: BOOL, isInstanceProperty: BOOL, - ) -> *mut objc_property; - pub fn protocol_isEqual(proto: *mut objc_protocol, other: *mut objc_protocol) -> BOOL; + ) -> *const objc_property; + pub fn protocol_isEqual(proto: *const objc_protocol, other: *const objc_protocol) -> BOOL; } diff --git a/objc_sys/src/selector.rs b/objc_sys/src/selector.rs index 8869e1163..788e213f7 100644 --- a/objc_sys/src/selector.rs +++ b/objc_sys/src/selector.rs @@ -11,8 +11,8 @@ pub struct objc_selector { extern "C" { pub fn sel_getName(sel: *const objc_selector) -> *const c_char; - pub fn sel_getUid(str_: *const c_char) -> *const objc_selector; + pub fn sel_getUid(name: *const c_char) -> *const objc_selector; pub fn sel_isEqual(lhs: *const objc_selector, rhs: *const objc_selector) -> BOOL; pub fn sel_isMapped(sel: *const objc_selector) -> BOOL; - pub fn sel_registerName(str_: *const c_char) -> *const objc_selector; + pub fn sel_registerName(name: *const c_char) -> *const objc_selector; } diff --git a/objc_sys/src/various.rs b/objc_sys/src/various.rs index dc7836462..a0a33d3ba 100644 --- a/objc_sys/src/various.rs +++ b/objc_sys/src/various.rs @@ -17,26 +17,29 @@ pub struct objc_ivar { pub type IMP = unsafe extern "C" fn(); extern "C" { - pub fn imp_getBlock(anImp: IMP) -> *mut objc_object; + pub fn imp_getBlock(imp: IMP) -> *mut objc_object; pub fn imp_implementationWithBlock(block: *mut objc_object) -> IMP; - pub fn imp_removeBlock(anImp: IMP) -> BOOL; + pub fn imp_removeBlock(imp: IMP) -> BOOL; - pub fn ivar_getName(v: *const objc_ivar) -> *const c_char; - pub fn ivar_getOffset(v: *const objc_ivar) -> isize; - pub fn ivar_getTypeEncoding(v: *const objc_ivar) -> *const c_char; + pub fn ivar_getName(ivar: *const objc_ivar) -> *const c_char; + pub fn ivar_getOffset(ivar: *const objc_ivar) -> isize; + pub fn ivar_getTypeEncoding(ivar: *const objc_ivar) -> *const c_char; pub fn objc_copyClassNamesForImage( image: *const c_char, - outCount: *mut c_uint, + out_len: *mut c_uint, ) -> *mut *const c_char; - pub fn objc_copyImageNames(outCount: *mut c_uint) -> *mut *const c_char; + pub fn objc_copyImageNames(out_len: *mut c_uint) -> *mut *const c_char; pub fn objc_enumerationMutation(obj: *mut objc_object); + pub fn objc_setEnumerationMutationHandler( + handler: Option, + ); pub fn objc_getAssociatedObject( - object: *mut objc_object, + object: *const objc_object, key: *const c_void, - ) -> *mut objc_object; + ) -> *const objc_object; pub fn objc_setAssociatedObject( object: *mut objc_object, key: *const c_void, From ea5578152d834d91d5ef41c8c8cad67b156d7153 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 14:44:33 +0200 Subject: [PATCH 18/36] sys: Add a few cfg-bound functions --- objc_sys/src/exception.rs | 13 ++++++++++--- objc_sys/src/various.rs | 32 +++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/objc_sys/src/exception.rs b/objc_sys/src/exception.rs index a65861a81..3c13e0925 100644 --- a/objc_sys/src/exception.rs +++ b/objc_sys/src/exception.rs @@ -27,11 +27,18 @@ extern "C" { pub fn objc_exception_throw(exception: *mut objc_object); pub fn objc_exception_rethrow(); - pub fn objc_setExceptionMatcher(fn_: objc_exception_matcher) -> objc_exception_matcher; + pub fn objc_setExceptionMatcher(f: objc_exception_matcher) -> objc_exception_matcher; pub fn objc_setExceptionPreprocessor( - fn_: objc_exception_preprocessor, + f: objc_exception_preprocessor, ) -> objc_exception_preprocessor; pub fn objc_setUncaughtExceptionHandler( - fn_: objc_uncaught_exception_handler, + f: objc_uncaught_exception_handler, ) -> objc_uncaught_exception_handler; + + /// Only available on macOS. + #[cfg(target_os = "macos")] + pub fn objc_addExceptionHandler(f: objc_exception_handler, context: *mut c_void) -> usize; + /// Only available on macOS. + #[cfg(target_os = "macos")] + pub fn objc_removeExceptionHandler(token: usize); } diff --git a/objc_sys/src/various.rs b/objc_sys/src/various.rs index a0a33d3ba..df0e92c5c 100644 --- a/objc_sys/src/various.rs +++ b/objc_sys/src/various.rs @@ -1,7 +1,7 @@ use core::ffi::c_void; use std::os::raw::{c_char, c_int, c_uint}; -use crate::{objc_AssociationPolicy, objc_object, OpaqueData, BOOL}; +use crate::{objc_AssociationPolicy, objc_class, objc_object, OpaqueData, BOOL}; /// A type that represents an instance variable. #[repr(C)] @@ -16,6 +16,19 @@ pub struct objc_ivar { /// Use `Option` where nullability is expected. TODO pub type IMP = unsafe extern "C" fn(); +/// Not available on macOS x86. +/// +/// Remember that this is non-null! +#[cfg(not(all(target_os = "macos", target_arch = "x86")))] +pub type objc_hook_getClass = + unsafe extern "C" fn(name: *const c_char, out_cls: *mut *const objc_class) -> BOOL; + +/// Not available on macOS x86. +/// +/// Remember that this is non-null! +#[cfg(not(all(target_os = "macos", target_arch = "x86")))] +pub type objc_hook_lazyClassNamer = unsafe extern "C" fn(cls: *const objc_class) -> *const c_char; + extern "C" { pub fn imp_getBlock(imp: IMP) -> *mut objc_object; pub fn imp_implementationWithBlock(block: *mut objc_object) -> IMP; @@ -51,4 +64,21 @@ extern "C" { pub fn objc_setForwardHandler(fwd: *mut c_void, fwd_stret: *mut c_void); pub fn objc_sync_enter(obj: *mut objc_object) -> c_int; pub fn objc_sync_exit(obj: *mut objc_object) -> c_int; + + /// Not available on macOS x86. + /// + /// Remember that this is non-null! + #[cfg(not(all(target_os = "macos", target_arch = "x86")))] + pub fn objc_setHook_getClass( + new_value: objc_hook_getClass, + out_old_value: *mut objc_hook_getClass, + ); + /// Not available on macOS x86. + /// + /// Remember that this is non-null! + #[cfg(not(all(target_os = "macos", target_arch = "x86")))] + pub fn objc_setHook_lazyClassNamer( + new_value: objc_hook_lazyClassNamer, + out_old_value: *mut objc_hook_lazyClassNamer, + ); } From 7309ada78093e75de9e92e1b44e792565e6fb3f5 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 14:53:48 +0200 Subject: [PATCH 19/36] sys: Add functions marked with OBJC_ARC_UNAVAILABLE --- objc/src/runtime.rs | 4 +++- objc/src/test_utils.rs | 1 + objc_sys/src/lib.rs | 4 +--- objc_sys/src/object.rs | 29 +++++++++++++++++++++++++++++ 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/objc/src/runtime.rs b/objc/src/runtime.rs index a8187c047..1c0d43686 100644 --- a/objc/src/runtime.rs +++ b/objc/src/runtime.rs @@ -14,6 +14,8 @@ use std::os::raw::c_uint; use crate::Encode; use objc_sys; +#[allow(deprecated)] +pub use objc_sys::object_dispose; pub use objc_sys::{ class_addIvar, class_addMethod, class_addProtocol, class_conformsToProtocol, class_copyIvarList, class_copyMethodList, class_copyProtocolList, class_createInstance, @@ -25,7 +27,7 @@ pub use objc_sys::{ objc_autoreleasePoolPop, objc_autoreleasePoolPush, objc_copyClassList, objc_copyProtocolList, objc_copyWeak, objc_destroyWeak, objc_disposeClassPair, objc_getClass, objc_getClassList, objc_getProtocol, objc_initWeak, objc_loadWeakRetained, objc_registerClassPair, - objc_registerProtocol, objc_release, objc_retain, object_dispose, object_getClass, + objc_registerProtocol, objc_release, objc_retain, object_getClass, protocol_addMethodDescription, protocol_addProtocol, protocol_conformsToProtocol, protocol_copyProtocolList, protocol_getName, protocol_isEqual, sel_getName, sel_registerName, }; diff --git a/objc/src/test_utils.rs b/objc/src/test_utils.rs index e0609ac2d..b7be60377 100644 --- a/objc/src/test_utils.rs +++ b/objc/src/test_utils.rs @@ -35,6 +35,7 @@ impl DerefMut for CustomObject { impl Drop for CustomObject { fn drop(&mut self) { unsafe { + #[allow(deprecated)] runtime::object_dispose(self.obj as _); } } diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index c7d263191..e1b55232f 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -54,6 +54,4 @@ pub use various::*; type OpaqueData = PhantomData<(UnsafeCell<*const ()>, PhantomPinned)>; #[link(name = "objc", kind = "dylib")] -extern "C" { - pub fn object_dispose(obj: *mut objc_object) -> *mut objc_object; -} +extern "C" {} diff --git a/objc_sys/src/object.rs b/objc_sys/src/object.rs index ddb1c52d8..464253278 100644 --- a/objc_sys/src/object.rs +++ b/objc_sys/src/object.rs @@ -20,4 +20,33 @@ extern "C" { pub fn object_setClass(obj: *mut objc_object, cls: *const objc_class) -> *const objc_class; pub fn object_setIvar(obj: *mut objc_object, ivar: *const objc_ivar, value: *mut objc_object); + + #[deprecated = "Not needed since ARC"] + pub fn object_copy(obj: *const objc_object, size: usize) -> *mut objc_object; + #[deprecated = "Not needed since ARC"] + pub fn object_dispose(obj: *mut objc_object) -> *mut objc_object; + #[deprecated = "Not needed since ARC"] + pub fn object_setInstanceVariable( + obj: *mut objc_object, + name: *const c_char, + value: *mut c_void, + ) -> *const objc_ivar; + #[deprecated = "Not needed since ARC"] + pub fn object_setInstanceVariableWithStrongDefault( + obj: *mut objc_object, + name: *const c_char, + value: *mut c_void, + ) -> *const objc_ivar; + #[deprecated = "Not needed since ARC"] + pub fn object_getInstanceVariable( + obj: *const objc_object, + name: *const c_char, + out_value: *mut *const c_void, + ) -> *const objc_ivar; + #[deprecated = "Not needed since ARC"] + pub fn objc_getFutureClass(name: *const c_char) -> *const objc_class; + #[deprecated = "Not needed since ARC"] + pub fn objc_constructInstance(cls: *const objc_class, bytes: *mut c_void) -> *mut objc_object; + #[deprecated = "Not needed since ARC"] + pub fn objc_destructInstance(obj: *mut objc_object) -> *mut c_void; } From 902847052de0bd80d53d73a9c6157a5191e978ec Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 14:51:13 +0200 Subject: [PATCH 20/36] sys: Fix IMP being a valid NULL in class_replaceMethod --- objc_sys/src/class.rs | 2 +- objc_sys/src/various.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/objc_sys/src/class.rs b/objc_sys/src/class.rs index 6ea16a8c5..6bcb8e9c7 100644 --- a/objc_sys/src/class.rs +++ b/objc_sys/src/class.rs @@ -102,7 +102,7 @@ extern "C" { name: *const objc_selector, imp: IMP, types: *const c_char, - ) -> IMP; + ) -> Option; pub fn class_replaceProperty( cls: *mut objc_class, name: *const c_char, diff --git a/objc_sys/src/various.rs b/objc_sys/src/various.rs index df0e92c5c..af068bdc7 100644 --- a/objc_sys/src/various.rs +++ b/objc_sys/src/various.rs @@ -12,8 +12,7 @@ pub struct objc_ivar { /// A pointer to the start of a method implementation. /// -/// Remember that this is non-null! -/// Use `Option` where nullability is expected. TODO +/// This must be non-null. Use `Option` when nullability is desired. pub type IMP = unsafe extern "C" fn(); /// Not available on macOS x86. From b8a54e5e6952aa43bac2cc617979a1192a4d4566 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 4 Sep 2021 16:47:04 +0200 Subject: [PATCH 21/36] Specify the "links" key in objc_sys Makes it possible for downstream users to customize the linking to libobjc, see https://doc.rust-lang.org/cargo/reference/build-scripts.html#overriding-build-scripts --- objc_sys/Cargo.toml | 13 ++++++++++++- objc_sys/build.rs | 10 ++++++++++ objc_sys/src/lib.rs | 10 +++++----- 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 objc_sys/build.rs diff --git a/objc_sys/Cargo.toml b/objc_sys/Cargo.toml index b383ec817..f79473ae4 100644 --- a/objc_sys/Cargo.toml +++ b/objc_sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "objc_sys" -version = "0.0.0" +version = "0.0.0" # Remember to update html_root_url in lib.rs authors = ["Mads Marquart "] edition = "2018" @@ -13,3 +13,14 @@ categories = [ repository = "https://github.com/madsmtm/objc" documentation = "https://docs.rs/objc_sys/" license = "MIT" + +exclude = [ + # Used to help developers track changes by running bindgen against + # different revisions of Apple's open source `objc4`. + "helper-scripts/*", +] + +# Downstream users can customize the linking to libobjc! +# See https://doc.rust-lang.org/cargo/reference/build-scripts.html#overriding-build-scripts +links = "objc" +build = "build.rs" diff --git a/objc_sys/build.rs b/objc_sys/build.rs new file mode 100644 index 000000000..007d6e7e6 --- /dev/null +++ b/objc_sys/build.rs @@ -0,0 +1,10 @@ +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rustc-link-lib=dylib=objc"); + + // TODO: Should we vendor GNUStep's libobjc2 on non-apple targets? + // Check std::env::env::var("CARGO_CFG_TARGET_VENDOR").unwrap() + // Cargo.toml: + // [target.'cfg(not(target_vendor = "apple"))'.build-dependencies] + // cc = "1.0" +} diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index e1b55232f..078a56019 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -5,15 +5,18 @@ //! Protocol / objc_protocol is no longer a type alias of objc_object, for //! better type safety. Their internal representation is the same, so the //! functionality is just a cast away. +//! +//! Deprecated functions are not included since they could be removed at any +//! macOS release, and then our code would break. // TODO: Replace `extern "C"` with `extern "C-unwind"`. #![no_std] #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] -// Update in Cargo.toml as well. -#![doc(html_root_url = "https://docs.rs/objc_sys/1.1.0")] +#![doc(html_root_url = "https://docs.rs/objc_sys/0.0.0")] +// TODO: Remove this and add "no-std" category to Cargo.toml extern crate std; use core::cell::UnsafeCell; @@ -52,6 +55,3 @@ pub use various::*; /// /// TODO: Replace this with `extern type` to also mark it as unsized. type OpaqueData = PhantomData<(UnsafeCell<*const ()>, PhantomPinned)>; - -#[link(name = "objc", kind = "dylib")] -extern "C" {} From a0f01d7a97a3d74a73652408f67993f2e53c2759 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 5 Sep 2021 22:20:15 +0200 Subject: [PATCH 22/36] sys: Add generated GNUStep libobjc2 bindings from v1.7 This is the lowest version we'll target because they added support for the `objc_msgSend` family of functions which we might want to use (instead of the current `objc_msg_lookup`). Alternatively we could have chosen v1.6, but they're both from 2013 so it's kinda moot at this point. v1.5 is missing lots of functionality. Commit https://github.com/gnustep/libobjc2/commit/50a797f16b1f4f270180e2a9b29ae96fd644b51e --- objc_sys/helper-scripts/gnustep-gen.fish | 22 + objc_sys/helper-scripts/gnustep-headers.h | 7 + objc_sys/src/tmp_gnustep.rs | 728 ++++++++++++++++++++++ 3 files changed, 757 insertions(+) create mode 100755 objc_sys/helper-scripts/gnustep-gen.fish create mode 100644 objc_sys/helper-scripts/gnustep-headers.h create mode 100644 objc_sys/src/tmp_gnustep.rs diff --git a/objc_sys/helper-scripts/gnustep-gen.fish b/objc_sys/helper-scripts/gnustep-gen.fish new file mode 100755 index 000000000..9087135f9 --- /dev/null +++ b/objc_sys/helper-scripts/gnustep-gen.fish @@ -0,0 +1,22 @@ +#!/usr/local/bin/fish + +# Yup, this is terrible + +# Source repo should be a path to https://github.com/gnustep/libobjc2.git +set source_repo $argv[1] +set out_file $argv[2] + +cp gnustep-headers.h $source_repo/objc/headers.h + +bindgen $source_repo/objc/headers.h \ + -o $out_file \ + --no-layout-tests \ + --no-doc-comments \ + --size_t-is-usize \ + --allowlist-function="(sel|object|class|objc|method|_?protocol|ivar|property|imp|_objc|)_.*" \ + --allowlist-var=".*OBJC.*" \ + --allowlist-var=".*objc.*" \ + # GNUStep-specific functions + --blocklist-function=".*_np" + +rm $source_repo/objc/headers.h diff --git a/objc_sys/helper-scripts/gnustep-headers.h b/objc_sys/helper-scripts/gnustep-headers.h new file mode 100644 index 000000000..6e2e59b1b --- /dev/null +++ b/objc_sys/helper-scripts/gnustep-headers.h @@ -0,0 +1,7 @@ +// Required to come before the below headers +#include "runtime.h" + +#include "capabilities.h" +#include "objc-arc.h" +#include "hooks.h" +#include "encoding.h" diff --git a/objc_sys/src/tmp_gnustep.rs b/objc_sys/src/tmp_gnustep.rs new file mode 100644 index 000000000..efad1083c --- /dev/null +++ b/objc_sys/src/tmp_gnustep.rs @@ -0,0 +1,728 @@ +/* automatically generated by rust-bindgen 0.59.1 */ + +pub const OBJC_SMALL_OBJECT_MASK: u32 = 7; +pub const OBJC_SMALL_OBJECT_SHIFT: u32 = 3; +pub const OBJC_CAP_EXCEPTIONS: u32 = 0; +pub const OBJC_CAP_SYNCRONIZE: u32 = 1; +pub const OBJC_CAP_PROPERTIES: u32 = 2; +pub const OBJC_CAP_PROPERTY_INTROSPECTION: u32 = 3; +pub const OBJC_CAP_OPTIONAL_PROTOCOLS: u32 = 4; +pub const OBJC_CAP_NONFRAGILE_IVARS: u32 = 5; +pub const OBJC_CAP_TYPE_DEPENDENT_DISPATCH: u32 = 6; +pub const OBJC_CAP_LOW_MEMORY: u32 = 7; +pub const OBJC_DEVELOPER_MODE: u32 = 8; +pub const OBJC_UNIFIED_EXCEPTION_MODEL: u32 = 9; +pub const OBJC_CAP_REGISTERED_COMPATIBILITY_ALIASES: u32 = 10; +pub const OBJC_CAP_ARC: u32 = 11; +pub const OBJC_CAP_GARBAGE_COLLECTION: u32 = 12; +pub const OBJC_CAP_ASSOCIATED_REFERENCES: u32 = 13; +pub const OBJC_CAP_SMALL_OBJECTS: u32 = 14; +pub const OBJC_CAP_PROTOTYPES: u32 = 15; +pub const OBJC_ARC_AUTORELEASE_DEBUG: u32 = 16; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_ivar { + _unused: [u8; 0], +} +pub type Ivar = *mut objc_ivar; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_selector { + _unused: [u8; 0], +} +pub type SEL = *mut objc_selector; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_class { + _unused: [u8; 0], +} +pub type Class = *mut objc_class; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_object { + pub isa: Class, +} +pub type id = *mut objc_object; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_super { + pub receiver: id, + pub class: Class, +} +pub type IMP = ::std::option::Option id>; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_method { + _unused: [u8; 0], +} +pub type Method = *mut objc_method; +pub type BOOL = ::std::os::raw::c_uchar; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_property { + _unused: [u8; 0], +} +pub type objc_property_t = *mut objc_property; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_protocol { + _unused: [u8; 0], +} +pub type Protocol = objc_protocol; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_method_description { + pub name: SEL, + pub types: *const ::std::os::raw::c_char, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_property_attribute_t { + pub name: *const ::std::os::raw::c_char, + pub value: *const ::std::os::raw::c_char, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_slot { + pub owner: Class, + pub cachedFor: Class, + pub types: *const ::std::os::raw::c_char, + pub version: ::std::os::raw::c_int, + pub method: IMP, + pub selector: SEL, +} +extern "C" { + pub fn objc_msgSend(self_: id, _cmd: SEL, ...) -> id; +} +extern "C" { + pub fn objc_msgSend_stret(self_: id, _cmd: SEL, ...); +} +extern "C" { + pub fn objc_msgSend_fpret(self_: id, _cmd: SEL, ...) -> u128; +} +extern "C" { + pub fn class_addIvar( + cls: Class, + name: *const ::std::os::raw::c_char, + size: usize, + alignment: u8, + types: *const ::std::os::raw::c_char, + ) -> BOOL; +} +extern "C" { + pub fn class_addMethod( + cls: Class, + name: SEL, + imp: IMP, + types: *const ::std::os::raw::c_char, + ) -> BOOL; +} +extern "C" { + pub fn class_addProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; +} +extern "C" { + pub fn class_conformsToProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; +} +extern "C" { + pub fn class_copyIvarList(cls: Class, outCount: *mut ::std::os::raw::c_uint) -> *mut Ivar; +} +extern "C" { + pub fn class_copyMethodList(cls: Class, outCount: *mut ::std::os::raw::c_uint) -> *mut Method; +} +extern "C" { + pub fn class_copyPropertyList( + cls: Class, + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut objc_property_t; +} +extern "C" { + pub fn class_copyProtocolList( + cls: Class, + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut *mut Protocol; +} +extern "C" { + pub fn class_createInstance(cls: Class, extraBytes: usize) -> id; +} +extern "C" { + pub fn class_getClassMethod(aClass: Class, aSelector: SEL) -> Method; +} +extern "C" { + pub fn class_getClassVariable(cls: Class, name: *const ::std::os::raw::c_char) -> Ivar; +} +extern "C" { + pub fn class_getInstanceMethod(aClass: Class, aSelector: SEL) -> Method; +} +extern "C" { + pub fn class_getInstanceSize(cls: Class) -> usize; +} +extern "C" { + pub fn class_getInstanceVariable(cls: Class, name: *const ::std::os::raw::c_char) -> Ivar; +} +extern "C" { + pub fn object_setIvar(object: id, ivar: Ivar, value: id); +} +extern "C" { + pub fn object_setInstanceVariable( + obj: id, + name: *const ::std::os::raw::c_char, + value: *mut ::std::os::raw::c_void, + ) -> Ivar; +} +extern "C" { + pub fn object_getIvar(object: id, ivar: Ivar) -> id; +} +extern "C" { + pub fn object_getInstanceVariable( + obj: id, + name: *const ::std::os::raw::c_char, + outValue: *mut *mut ::std::os::raw::c_void, + ) -> Ivar; +} +extern "C" { + pub fn class_getMethodImplementation(cls: Class, name: SEL) -> IMP; +} +extern "C" { + pub fn class_getMethodImplementation_stret(cls: Class, name: SEL) -> IMP; +} +extern "C" { + pub fn class_getName(cls: Class) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn class_getProperty(cls: Class, name: *const ::std::os::raw::c_char) -> objc_property_t; +} +extern "C" { + pub fn class_getSuperclass(cls: Class) -> Class; +} +extern "C" { + pub fn class_getVersion(theClass: Class) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn class_setVersion(theClass: Class, version: ::std::os::raw::c_int); +} +extern "C" { + pub fn class_getWeakIvarLayout(cls: Class) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn class_isMetaClass(cls: Class) -> BOOL; +} +extern "C" { + pub fn class_replaceMethod( + cls: Class, + name: SEL, + imp: IMP, + types: *const ::std::os::raw::c_char, + ) -> IMP; +} +extern "C" { + pub fn class_respondsToSelector(cls: Class, sel: SEL) -> BOOL; +} +extern "C" { + pub fn class_getIvarLayout(cls: Class) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn class_setIvarLayout(cls: Class, layout: *const ::std::os::raw::c_char); +} +extern "C" { + pub fn class_setSuperclass(cls: Class, newSuper: Class) -> Class; +} +extern "C" { + pub fn class_setWeakIvarLayout(cls: Class, layout: *const ::std::os::raw::c_char); +} +extern "C" { + pub fn ivar_getName(ivar: Ivar) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn ivar_getOffset(ivar: Ivar) -> isize; +} +extern "C" { + pub fn ivar_getTypeEncoding(ivar: Ivar) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn method_copyArgumentType( + method: Method, + index: ::std::os::raw::c_uint, + ) -> *mut ::std::os::raw::c_char; +} +extern "C" { + pub fn method_copyReturnType(method: Method) -> *mut ::std::os::raw::c_char; +} +extern "C" { + pub fn method_exchangeImplementations(m1: Method, m2: Method); +} +extern "C" { + pub fn method_getArgumentType( + method: Method, + index: ::std::os::raw::c_uint, + dst: *mut ::std::os::raw::c_char, + dst_len: usize, + ); +} +extern "C" { + pub fn method_getImplementation(method: Method) -> IMP; +} +extern "C" { + pub fn method_getName(method: Method) -> SEL; +} +extern "C" { + pub fn method_getNumberOfArguments(method: Method) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn method_getReturnType(method: Method, dst: *mut ::std::os::raw::c_char, dst_len: usize); +} +extern "C" { + pub fn method_getTypeEncoding(method: Method) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn method_setImplementation(method: Method, imp: IMP) -> IMP; +} +extern "C" { + pub fn objc_allocateClassPair( + superclass: Class, + name: *const ::std::os::raw::c_char, + extraBytes: usize, + ) -> Class; +} +extern "C" { + pub fn objc_disposeClassPair(cls: Class); +} +extern "C" { + pub fn objc_getClass(name: *const ::std::os::raw::c_char) -> id; +} +extern "C" { + pub fn objc_getClassList( + buffer: *mut Class, + bufferLen: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn objc_copyClassList(outCount: *mut ::std::os::raw::c_uint) -> *mut Class; +} +extern "C" { + pub fn objc_getMetaClass(name: *const ::std::os::raw::c_char) -> id; +} +extern "C" { + pub fn objc_getRequiredClass(name: *const ::std::os::raw::c_char) -> id; +} +extern "C" { + pub fn objc_lookUpClass(name: *const ::std::os::raw::c_char) -> id; +} +extern "C" { + pub fn objc_getProtocol(name: *const ::std::os::raw::c_char) -> *mut Protocol; +} +extern "C" { + pub fn objc_allocateProtocol(name: *const ::std::os::raw::c_char) -> *mut Protocol; +} +extern "C" { + pub fn objc_registerProtocol(proto: *mut Protocol); +} +extern "C" { + pub fn protocol_addMethodDescription( + aProtocol: *mut Protocol, + name: SEL, + types: *const ::std::os::raw::c_char, + isRequiredMethod: BOOL, + isInstanceMethod: BOOL, + ); +} +extern "C" { + pub fn protocol_addProtocol(aProtocol: *mut Protocol, addition: *mut Protocol); +} +extern "C" { + pub fn protocol_addProperty( + aProtocol: *mut Protocol, + name: *const ::std::os::raw::c_char, + attributes: *const objc_property_attribute_t, + attributeCount: ::std::os::raw::c_uint, + isRequiredProperty: BOOL, + isInstanceProperty: BOOL, + ); +} +extern "C" { + pub fn objc_registerClassPair(cls: Class); +} +extern "C" { + pub fn object_getIndexedIvars(obj: id) -> *mut ::std::os::raw::c_void; +} +extern "C" { + pub fn object_dispose(obj: id) -> id; +} +extern "C" { + pub fn object_getClass(obj: id) -> Class; +} +extern "C" { + pub fn object_setClass(obj: id, cls: Class) -> Class; +} +extern "C" { + pub fn object_getClassName(obj: id) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn property_getName(property: objc_property_t) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn property_getAttributes(property: objc_property_t) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn property_copyAttributeList( + property: objc_property_t, + outCount: *mut ::std::os::raw::c_uint, + ) -> *mut objc_property_attribute_t; +} +extern "C" { + pub fn class_addProperty( + cls: Class, + name: *const ::std::os::raw::c_char, + attributes: *const objc_property_attribute_t, + attributeCount: ::std::os::raw::c_uint, + ) -> BOOL; +} +extern "C" { + pub fn class_replaceProperty( + cls: Class, + name: *const ::std::os::raw::c_char, + attributes: *const objc_property_attribute_t, + attributeCount: ::std::os::raw::c_uint, + ); +} +extern "C" { + pub fn property_copyAttributeValue( + property: objc_property_t, + attributeName: *const ::std::os::raw::c_char, + ) -> *mut ::std::os::raw::c_char; +} +extern "C" { + pub fn protocol_conformsToProtocol(p: *mut Protocol, other: *mut Protocol) -> BOOL; +} +extern "C" { + pub fn protocol_copyMethodDescriptionList( + p: *mut Protocol, + isRequiredMethod: BOOL, + isInstanceMethod: BOOL, + count: *mut ::std::os::raw::c_uint, + ) -> *mut objc_method_description; +} +extern "C" { + pub fn protocol_copyPropertyList( + p: *mut Protocol, + count: *mut ::std::os::raw::c_uint, + ) -> *mut objc_property_t; +} +extern "C" { + pub fn protocol_copyProtocolList( + p: *mut Protocol, + count: *mut ::std::os::raw::c_uint, + ) -> *mut *mut Protocol; +} +extern "C" { + pub fn objc_copyProtocolList(outCount: *mut ::std::os::raw::c_uint) -> *mut *mut Protocol; +} +extern "C" { + pub fn protocol_getMethodDescription( + p: *mut Protocol, + aSel: SEL, + isRequiredMethod: BOOL, + isInstanceMethod: BOOL, + ) -> objc_method_description; +} +extern "C" { + pub fn protocol_getName(p: *mut Protocol) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn protocol_getProperty( + p: *mut Protocol, + name: *const ::std::os::raw::c_char, + isRequiredProperty: BOOL, + isInstanceProperty: BOOL, + ) -> objc_property_t; +} +extern "C" { + pub fn protocol_isEqual(p: *mut Protocol, other: *mut Protocol) -> BOOL; +} +extern "C" { + pub fn objc_msg_lookup(arg1: id, arg2: SEL) -> IMP; +} +extern "C" { + pub fn objc_msg_lookup_super(arg1: *mut objc_super, arg2: SEL) -> IMP; +} +extern "C" { + pub fn sel_getName(sel: SEL) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn sel_getUid(selName: *const ::std::os::raw::c_char) -> SEL; +} +extern "C" { + pub fn sel_isEqual(sel1: SEL, sel2: SEL) -> BOOL; +} +extern "C" { + pub fn sel_registerName(selName: *const ::std::os::raw::c_char) -> SEL; +} +extern "C" { + pub fn objc_msg_lookup_sender(receiver: *mut id, selector: SEL, sender: id) -> *mut objc_slot; +} +pub const OBJC_ASSOCIATION_ASSIGN: ::std::os::raw::c_uint = 0; +pub const OBJC_ASSOCIATION_RETAIN_NONATOMIC: ::std::os::raw::c_uint = 1; +pub const OBJC_ASSOCIATION_COPY_NONATOMIC: ::std::os::raw::c_uint = 3; +pub const OBJC_ASSOCIATION_RETAIN: ::std::os::raw::c_uint = 769; +pub const OBJC_ASSOCIATION_COPY: ::std::os::raw::c_uint = 771; +pub type _bindgen_ty_1 = ::std::os::raw::c_uint; +pub type objc_AssociationPolicy = usize; +extern "C" { + pub fn objc_getAssociatedObject(object: id, key: *mut ::std::os::raw::c_void) -> id; +} +extern "C" { + pub fn objc_setAssociatedObject( + object: id, + key: *mut ::std::os::raw::c_void, + value: id, + policy: objc_AssociationPolicy, + ); +} +extern "C" { + pub fn objc_removeAssociatedObjects(object: id); +} +extern "C" { + pub fn imp_implementationWithBlock(block: *mut ::std::os::raw::c_void) -> IMP; +} +extern "C" { + pub fn imp_getBlock(anImp: IMP) -> *mut ::std::os::raw::c_void; +} +extern "C" { + pub fn imp_removeBlock(anImp: IMP) -> BOOL; +} +extern "C" { + pub fn objc_set_apple_compatible_objcxx_exceptions( + newValue: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn objc_malloc(size: usize) -> *mut ::std::os::raw::c_void; +} +extern "C" { + pub fn objc_atomic_malloc(size: usize) -> *mut ::std::os::raw::c_void; +} +extern "C" { + pub fn objc_valloc(size: usize) -> *mut ::std::os::raw::c_void; +} +extern "C" { + pub fn objc_realloc( + mem: *mut ::std::os::raw::c_void, + size: usize, + ) -> *mut ::std::os::raw::c_void; +} +extern "C" { + pub fn objc_calloc(nelem: usize, size: usize) -> *mut ::std::os::raw::c_void; +} +extern "C" { + pub fn objc_free(mem: *mut ::std::os::raw::c_void); +} +extern "C" { + pub fn objc_get_class(name: *const ::std::os::raw::c_char) -> id; +} +extern "C" { + pub fn objc_lookup_class(name: *const ::std::os::raw::c_char) -> id; +} +extern "C" { + pub fn objc_get_meta_class(name: *const ::std::os::raw::c_char) -> id; +} +extern "C" { + pub fn objc_next_class(enum_state: *mut *mut ::std::os::raw::c_void) -> Class; +} +extern "C" { + pub fn class_pose_as(impostor: Class, super_class: Class) -> Class; +} +extern "C" { + pub fn sel_get_typed_uid( + name: *const ::std::os::raw::c_char, + types: *const ::std::os::raw::c_char, + ) -> SEL; +} +extern "C" { + pub fn sel_get_any_typed_uid(name: *const ::std::os::raw::c_char) -> SEL; +} +extern "C" { + pub fn sel_get_any_uid(name: *const ::std::os::raw::c_char) -> SEL; +} +extern "C" { + pub fn sel_get_uid(name: *const ::std::os::raw::c_char) -> SEL; +} +extern "C" { + pub fn sel_get_name(selector: SEL) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn sel_is_mapped(selector: SEL) -> BOOL; +} +extern "C" { + pub fn sel_get_type(selector: SEL) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn sel_register_name(name: *const ::std::os::raw::c_char) -> SEL; +} +extern "C" { + pub fn sel_register_typed_name( + name: *const ::std::os::raw::c_char, + type_: *const ::std::os::raw::c_char, + ) -> SEL; +} +extern "C" { + pub fn sel_eq(s1: SEL, s2: SEL) -> BOOL; +} +extern "C" { + pub fn objc_test_capability(x: ::std::os::raw::c_int) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn objc_autorelease(obj: id) -> id; +} +extern "C" { + pub fn objc_autoreleaseReturnValue(obj: id) -> id; +} +extern "C" { + pub fn objc_initWeak(object: *mut id, value: id) -> id; +} +extern "C" { + pub fn objc_loadWeak(object: *mut id) -> id; +} +extern "C" { + pub fn objc_loadWeakRetained(obj: *mut id) -> id; +} +extern "C" { + pub fn objc_retain(obj: id) -> id; +} +extern "C" { + pub fn objc_retainAutorelease(obj: id) -> id; +} +extern "C" { + pub fn objc_retainAutoreleaseReturnValue(obj: id) -> id; +} +extern "C" { + pub fn objc_retainAutoreleasedReturnValue(obj: id) -> id; +} +extern "C" { + pub fn objc_retainBlock(b: id) -> id; +} +extern "C" { + pub fn objc_storeStrong(addr: *mut id, value: id) -> id; +} +extern "C" { + pub fn objc_storeWeak(addr: *mut id, obj: id) -> id; +} +extern "C" { + pub fn objc_autoreleasePoolPush() -> *mut ::std::os::raw::c_void; +} +extern "C" { + pub fn objc_autoreleasePoolPop(pool: *mut ::std::os::raw::c_void); +} +extern "C" { + pub fn objc_copyWeak(dest: *mut id, src: *mut id); +} +extern "C" { + pub fn objc_destroyWeak(addr: *mut id); +} +extern "C" { + pub fn objc_moveWeak(dest: *mut id, src: *mut id); +} +extern "C" { + pub fn objc_release(obj: id); +} +extern "C" { + pub fn objc_delete_weak_refs(obj: id); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_category { + _unused: [u8; 0], +} +extern "C" { + pub static mut _objc_lookup_class: + ::std::option::Option Class>; +} +extern "C" { + pub static mut _objc_load_callback: + ::std::option::Option; +} +extern "C" { + pub static mut objc_proxy_lookup: + ::std::option::Option id>; +} +extern "C" { + pub static mut __objc_msg_forward3: + ::std::option::Option *mut objc_slot>; +} +extern "C" { + pub static mut __objc_msg_forward2: + ::std::option::Option IMP>; +} +extern "C" { + pub static mut _objc_unexpected_exception: + ::std::option::Option; +} +extern "C" { + pub static mut _objc_class_for_boxing_foreign_exception: + ::std::option::Option Class>; +} +extern "C" { + pub static mut _objc_selector_type_mismatch: ::std::option::Option< + unsafe extern "C" fn(cls: Class, selector: SEL, result: *mut objc_slot) -> *mut objc_slot, + >; +} +extern "C" { + pub static mut _objc_weak_load: ::std::option::Option id>; +} +extern "C" { + pub fn objc_skip_type_qualifiers( + type_: *const ::std::os::raw::c_char, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn objc_skip_typespec( + type_: *const ::std::os::raw::c_char, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn objc_skip_argspec(type_: *const ::std::os::raw::c_char) + -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn objc_sizeof_type(type_: *const ::std::os::raw::c_char) -> usize; +} +extern "C" { + pub fn objc_alignof_type(type_: *const ::std::os::raw::c_char) -> usize; +} +extern "C" { + pub fn objc_aligned_size(type_: *const ::std::os::raw::c_char) -> usize; +} +extern "C" { + pub fn objc_promoted_size(type_: *const ::std::os::raw::c_char) -> usize; +} +extern "C" { + pub fn method_get_number_of_arguments(method: *mut objc_method) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn objc_get_type_qualifiers(type_: *const ::std::os::raw::c_char) + -> ::std::os::raw::c_uint; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct objc_struct_layout { + pub original_type: *const ::std::os::raw::c_char, + pub type_: *const ::std::os::raw::c_char, + pub prev_type: *const ::std::os::raw::c_char, + pub record_size: ::std::os::raw::c_uint, + pub record_align: ::std::os::raw::c_uint, +} +extern "C" { + pub fn objc_layout_structure( + type_: *const ::std::os::raw::c_char, + layout: *mut objc_struct_layout, + ); +} +extern "C" { + pub fn objc_layout_structure_next_member(layout: *mut objc_struct_layout) -> BOOL; +} +extern "C" { + pub fn objc_layout_structure_get_info( + layout: *mut objc_struct_layout, + offset: *mut ::std::os::raw::c_uint, + align: *mut ::std::os::raw::c_uint, + type_: *mut *const ::std::os::raw::c_char, + ); +} From 3c01d3a0f066c4b9fa95f8e670a6d63d55089d6f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 5 Sep 2021 22:03:07 +0200 Subject: [PATCH 23/36] sys: Generate GNUStep libobjc2 bindings from v2.1 This can be used to see the main differences in the objc API from v1.7 to v2.1; in essence, the API we'll be using haven't actually changed! Commit https://github.com/gnustep/libobjc2/commit/282486deb636d4c4ded7135560bcceb531b8b78c --- objc_sys/src/tmp_gnustep.rs | 68 ++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/objc_sys/src/tmp_gnustep.rs b/objc_sys/src/tmp_gnustep.rs index efad1083c..79d20f8ff 100644 --- a/objc_sys/src/tmp_gnustep.rs +++ b/objc_sys/src/tmp_gnustep.rs @@ -19,6 +19,7 @@ pub const OBJC_CAP_ASSOCIATED_REFERENCES: u32 = 13; pub const OBJC_CAP_SMALL_OBJECTS: u32 = 14; pub const OBJC_CAP_PROTOTYPES: u32 = 15; pub const OBJC_ARC_AUTORELEASE_DEBUG: u32 = 16; +pub const OBJC_CAP_TRACING: u32 = 17; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct objc_ivar { @@ -83,6 +84,14 @@ pub struct objc_property_attribute_t { } #[repr(C)] #[derive(Debug, Copy, Clone)] +pub struct objc_slot2 { + pub method: IMP, +} +extern "C" { + pub static mut objc_method_cache_version: u64; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] pub struct objc_slot { pub owner: Class, pub cachedFor: Class, @@ -407,6 +416,14 @@ extern "C" { count: *mut ::std::os::raw::c_uint, ) -> *mut objc_property_t; } +extern "C" { + pub fn protocol_copyPropertyList2( + p: *mut Protocol, + count: *mut ::std::os::raw::c_uint, + isRequiredProperty: BOOL, + isInstanceProperty: BOOL, + ) -> *mut objc_property_t; +} extern "C" { pub fn protocol_copyProtocolList( p: *mut Protocol, @@ -424,6 +441,14 @@ extern "C" { isInstanceMethod: BOOL, ) -> objc_method_description; } +extern "C" { + pub fn _protocol_getMethodTypeEncoding( + p: *mut Protocol, + aSel: SEL, + isRequiredMethod: BOOL, + isInstanceMethod: BOOL, + ) -> *const ::std::os::raw::c_char; +} extern "C" { pub fn protocol_getName(p: *mut Protocol) -> *const ::std::os::raw::c_char; } @@ -459,6 +484,22 @@ extern "C" { extern "C" { pub fn objc_msg_lookup_sender(receiver: *mut id, selector: SEL, sender: id) -> *mut objc_slot; } +extern "C" { + pub fn objc_get_slot(arg1: Class, arg2: SEL) -> *mut objc_slot; +} +extern "C" { + pub fn objc_get_slot2(arg1: Class, arg2: SEL, arg3: *mut u64) -> *mut objc_slot2; +} +extern "C" { + pub fn objc_slot_lookup_version( + receiver: *mut id, + selector: SEL, + arg1: *mut u64, + ) -> *mut objc_slot2; +} +extern "C" { + pub fn objc_msg_lookup2(receiver: *mut id, selector: SEL) -> IMP; +} pub const OBJC_ASSOCIATION_ASSIGN: ::std::os::raw::c_uint = 0; pub const OBJC_ASSOCIATION_RETAIN_NONATOMIC: ::std::os::raw::c_uint = 1; pub const OBJC_ASSOCIATION_COPY_NONATOMIC: ::std::os::raw::c_uint = 3; @@ -467,12 +508,12 @@ pub const OBJC_ASSOCIATION_COPY: ::std::os::raw::c_uint = 771; pub type _bindgen_ty_1 = ::std::os::raw::c_uint; pub type objc_AssociationPolicy = usize; extern "C" { - pub fn objc_getAssociatedObject(object: id, key: *mut ::std::os::raw::c_void) -> id; + pub fn objc_getAssociatedObject(object: id, key: *const ::std::os::raw::c_void) -> id; } extern "C" { pub fn objc_setAssociatedObject( object: id, - key: *mut ::std::os::raw::c_void, + key: *const ::std::os::raw::c_void, value: id, policy: objc_AssociationPolicy, ); @@ -481,10 +522,10 @@ extern "C" { pub fn objc_removeAssociatedObjects(object: id); } extern "C" { - pub fn imp_implementationWithBlock(block: *mut ::std::os::raw::c_void) -> IMP; + pub fn imp_implementationWithBlock(block: id) -> IMP; } extern "C" { - pub fn imp_getBlock(anImp: IMP) -> *mut ::std::os::raw::c_void; + pub fn imp_getBlock(anImp: IMP) -> id; } extern "C" { pub fn imp_removeBlock(anImp: IMP) -> BOOL; @@ -624,7 +665,7 @@ extern "C" { pub fn objc_release(obj: id); } extern "C" { - pub fn objc_delete_weak_refs(obj: id); + pub fn objc_delete_weak_refs(obj: id) -> BOOL; } #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -659,6 +700,11 @@ extern "C" { pub static mut _objc_class_for_boxing_foreign_exception: ::std::option::Option Class>; } +extern "C" { + pub static mut _objc_selector_type_mismatch2: ::std::option::Option< + unsafe extern "C" fn(cls: Class, selector: SEL, result: *mut objc_slot2) -> IMP, + >; +} extern "C" { pub static mut _objc_selector_type_mismatch: ::std::option::Option< unsafe extern "C" fn(cls: Class, selector: SEL, result: *mut objc_slot) -> *mut objc_slot, @@ -667,6 +713,18 @@ extern "C" { extern "C" { pub static mut _objc_weak_load: ::std::option::Option id>; } +pub type objc_tracing_hook = ::std::option::Option< + unsafe extern "C" fn( + arg1: id, + arg2: SEL, + arg3: IMP, + arg4: ::std::os::raw::c_int, + arg5: *mut ::std::os::raw::c_void, + ) -> IMP, +>; +extern "C" { + pub fn objc_registerTracingHook(arg1: SEL, arg2: objc_tracing_hook) -> ::std::os::raw::c_int; +} extern "C" { pub fn objc_skip_type_qualifiers( type_: *const ::std::os::raw::c_char, From 1327d24b140fd0d7322b8e456825013503ef46fd Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 5 Sep 2021 21:45:50 +0200 Subject: [PATCH 24/36] Add cfg(apple) and cfg(gnustep) helpers --- objc_sys/build.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/objc_sys/build.rs b/objc_sys/build.rs index 007d6e7e6..c2db6ca95 100644 --- a/objc_sys/build.rs +++ b/objc_sys/build.rs @@ -1,10 +1,23 @@ +use std::env; + fn main() { + // Only rerun if this file changes; the script doesn't depend on our code println!("cargo:rerun-if-changed=build.rs"); + // Link to libobjc println!("cargo:rustc-link-lib=dylib=objc"); - // TODO: Should we vendor GNUStep's libobjc2 on non-apple targets? - // Check std::env::env::var("CARGO_CFG_TARGET_VENDOR").unwrap() - // Cargo.toml: - // [target.'cfg(not(target_vendor = "apple"))'.build-dependencies] - // cc = "1.0" + let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap(); + + // Adds useful #[cfg(apple)] and #[cfg(gnustep)] directives + if target_vendor == "apple" { + println!("cargo:rustc-cfg=apple"); + } else { + // TODO: Are there other possibilities than GNUStep? Airyx? Is it + // possible to use Apple's open source objc4 on other platforms? + println!("cargo:rustc-cfg=gnustep"); + // TODO: Should we vendor GNUStep's libobjc2? + // Using Cargo.toml: + // [target.'cfg(not(target_vendor = "apple"))'.build-dependencies] + // cc = "1.0" + } } From 2d19c5fea9ca89fea3337b05c830bd583c55724b Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 5 Sep 2021 21:31:58 +0200 Subject: [PATCH 25/36] sys: Verify that GNUStep supports all ARC functions Also add objc_retainAutoreleaseReturnValue that I missed in 052bcd697a08286a8f416d78c5a38d19765ce952 --- objc_sys/src/rc.rs | 26 +++++++++-------- objc_sys/src/tmp_gnustep.rs | 57 ------------------------------------- 2 files changed, 14 insertions(+), 69 deletions(-) diff --git a/objc_sys/src/rc.rs b/objc_sys/src/rc.rs index 3b9d60838..31b38b1f6 100644 --- a/objc_sys/src/rc.rs +++ b/objc_sys/src/rc.rs @@ -5,6 +5,8 @@ //! Defined in `objc-internal.h`, but is available in Clang's //! [documentation][ARC] so these are safe to rely on. //! +//! On GNUStep these are defined in `objc-arc.h`. +//! //! [ARC]: https://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime-support> use core::ffi::c_void; @@ -21,14 +23,11 @@ extern "C" { // Weak pointers pub fn objc_copyWeak(to: *mut *mut objc_object, from: *mut *mut objc_object); - pub fn objc_destroyWeak(location: *mut *mut objc_object); - pub fn objc_initWeak( - location: *mut *mut objc_object, - value: *mut objc_object, - ) -> *mut objc_object; + pub fn objc_destroyWeak(addr: *mut *mut objc_object); + pub fn objc_initWeak(addr: *mut *mut objc_object, value: *mut objc_object) -> *mut objc_object; // Defined in runtime.h - pub fn objc_loadWeak(location: *mut *mut objc_object) -> *mut objc_object; - pub fn objc_loadWeakRetained(location: *mut *mut objc_object) -> *mut objc_object; + pub fn objc_loadWeak(addr: *mut *mut objc_object) -> *mut objc_object; + pub fn objc_loadWeakRetained(addr: *mut *mut objc_object) -> *mut objc_object; pub fn objc_moveWeak(to: *mut *mut objc_object, from: *mut *mut objc_object); // Retain / release @@ -36,16 +35,19 @@ extern "C" { pub fn objc_release(value: *mut objc_object); pub fn objc_retain(value: *mut objc_object) -> *mut objc_object; pub fn objc_retainAutorelease(value: *mut objc_object) -> *mut objc_object; + pub fn objc_retainAutoreleaseReturnValue(value: *mut objc_object) -> *mut objc_object; pub fn objc_retainAutoreleasedReturnValue(value: *mut objc_object) -> *mut objc_object; // Defined in objc-abi.h pub fn objc_retainBlock(value: *mut objc_object) -> *mut objc_object; // Storing values - pub fn objc_storeStrong(location: *mut *mut objc_object, value: *mut objc_object); + pub fn objc_storeStrong(addr: *mut *mut objc_object, value: *mut objc_object); // Defined in runtime.h - pub fn objc_storeWeak( - location: *mut *mut objc_object, - value: *mut objc_object, - ) -> *mut objc_object; + pub fn objc_storeWeak(addr: *mut *mut objc_object, value: *mut objc_object) + -> *mut objc_object; + + // TODO: Decide about nonstandard extensions like these: + // #[cfg(gnustep)] + // pub fn objc_delete_weak_refs(obj: *mut objc_object) -> BOOL; } diff --git a/objc_sys/src/tmp_gnustep.rs b/objc_sys/src/tmp_gnustep.rs index 79d20f8ff..a7c3f55cf 100644 --- a/objc_sys/src/tmp_gnustep.rs +++ b/objc_sys/src/tmp_gnustep.rs @@ -610,63 +610,6 @@ extern "C" { extern "C" { pub fn objc_test_capability(x: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } -extern "C" { - pub fn objc_autorelease(obj: id) -> id; -} -extern "C" { - pub fn objc_autoreleaseReturnValue(obj: id) -> id; -} -extern "C" { - pub fn objc_initWeak(object: *mut id, value: id) -> id; -} -extern "C" { - pub fn objc_loadWeak(object: *mut id) -> id; -} -extern "C" { - pub fn objc_loadWeakRetained(obj: *mut id) -> id; -} -extern "C" { - pub fn objc_retain(obj: id) -> id; -} -extern "C" { - pub fn objc_retainAutorelease(obj: id) -> id; -} -extern "C" { - pub fn objc_retainAutoreleaseReturnValue(obj: id) -> id; -} -extern "C" { - pub fn objc_retainAutoreleasedReturnValue(obj: id) -> id; -} -extern "C" { - pub fn objc_retainBlock(b: id) -> id; -} -extern "C" { - pub fn objc_storeStrong(addr: *mut id, value: id) -> id; -} -extern "C" { - pub fn objc_storeWeak(addr: *mut id, obj: id) -> id; -} -extern "C" { - pub fn objc_autoreleasePoolPush() -> *mut ::std::os::raw::c_void; -} -extern "C" { - pub fn objc_autoreleasePoolPop(pool: *mut ::std::os::raw::c_void); -} -extern "C" { - pub fn objc_copyWeak(dest: *mut id, src: *mut id); -} -extern "C" { - pub fn objc_destroyWeak(addr: *mut id); -} -extern "C" { - pub fn objc_moveWeak(dest: *mut id, src: *mut id); -} -extern "C" { - pub fn objc_release(obj: id); -} -extern "C" { - pub fn objc_delete_weak_refs(obj: id) -> BOOL; -} #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct objc_category { From 6b9f624a5110b9b39d11dcfd412450ee756eb316 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 5 Sep 2021 22:25:54 +0200 Subject: [PATCH 26/36] sys: Verify that GNUStep supports objc types --- objc_sys/src/class.rs | 4 +-- objc_sys/src/message.rs | 2 ++ objc_sys/src/protocol.rs | 8 ++++- objc_sys/src/tmp_gnustep.rs | 62 ------------------------------------- objc_sys/src/types.rs | 6 ++-- 5 files changed, 15 insertions(+), 67 deletions(-) diff --git a/objc_sys/src/class.rs b/objc_sys/src/class.rs index 6bcb8e9c7..cdb026ec0 100644 --- a/objc_sys/src/class.rs +++ b/objc_sys/src/class.rs @@ -8,8 +8,8 @@ use crate::{ /// An opaque type that represents an Objective-C class. #[repr(C)] pub struct objc_class { - // `isa` field is deprecated, so we don't expose it here. - // Use `class_getSuperclass` instead. + // `isa` field is deprecated and not available on GNUStep, so we don't + // expose it here. Use `class_getSuperclass` instead. _priv: [u8; 0], _p: OpaqueData, } diff --git a/objc_sys/src/message.rs b/objc_sys/src/message.rs index 15466a22b..65c611296 100644 --- a/objc_sys/src/message.rs +++ b/objc_sys/src/message.rs @@ -11,6 +11,8 @@ pub struct objc_super { /// The object / instance to send a message to. pub receiver: *mut objc_object, /// The particular superclass of the instance to message. + /// + /// Named `class` in GNUStep and in older Objective-C versions. pub super_class: *const objc_class, } diff --git a/objc_sys/src/protocol.rs b/objc_sys/src/protocol.rs index f72904167..c8bbcec43 100644 --- a/objc_sys/src/protocol.rs +++ b/objc_sys/src/protocol.rs @@ -5,7 +5,13 @@ use crate::{ BOOL, }; -/// Nonstandard naming, actually... (TODO) +/// Opaque type for Objective-C protocols. +/// +/// Note that, although protocols are objects, sending messages to them is +/// deprecated and may not work in the future. +/// +/// The naming of this follows GNUStep; this does not exist in Apple's +/// original, there `Protocol` is just a type alias of `objc_object`. #[repr(C)] pub struct objc_protocol { _priv: [u8; 0], diff --git a/objc_sys/src/tmp_gnustep.rs b/objc_sys/src/tmp_gnustep.rs index a7c3f55cf..6ef1e5f8f 100644 --- a/objc_sys/src/tmp_gnustep.rs +++ b/objc_sys/src/tmp_gnustep.rs @@ -22,68 +22,6 @@ pub const OBJC_ARC_AUTORELEASE_DEBUG: u32 = 16; pub const OBJC_CAP_TRACING: u32 = 17; #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct objc_ivar { - _unused: [u8; 0], -} -pub type Ivar = *mut objc_ivar; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_selector { - _unused: [u8; 0], -} -pub type SEL = *mut objc_selector; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_class { - _unused: [u8; 0], -} -pub type Class = *mut objc_class; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_object { - pub isa: Class, -} -pub type id = *mut objc_object; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_super { - pub receiver: id, - pub class: Class, -} -pub type IMP = ::std::option::Option id>; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_method { - _unused: [u8; 0], -} -pub type Method = *mut objc_method; -pub type BOOL = ::std::os::raw::c_uchar; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_property { - _unused: [u8; 0], -} -pub type objc_property_t = *mut objc_property; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_protocol { - _unused: [u8; 0], -} -pub type Protocol = objc_protocol; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_method_description { - pub name: SEL, - pub types: *const ::std::os::raw::c_char, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_property_attribute_t { - pub name: *const ::std::os::raw::c_char, - pub value: *const ::std::os::raw::c_char, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] pub struct objc_slot2 { pub method: IMP, } diff --git a/objc_sys/src/types.rs b/objc_sys/src/types.rs index b8fb91d99..f98e151c1 100644 --- a/objc_sys/src/types.rs +++ b/objc_sys/src/types.rs @@ -8,9 +8,11 @@ use crate::{ /// /// To convert an Objective-C `BOOL` into a Rust [`bool`], compare it with /// [`NO`][`super::NO`]. -#[cfg(all(target_vendor = "apple", not(target_arch = "aarch64")))] +#[cfg(all(apple, not(target_arch = "aarch64")))] pub type BOOL = i8; -#[cfg(all(not(target_vendor = "apple"), not(target_arch = "aarch64")))] +/// TODO: Only if STRICT_APPLE_COMPATIBILITY is NOT defined. +/// TODO: (__vxworks || _WIN32) becomes BOOL = c_int. +#[cfg(all(gnustep, not(target_arch = "aarch64")))] pub type BOOL = u8; #[cfg(target_arch = "aarch64")] pub type BOOL = bool; From 87504cde34e71b7d36aca457ffa9b5b4ce348cdb Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 5 Sep 2021 23:41:16 +0200 Subject: [PATCH 27/36] sys: Mark Apple-only functions and types --- objc_sys/src/class.rs | 3 +++ objc_sys/src/constants.rs | 4 ++++ objc_sys/src/exception.rs | 1 + objc_sys/src/lib.rs | 2 ++ objc_sys/src/message.rs | 9 +++++++++ objc_sys/src/method.rs | 1 + objc_sys/src/object.rs | 6 ++++++ objc_sys/src/selector.rs | 1 + objc_sys/src/various.rs | 15 +++++++++++---- 9 files changed, 38 insertions(+), 4 deletions(-) diff --git a/objc_sys/src/class.rs b/objc_sys/src/class.rs index cdb026ec0..b9ea8f0fd 100644 --- a/objc_sys/src/class.rs +++ b/objc_sys/src/class.rs @@ -27,6 +27,7 @@ extern "C" { name: *const c_char, extra_bytes: usize, ) -> *mut objc_class; + #[cfg(apple)] pub fn objc_duplicateClass( original: *const objc_class, name: *const c_char, @@ -95,6 +96,7 @@ extern "C" { pub fn class_getProperty(cls: *const objc_class, name: *const c_char) -> *const objc_property; pub fn class_getSuperclass(cls: *const objc_class) -> *const objc_class; pub fn class_getVersion(cls: *const objc_class) -> c_int; + #[cfg(apple)] pub fn class_getWeakIvarLayout(cls: *const objc_class) -> *const u8; pub fn class_isMetaClass(cls: *const objc_class) -> BOOL; pub fn class_replaceMethod( @@ -112,5 +114,6 @@ extern "C" { pub fn class_respondsToSelector(cls: *const objc_class, sel: *const objc_selector) -> BOOL; pub fn class_setIvarLayout(cls: *mut objc_class, layout: *const u8); pub fn class_setVersion(cls: *mut objc_class, version: c_int); + #[cfg(apple)] pub fn class_setWeakIvarLayout(cls: *mut objc_class, layout: *const u8); } diff --git a/objc_sys/src/constants.rs b/objc_sys/src/constants.rs index 1dafc423d..fad034c11 100644 --- a/objc_sys/src/constants.rs +++ b/objc_sys/src/constants.rs @@ -29,9 +29,13 @@ pub const OBJC_ASSOCIATION_COPY_NONATOMIC: objc_AssociationPolicy = 3; pub const OBJC_ASSOCIATION_RETAIN: objc_AssociationPolicy = 769; pub const OBJC_ASSOCIATION_COPY: objc_AssociationPolicy = 771; +#[cfg(apple)] pub const OBJC_SYNC_SUCCESS: c_int = 0; +#[cfg(apple)] pub const OBJC_SYNC_NOT_OWNING_THREAD_ERROR: c_int = -1; /// Only relevant before macOS 10.13 +#[cfg(apple)] pub const OBJC_SYNC_TIMED_OUT: c_int = -2; /// Only relevant before macOS 10.13 +#[cfg(apple)] pub const OBJC_SYNC_NOT_INITIALIZED: c_int = -3; diff --git a/objc_sys/src/exception.rs b/objc_sys/src/exception.rs index 3c13e0925..c6dd85446 100644 --- a/objc_sys/src/exception.rs +++ b/objc_sys/src/exception.rs @@ -1,3 +1,4 @@ +//! Only available with Apple's objc4. use core::ffi::c_void; use std::os::raw::c_int; diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index 078a56019..ed01af371 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -24,6 +24,7 @@ use core::marker::{PhantomData, PhantomPinned}; mod class; mod constants; +#[cfg(apple)] mod exception; mod message; mod method; @@ -37,6 +38,7 @@ mod various; pub use class::*; pub use constants::*; +#[cfg(apple)] pub use exception::*; pub use message::*; pub use method::*; diff --git a/objc_sys/src/message.rs b/objc_sys/src/message.rs index 65c611296..7a690a455 100644 --- a/objc_sys/src/message.rs +++ b/objc_sys/src/message.rs @@ -1,6 +1,8 @@ //! The `objc_msgSend` familiy of functions. //! //! Most of these are `cfg`-gated, these configs are semver-stable. +//! +//! TODO: Some of these are only supported on _some_ GNUStep targets! use super::{objc_class, objc_object}; /// Specifies data used when sending messages to superclasses. @@ -18,8 +20,11 @@ pub struct objc_super { extern "C" { pub fn objc_msgSend(); + #[cfg(apple)] pub fn objc_msgSendSuper(); + #[cfg(apple)] pub fn method_invoke(); + #[cfg(apple)] pub fn _objc_msgForward(); pub fn class_getMethodImplementation(); } @@ -29,10 +34,13 @@ extern "C" { /// Not available on `target_arch = "aarch64"` pub fn objc_msgSend_stret(); /// Not available on `target_arch = "aarch64"` + #[cfg(apple)] pub fn objc_msgSendSuper_stret(); /// Not available on `target_arch = "aarch64"` + #[cfg(apple)] pub fn method_invoke_stret(); /// Not available on `target_arch = "aarch64"` + #[cfg(apple)] pub fn _objc_msgForward_stret(); /// Not available on `target_arch = "aarch64"` pub fn class_getMethodImplementation_stret(); @@ -47,5 +55,6 @@ extern "C" { #[cfg(target_arch = "x86_64")] // __x86_64__ extern "C" { /// Only available on `target_arch = "x86_64"` + #[cfg(apple)] pub fn objc_msgSend_fp2ret(); } diff --git a/objc_sys/src/method.rs b/objc_sys/src/method.rs index 766fc74ca..055f4f597 100644 --- a/objc_sys/src/method.rs +++ b/objc_sys/src/method.rs @@ -26,6 +26,7 @@ extern "C" { dst: *mut c_char, dst_len: usize, ); + #[cfg(apple)] pub fn method_getDescription(m: *const objc_method) -> *const objc_method_description; pub fn method_getImplementation(method: *const objc_method) -> IMP; pub fn method_getName(method: *const objc_method) -> *const objc_selector; diff --git a/objc_sys/src/object.rs b/objc_sys/src/object.rs index 464253278..12ca45664 100644 --- a/objc_sys/src/object.rs +++ b/objc_sys/src/object.rs @@ -22,8 +22,10 @@ extern "C" { pub fn object_setIvar(obj: *mut objc_object, ivar: *const objc_ivar, value: *mut objc_object); #[deprecated = "Not needed since ARC"] + #[cfg(apple)] pub fn object_copy(obj: *const objc_object, size: usize) -> *mut objc_object; #[deprecated = "Not needed since ARC"] + #[cfg(apple)] pub fn object_dispose(obj: *mut objc_object) -> *mut objc_object; #[deprecated = "Not needed since ARC"] pub fn object_setInstanceVariable( @@ -32,6 +34,7 @@ extern "C" { value: *mut c_void, ) -> *const objc_ivar; #[deprecated = "Not needed since ARC"] + #[cfg(apple)] pub fn object_setInstanceVariableWithStrongDefault( obj: *mut objc_object, name: *const c_char, @@ -44,9 +47,12 @@ extern "C" { out_value: *mut *const c_void, ) -> *const objc_ivar; #[deprecated = "Not needed since ARC"] + #[cfg(apple)] pub fn objc_getFutureClass(name: *const c_char) -> *const objc_class; #[deprecated = "Not needed since ARC"] + #[cfg(apple)] pub fn objc_constructInstance(cls: *const objc_class, bytes: *mut c_void) -> *mut objc_object; #[deprecated = "Not needed since ARC"] + #[cfg(apple)] pub fn objc_destructInstance(obj: *mut objc_object) -> *mut c_void; } diff --git a/objc_sys/src/selector.rs b/objc_sys/src/selector.rs index 788e213f7..92b3318f2 100644 --- a/objc_sys/src/selector.rs +++ b/objc_sys/src/selector.rs @@ -13,6 +13,7 @@ extern "C" { pub fn sel_getName(sel: *const objc_selector) -> *const c_char; pub fn sel_getUid(name: *const c_char) -> *const objc_selector; pub fn sel_isEqual(lhs: *const objc_selector, rhs: *const objc_selector) -> BOOL; + #[cfg(apple)] pub fn sel_isMapped(sel: *const objc_selector) -> BOOL; pub fn sel_registerName(name: *const c_char) -> *const objc_selector; } diff --git a/objc_sys/src/various.rs b/objc_sys/src/various.rs index af068bdc7..7378abe7c 100644 --- a/objc_sys/src/various.rs +++ b/objc_sys/src/various.rs @@ -18,14 +18,14 @@ pub type IMP = unsafe extern "C" fn(); /// Not available on macOS x86. /// /// Remember that this is non-null! -#[cfg(not(all(target_os = "macos", target_arch = "x86")))] +#[cfg(all(apple, not(all(target_os = "macos", target_arch = "x86"))))] pub type objc_hook_getClass = unsafe extern "C" fn(name: *const c_char, out_cls: *mut *const objc_class) -> BOOL; /// Not available on macOS x86. /// /// Remember that this is non-null! -#[cfg(not(all(target_os = "macos", target_arch = "x86")))] +#[cfg(all(apple, not(all(target_os = "macos", target_arch = "x86"))))] pub type objc_hook_lazyClassNamer = unsafe extern "C" fn(cls: *const objc_class) -> *const c_char; extern "C" { @@ -37,13 +37,17 @@ extern "C" { pub fn ivar_getOffset(ivar: *const objc_ivar) -> isize; pub fn ivar_getTypeEncoding(ivar: *const objc_ivar) -> *const c_char; + #[cfg(apple)] pub fn objc_copyClassNamesForImage( image: *const c_char, out_len: *mut c_uint, ) -> *mut *const c_char; + #[cfg(apple)] pub fn objc_copyImageNames(out_len: *mut c_uint) -> *mut *const c_char; + #[cfg(apple)] pub fn objc_enumerationMutation(obj: *mut objc_object); + #[cfg(apple)] pub fn objc_setEnumerationMutationHandler( handler: Option, ); @@ -60,14 +64,17 @@ extern "C" { ); pub fn objc_removeAssociatedObjects(object: *mut objc_object); + #[cfg(apple)] pub fn objc_setForwardHandler(fwd: *mut c_void, fwd_stret: *mut c_void); + #[cfg(apple)] pub fn objc_sync_enter(obj: *mut objc_object) -> c_int; + #[cfg(apple)] pub fn objc_sync_exit(obj: *mut objc_object) -> c_int; /// Not available on macOS x86. /// /// Remember that this is non-null! - #[cfg(not(all(target_os = "macos", target_arch = "x86")))] + #[cfg(all(apple, not(all(target_os = "macos", target_arch = "x86"))))] pub fn objc_setHook_getClass( new_value: objc_hook_getClass, out_old_value: *mut objc_hook_getClass, @@ -75,7 +82,7 @@ extern "C" { /// Not available on macOS x86. /// /// Remember that this is non-null! - #[cfg(not(all(target_os = "macos", target_arch = "x86")))] + #[cfg(all(apple, not(all(target_os = "macos", target_arch = "x86"))))] pub fn objc_setHook_lazyClassNamer( new_value: objc_hook_lazyClassNamer, out_old_value: *mut objc_hook_lazyClassNamer, From 39faf9e970f2da42b69260cdd6a84ed9a579c83f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 5 Sep 2021 23:34:55 +0200 Subject: [PATCH 28/36] sys: Remove GNUStep functions that we've already defined --- objc_sys/src/class.rs | 17 +- objc_sys/src/protocol.rs | 14 +- objc_sys/src/tmp_gnustep.rs | 386 ------------------------------------ 3 files changed, 20 insertions(+), 397 deletions(-) diff --git a/objc_sys/src/class.rs b/objc_sys/src/class.rs index b9ea8f0fd..2aeee17fd 100644 --- a/objc_sys/src/class.rs +++ b/objc_sys/src/class.rs @@ -14,6 +14,15 @@ pub struct objc_class { _p: OpaqueData, } +/// This is `c_char` in GNUStep's libobjc2 and `uint8_t` in Apple's objc4. +/// +/// The pointer represents opaque data, and is definitely not just an integer, +/// so its signedness (i8 vs. u8) is not applicable. +/// +/// So we just assign it here as a private alias to u8, to not document the +/// difference. +type ivar_layout_type = u8; + extern "C" { pub fn objc_getClass(name: *const c_char) -> *const objc_class; pub fn objc_getRequiredClass(name: *const c_char) -> *const objc_class; @@ -91,13 +100,13 @@ extern "C" { cls: *const objc_class, name: *const c_char, ) -> *const objc_ivar; - pub fn class_getIvarLayout(cls: *const objc_class) -> *const u8; + pub fn class_getIvarLayout(cls: *const objc_class) -> *const ivar_layout_type; pub fn class_getName(cls: *const objc_class) -> *const c_char; pub fn class_getProperty(cls: *const objc_class, name: *const c_char) -> *const objc_property; pub fn class_getSuperclass(cls: *const objc_class) -> *const objc_class; pub fn class_getVersion(cls: *const objc_class) -> c_int; #[cfg(apple)] - pub fn class_getWeakIvarLayout(cls: *const objc_class) -> *const u8; + pub fn class_getWeakIvarLayout(cls: *const objc_class) -> *const ivar_layout_type; pub fn class_isMetaClass(cls: *const objc_class) -> BOOL; pub fn class_replaceMethod( cls: *mut objc_class, @@ -112,8 +121,8 @@ extern "C" { attributes_len: c_uint, ); pub fn class_respondsToSelector(cls: *const objc_class, sel: *const objc_selector) -> BOOL; - pub fn class_setIvarLayout(cls: *mut objc_class, layout: *const u8); + pub fn class_setIvarLayout(cls: *mut objc_class, layout: *const ivar_layout_type); pub fn class_setVersion(cls: *mut objc_class, version: c_int); #[cfg(apple)] - pub fn class_setWeakIvarLayout(cls: *mut objc_class, layout: *const u8); + pub fn class_setWeakIvarLayout(cls: *mut objc_class, layout: *const ivar_layout_type); } diff --git a/objc_sys/src/protocol.rs b/objc_sys/src/protocol.rs index c8bbcec43..06b202601 100644 --- a/objc_sys/src/protocol.rs +++ b/objc_sys/src/protocol.rs @@ -29,8 +29,8 @@ extern "C" { proto: *mut objc_protocol, name: *const objc_selector, types: *const c_char, - isRequiredMethod: BOOL, - isInstanceMethod: BOOL, + is_required_method: BOOL, + is_instance_method: BOOL, ); pub fn protocol_addProperty( proto: *mut objc_protocol, @@ -61,16 +61,16 @@ extern "C" { ) -> *mut *const objc_protocol; pub fn protocol_getMethodDescription( proto: *const objc_protocol, - aSel: *const objc_selector, - isRequiredMethod: BOOL, - isInstanceMethod: BOOL, + sel: *const objc_selector, + is_required_method: BOOL, + is_instance_method: BOOL, ) -> objc_method_description; pub fn protocol_getName(proto: *const objc_protocol) -> *const c_char; pub fn protocol_getProperty( proto: *const objc_protocol, name: *const c_char, - isRequiredProperty: BOOL, - isInstanceProperty: BOOL, + is_required_property: BOOL, + is_instance_property: BOOL, ) -> *const objc_property; pub fn protocol_isEqual(proto: *const objc_protocol, other: *const objc_protocol) -> BOOL; } diff --git a/objc_sys/src/tmp_gnustep.rs b/objc_sys/src/tmp_gnustep.rs index 6ef1e5f8f..89c759b87 100644 --- a/objc_sys/src/tmp_gnustep.rs +++ b/objc_sys/src/tmp_gnustep.rs @@ -38,322 +38,9 @@ pub struct objc_slot { pub method: IMP, pub selector: SEL, } -extern "C" { - pub fn objc_msgSend(self_: id, _cmd: SEL, ...) -> id; -} -extern "C" { - pub fn objc_msgSend_stret(self_: id, _cmd: SEL, ...); -} -extern "C" { - pub fn objc_msgSend_fpret(self_: id, _cmd: SEL, ...) -> u128; -} -extern "C" { - pub fn class_addIvar( - cls: Class, - name: *const ::std::os::raw::c_char, - size: usize, - alignment: u8, - types: *const ::std::os::raw::c_char, - ) -> BOOL; -} -extern "C" { - pub fn class_addMethod( - cls: Class, - name: SEL, - imp: IMP, - types: *const ::std::os::raw::c_char, - ) -> BOOL; -} -extern "C" { - pub fn class_addProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; -} -extern "C" { - pub fn class_conformsToProtocol(cls: Class, protocol: *mut Protocol) -> BOOL; -} -extern "C" { - pub fn class_copyIvarList(cls: Class, outCount: *mut ::std::os::raw::c_uint) -> *mut Ivar; -} -extern "C" { - pub fn class_copyMethodList(cls: Class, outCount: *mut ::std::os::raw::c_uint) -> *mut Method; -} -extern "C" { - pub fn class_copyPropertyList( - cls: Class, - outCount: *mut ::std::os::raw::c_uint, - ) -> *mut objc_property_t; -} -extern "C" { - pub fn class_copyProtocolList( - cls: Class, - outCount: *mut ::std::os::raw::c_uint, - ) -> *mut *mut Protocol; -} -extern "C" { - pub fn class_createInstance(cls: Class, extraBytes: usize) -> id; -} -extern "C" { - pub fn class_getClassMethod(aClass: Class, aSelector: SEL) -> Method; -} -extern "C" { - pub fn class_getClassVariable(cls: Class, name: *const ::std::os::raw::c_char) -> Ivar; -} -extern "C" { - pub fn class_getInstanceMethod(aClass: Class, aSelector: SEL) -> Method; -} -extern "C" { - pub fn class_getInstanceSize(cls: Class) -> usize; -} -extern "C" { - pub fn class_getInstanceVariable(cls: Class, name: *const ::std::os::raw::c_char) -> Ivar; -} -extern "C" { - pub fn object_setIvar(object: id, ivar: Ivar, value: id); -} -extern "C" { - pub fn object_setInstanceVariable( - obj: id, - name: *const ::std::os::raw::c_char, - value: *mut ::std::os::raw::c_void, - ) -> Ivar; -} -extern "C" { - pub fn object_getIvar(object: id, ivar: Ivar) -> id; -} -extern "C" { - pub fn object_getInstanceVariable( - obj: id, - name: *const ::std::os::raw::c_char, - outValue: *mut *mut ::std::os::raw::c_void, - ) -> Ivar; -} -extern "C" { - pub fn class_getMethodImplementation(cls: Class, name: SEL) -> IMP; -} -extern "C" { - pub fn class_getMethodImplementation_stret(cls: Class, name: SEL) -> IMP; -} -extern "C" { - pub fn class_getName(cls: Class) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn class_getProperty(cls: Class, name: *const ::std::os::raw::c_char) -> objc_property_t; -} -extern "C" { - pub fn class_getSuperclass(cls: Class) -> Class; -} -extern "C" { - pub fn class_getVersion(theClass: Class) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn class_setVersion(theClass: Class, version: ::std::os::raw::c_int); -} -extern "C" { - pub fn class_getWeakIvarLayout(cls: Class) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn class_isMetaClass(cls: Class) -> BOOL; -} -extern "C" { - pub fn class_replaceMethod( - cls: Class, - name: SEL, - imp: IMP, - types: *const ::std::os::raw::c_char, - ) -> IMP; -} -extern "C" { - pub fn class_respondsToSelector(cls: Class, sel: SEL) -> BOOL; -} -extern "C" { - pub fn class_getIvarLayout(cls: Class) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn class_setIvarLayout(cls: Class, layout: *const ::std::os::raw::c_char); -} extern "C" { pub fn class_setSuperclass(cls: Class, newSuper: Class) -> Class; } -extern "C" { - pub fn class_setWeakIvarLayout(cls: Class, layout: *const ::std::os::raw::c_char); -} -extern "C" { - pub fn ivar_getName(ivar: Ivar) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn ivar_getOffset(ivar: Ivar) -> isize; -} -extern "C" { - pub fn ivar_getTypeEncoding(ivar: Ivar) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn method_copyArgumentType( - method: Method, - index: ::std::os::raw::c_uint, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn method_copyReturnType(method: Method) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn method_exchangeImplementations(m1: Method, m2: Method); -} -extern "C" { - pub fn method_getArgumentType( - method: Method, - index: ::std::os::raw::c_uint, - dst: *mut ::std::os::raw::c_char, - dst_len: usize, - ); -} -extern "C" { - pub fn method_getImplementation(method: Method) -> IMP; -} -extern "C" { - pub fn method_getName(method: Method) -> SEL; -} -extern "C" { - pub fn method_getNumberOfArguments(method: Method) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn method_getReturnType(method: Method, dst: *mut ::std::os::raw::c_char, dst_len: usize); -} -extern "C" { - pub fn method_getTypeEncoding(method: Method) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn method_setImplementation(method: Method, imp: IMP) -> IMP; -} -extern "C" { - pub fn objc_allocateClassPair( - superclass: Class, - name: *const ::std::os::raw::c_char, - extraBytes: usize, - ) -> Class; -} -extern "C" { - pub fn objc_disposeClassPair(cls: Class); -} -extern "C" { - pub fn objc_getClass(name: *const ::std::os::raw::c_char) -> id; -} -extern "C" { - pub fn objc_getClassList( - buffer: *mut Class, - bufferLen: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn objc_copyClassList(outCount: *mut ::std::os::raw::c_uint) -> *mut Class; -} -extern "C" { - pub fn objc_getMetaClass(name: *const ::std::os::raw::c_char) -> id; -} -extern "C" { - pub fn objc_getRequiredClass(name: *const ::std::os::raw::c_char) -> id; -} -extern "C" { - pub fn objc_lookUpClass(name: *const ::std::os::raw::c_char) -> id; -} -extern "C" { - pub fn objc_getProtocol(name: *const ::std::os::raw::c_char) -> *mut Protocol; -} -extern "C" { - pub fn objc_allocateProtocol(name: *const ::std::os::raw::c_char) -> *mut Protocol; -} -extern "C" { - pub fn objc_registerProtocol(proto: *mut Protocol); -} -extern "C" { - pub fn protocol_addMethodDescription( - aProtocol: *mut Protocol, - name: SEL, - types: *const ::std::os::raw::c_char, - isRequiredMethod: BOOL, - isInstanceMethod: BOOL, - ); -} -extern "C" { - pub fn protocol_addProtocol(aProtocol: *mut Protocol, addition: *mut Protocol); -} -extern "C" { - pub fn protocol_addProperty( - aProtocol: *mut Protocol, - name: *const ::std::os::raw::c_char, - attributes: *const objc_property_attribute_t, - attributeCount: ::std::os::raw::c_uint, - isRequiredProperty: BOOL, - isInstanceProperty: BOOL, - ); -} -extern "C" { - pub fn objc_registerClassPair(cls: Class); -} -extern "C" { - pub fn object_getIndexedIvars(obj: id) -> *mut ::std::os::raw::c_void; -} -extern "C" { - pub fn object_dispose(obj: id) -> id; -} -extern "C" { - pub fn object_getClass(obj: id) -> Class; -} -extern "C" { - pub fn object_setClass(obj: id, cls: Class) -> Class; -} -extern "C" { - pub fn object_getClassName(obj: id) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn property_getName(property: objc_property_t) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn property_getAttributes(property: objc_property_t) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn property_copyAttributeList( - property: objc_property_t, - outCount: *mut ::std::os::raw::c_uint, - ) -> *mut objc_property_attribute_t; -} -extern "C" { - pub fn class_addProperty( - cls: Class, - name: *const ::std::os::raw::c_char, - attributes: *const objc_property_attribute_t, - attributeCount: ::std::os::raw::c_uint, - ) -> BOOL; -} -extern "C" { - pub fn class_replaceProperty( - cls: Class, - name: *const ::std::os::raw::c_char, - attributes: *const objc_property_attribute_t, - attributeCount: ::std::os::raw::c_uint, - ); -} -extern "C" { - pub fn property_copyAttributeValue( - property: objc_property_t, - attributeName: *const ::std::os::raw::c_char, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn protocol_conformsToProtocol(p: *mut Protocol, other: *mut Protocol) -> BOOL; -} -extern "C" { - pub fn protocol_copyMethodDescriptionList( - p: *mut Protocol, - isRequiredMethod: BOOL, - isInstanceMethod: BOOL, - count: *mut ::std::os::raw::c_uint, - ) -> *mut objc_method_description; -} -extern "C" { - pub fn protocol_copyPropertyList( - p: *mut Protocol, - count: *mut ::std::os::raw::c_uint, - ) -> *mut objc_property_t; -} extern "C" { pub fn protocol_copyPropertyList2( p: *mut Protocol, @@ -362,23 +49,6 @@ extern "C" { isInstanceProperty: BOOL, ) -> *mut objc_property_t; } -extern "C" { - pub fn protocol_copyProtocolList( - p: *mut Protocol, - count: *mut ::std::os::raw::c_uint, - ) -> *mut *mut Protocol; -} -extern "C" { - pub fn objc_copyProtocolList(outCount: *mut ::std::os::raw::c_uint) -> *mut *mut Protocol; -} -extern "C" { - pub fn protocol_getMethodDescription( - p: *mut Protocol, - aSel: SEL, - isRequiredMethod: BOOL, - isInstanceMethod: BOOL, - ) -> objc_method_description; -} extern "C" { pub fn _protocol_getMethodTypeEncoding( p: *mut Protocol, @@ -387,38 +57,12 @@ extern "C" { isInstanceMethod: BOOL, ) -> *const ::std::os::raw::c_char; } -extern "C" { - pub fn protocol_getName(p: *mut Protocol) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn protocol_getProperty( - p: *mut Protocol, - name: *const ::std::os::raw::c_char, - isRequiredProperty: BOOL, - isInstanceProperty: BOOL, - ) -> objc_property_t; -} -extern "C" { - pub fn protocol_isEqual(p: *mut Protocol, other: *mut Protocol) -> BOOL; -} extern "C" { pub fn objc_msg_lookup(arg1: id, arg2: SEL) -> IMP; } extern "C" { pub fn objc_msg_lookup_super(arg1: *mut objc_super, arg2: SEL) -> IMP; } -extern "C" { - pub fn sel_getName(sel: SEL) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn sel_getUid(selName: *const ::std::os::raw::c_char) -> SEL; -} -extern "C" { - pub fn sel_isEqual(sel1: SEL, sel2: SEL) -> BOOL; -} -extern "C" { - pub fn sel_registerName(selName: *const ::std::os::raw::c_char) -> SEL; -} extern "C" { pub fn objc_msg_lookup_sender(receiver: *mut id, selector: SEL, sender: id) -> *mut objc_slot; } @@ -438,36 +82,6 @@ extern "C" { extern "C" { pub fn objc_msg_lookup2(receiver: *mut id, selector: SEL) -> IMP; } -pub const OBJC_ASSOCIATION_ASSIGN: ::std::os::raw::c_uint = 0; -pub const OBJC_ASSOCIATION_RETAIN_NONATOMIC: ::std::os::raw::c_uint = 1; -pub const OBJC_ASSOCIATION_COPY_NONATOMIC: ::std::os::raw::c_uint = 3; -pub const OBJC_ASSOCIATION_RETAIN: ::std::os::raw::c_uint = 769; -pub const OBJC_ASSOCIATION_COPY: ::std::os::raw::c_uint = 771; -pub type _bindgen_ty_1 = ::std::os::raw::c_uint; -pub type objc_AssociationPolicy = usize; -extern "C" { - pub fn objc_getAssociatedObject(object: id, key: *const ::std::os::raw::c_void) -> id; -} -extern "C" { - pub fn objc_setAssociatedObject( - object: id, - key: *const ::std::os::raw::c_void, - value: id, - policy: objc_AssociationPolicy, - ); -} -extern "C" { - pub fn objc_removeAssociatedObjects(object: id); -} -extern "C" { - pub fn imp_implementationWithBlock(block: id) -> IMP; -} -extern "C" { - pub fn imp_getBlock(anImp: IMP) -> id; -} -extern "C" { - pub fn imp_removeBlock(anImp: IMP) -> BOOL; -} extern "C" { pub fn objc_set_apple_compatible_objcxx_exceptions( newValue: ::std::os::raw::c_int, From 513ed03aea9786b5d35fd512a2b43c4dbd626a47 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 6 Sep 2021 00:03:18 +0200 Subject: [PATCH 29/36] sys: Remove some deprecated and non-available GNUStep functions --- objc_sys/src/class.rs | 9 ++++ objc_sys/src/lib.rs | 4 +- objc_sys/src/object.rs | 7 +++ objc_sys/src/protocol.rs | 6 +++ objc_sys/src/tmp_gnustep.rs | 91 ------------------------------------- objc_sys/src/various.rs | 4 ++ 6 files changed, 28 insertions(+), 93 deletions(-) diff --git a/objc_sys/src/class.rs b/objc_sys/src/class.rs index 2aeee17fd..bc5c43db6 100644 --- a/objc_sys/src/class.rs +++ b/objc_sys/src/class.rs @@ -125,4 +125,13 @@ extern "C" { pub fn class_setVersion(cls: *mut objc_class, version: c_int); #[cfg(apple)] pub fn class_setWeakIvarLayout(cls: *mut objc_class, layout: *const ivar_layout_type); + + // #[deprecated = "not recommended"] + // pub fn class_setSuperclass + // #[deprecated = "use class_getMethodImplementation instead"] + // #[cfg(apple)] + // pub fn class_lookupMethod + // #[deprecated = "use class_respondsToSelector instead"] + // #[cfg(apple)] + // pub fn class_respondsToMethod } diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index ed01af371..653ba08af 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -6,8 +6,8 @@ //! better type safety. Their internal representation is the same, so the //! functionality is just a cast away. //! -//! Deprecated functions are not included since they could be removed at any -//! macOS release, and then our code would break. +//! Deprecated functions are not included for future compability, since they +//! could be removed at any macOS release, and then our code would break. // TODO: Replace `extern "C"` with `extern "C-unwind"`. diff --git a/objc_sys/src/object.rs b/objc_sys/src/object.rs index 12ca45664..c9976869c 100644 --- a/objc_sys/src/object.rs +++ b/objc_sys/src/object.rs @@ -55,4 +55,11 @@ extern "C" { #[deprecated = "Not needed since ARC"] #[cfg(apple)] pub fn objc_destructInstance(obj: *mut objc_object) -> *mut c_void; + + // #[deprecated = "use object_copy instead"] + // #[cfg(all(apple, target_os = "macos"))] + // object_copyFromZone + // #[deprecated = "use class_createInstance instead"] + // #[cfg(all(apple, target_os = "macos"))] + // class_createInstanceFromZone } diff --git a/objc_sys/src/protocol.rs b/objc_sys/src/protocol.rs index 06b202601..bc957b679 100644 --- a/objc_sys/src/protocol.rs +++ b/objc_sys/src/protocol.rs @@ -73,4 +73,10 @@ extern "C" { is_instance_property: BOOL, ) -> *const objc_property; pub fn protocol_isEqual(proto: *const objc_protocol, other: *const objc_protocol) -> BOOL; + + // #[cfg(macos >= 10.12)] + // protocol_copyPropertyList2 + + // #[cfg(gnustep)] + // _protocol_getMethodTypeEncoding } diff --git a/objc_sys/src/tmp_gnustep.rs b/objc_sys/src/tmp_gnustep.rs index 89c759b87..5d897a0d7 100644 --- a/objc_sys/src/tmp_gnustep.rs +++ b/objc_sys/src/tmp_gnustep.rs @@ -38,25 +38,6 @@ pub struct objc_slot { pub method: IMP, pub selector: SEL, } -extern "C" { - pub fn class_setSuperclass(cls: Class, newSuper: Class) -> Class; -} -extern "C" { - pub fn protocol_copyPropertyList2( - p: *mut Protocol, - count: *mut ::std::os::raw::c_uint, - isRequiredProperty: BOOL, - isInstanceProperty: BOOL, - ) -> *mut objc_property_t; -} -extern "C" { - pub fn _protocol_getMethodTypeEncoding( - p: *mut Protocol, - aSel: SEL, - isRequiredMethod: BOOL, - isInstanceMethod: BOOL, - ) -> *const ::std::os::raw::c_char; -} extern "C" { pub fn objc_msg_lookup(arg1: id, arg2: SEL) -> IMP; } @@ -87,78 +68,6 @@ extern "C" { newValue: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } -extern "C" { - pub fn objc_malloc(size: usize) -> *mut ::std::os::raw::c_void; -} -extern "C" { - pub fn objc_atomic_malloc(size: usize) -> *mut ::std::os::raw::c_void; -} -extern "C" { - pub fn objc_valloc(size: usize) -> *mut ::std::os::raw::c_void; -} -extern "C" { - pub fn objc_realloc( - mem: *mut ::std::os::raw::c_void, - size: usize, - ) -> *mut ::std::os::raw::c_void; -} -extern "C" { - pub fn objc_calloc(nelem: usize, size: usize) -> *mut ::std::os::raw::c_void; -} -extern "C" { - pub fn objc_free(mem: *mut ::std::os::raw::c_void); -} -extern "C" { - pub fn objc_get_class(name: *const ::std::os::raw::c_char) -> id; -} -extern "C" { - pub fn objc_lookup_class(name: *const ::std::os::raw::c_char) -> id; -} -extern "C" { - pub fn objc_get_meta_class(name: *const ::std::os::raw::c_char) -> id; -} -extern "C" { - pub fn objc_next_class(enum_state: *mut *mut ::std::os::raw::c_void) -> Class; -} -extern "C" { - pub fn class_pose_as(impostor: Class, super_class: Class) -> Class; -} -extern "C" { - pub fn sel_get_typed_uid( - name: *const ::std::os::raw::c_char, - types: *const ::std::os::raw::c_char, - ) -> SEL; -} -extern "C" { - pub fn sel_get_any_typed_uid(name: *const ::std::os::raw::c_char) -> SEL; -} -extern "C" { - pub fn sel_get_any_uid(name: *const ::std::os::raw::c_char) -> SEL; -} -extern "C" { - pub fn sel_get_uid(name: *const ::std::os::raw::c_char) -> SEL; -} -extern "C" { - pub fn sel_get_name(selector: SEL) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn sel_is_mapped(selector: SEL) -> BOOL; -} -extern "C" { - pub fn sel_get_type(selector: SEL) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn sel_register_name(name: *const ::std::os::raw::c_char) -> SEL; -} -extern "C" { - pub fn sel_register_typed_name( - name: *const ::std::os::raw::c_char, - type_: *const ::std::os::raw::c_char, - ) -> SEL; -} -extern "C" { - pub fn sel_eq(s1: SEL, s2: SEL) -> BOOL; -} extern "C" { pub fn objc_test_capability(x: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } diff --git a/objc_sys/src/various.rs b/objc_sys/src/various.rs index 7378abe7c..0c78da6bd 100644 --- a/objc_sys/src/various.rs +++ b/objc_sys/src/various.rs @@ -87,4 +87,8 @@ extern "C" { new_value: objc_hook_lazyClassNamer, out_old_value: *mut objc_hook_lazyClassNamer, ); + + // #[deprecated = "not recommended"] + // #[cfg(apple)] + // pub fn _objc_flush_caches } From 4d72245479727f0ce24c05bd2e8b79f5f19732be Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 6 Sep 2021 00:20:43 +0200 Subject: [PATCH 30/36] sys: Configure GNUStep exception functions --- objc_sys/src/exception.rs | 27 +++++++++++++++++++++------ objc_sys/src/lib.rs | 2 -- objc_sys/src/tmp_gnustep.rs | 5 ----- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/objc_sys/src/exception.rs b/objc_sys/src/exception.rs index c6dd85446..3c58eff14 100644 --- a/objc_sys/src/exception.rs +++ b/objc_sys/src/exception.rs @@ -1,45 +1,60 @@ -//! Only available with Apple's objc4. +//! Defined in: +//! Apple: `objc-exception.h` +//! GNUStep: `eh_personality.c`, which is a bit brittle to rely on, but I +//! think it's fine... use core::ffi::c_void; use std::os::raw::c_int; use crate::{objc_class, objc_object}; /// Remember that this is non-null! +#[cfg(apple)] pub type objc_exception_matcher = unsafe extern "C" fn(catch_type: *mut objc_class, exception: *mut objc_object) -> c_int; /// Remember that this is non-null! +#[cfg(apple)] pub type objc_exception_preprocessor = unsafe extern "C" fn(exception: *mut objc_object) -> *mut objc_object; /// Remember that this is non-null! +#[cfg(apple)] pub type objc_uncaught_exception_handler = unsafe extern "C" fn(exception: *mut objc_object); /// Only available on macOS. /// /// Remember that this is non-null! -#[cfg(target_os = "macos")] +#[cfg(all(apple, target_os = "macos"))] pub type objc_exception_handler = unsafe extern "C" fn(unused: *mut objc_object, context: *mut c_void); extern "C" { pub fn objc_begin_catch(exc_buf: *mut c_void) -> *mut objc_object; pub fn objc_end_catch(); - pub fn objc_exception_throw(exception: *mut objc_object); - pub fn objc_exception_rethrow(); + pub fn objc_exception_throw(exception: *mut objc_object) -> !; + #[cfg(apple)] + pub fn objc_exception_rethrow() -> !; + #[cfg(gnustep)] + pub fn objc_exception_rethrow(exc_buf: *mut c_void) -> !; + #[cfg(apple)] pub fn objc_setExceptionMatcher(f: objc_exception_matcher) -> objc_exception_matcher; + #[cfg(apple)] pub fn objc_setExceptionPreprocessor( f: objc_exception_preprocessor, ) -> objc_exception_preprocessor; + #[cfg(apple)] pub fn objc_setUncaughtExceptionHandler( f: objc_uncaught_exception_handler, ) -> objc_uncaught_exception_handler; /// Only available on macOS. - #[cfg(target_os = "macos")] + #[cfg(all(apple, target_os = "macos"))] pub fn objc_addExceptionHandler(f: objc_exception_handler, context: *mut c_void) -> usize; /// Only available on macOS. - #[cfg(target_os = "macos")] + #[cfg(all(apple, target_os = "macos"))] pub fn objc_removeExceptionHandler(token: usize); + + #[cfg(gnustep)] + pub fn objc_set_apple_compatible_objcxx_exceptions(newValue: c_int) -> c_int; } diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index 653ba08af..11c4b4a18 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -24,7 +24,6 @@ use core::marker::{PhantomData, PhantomPinned}; mod class; mod constants; -#[cfg(apple)] mod exception; mod message; mod method; @@ -38,7 +37,6 @@ mod various; pub use class::*; pub use constants::*; -#[cfg(apple)] pub use exception::*; pub use message::*; pub use method::*; diff --git a/objc_sys/src/tmp_gnustep.rs b/objc_sys/src/tmp_gnustep.rs index 5d897a0d7..3971f47c7 100644 --- a/objc_sys/src/tmp_gnustep.rs +++ b/objc_sys/src/tmp_gnustep.rs @@ -63,11 +63,6 @@ extern "C" { extern "C" { pub fn objc_msg_lookup2(receiver: *mut id, selector: SEL) -> IMP; } -extern "C" { - pub fn objc_set_apple_compatible_objcxx_exceptions( - newValue: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} extern "C" { pub fn objc_test_capability(x: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } From 98ae6d39150ee3c745d9a0fa653fd4fa187e2852 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 6 Sep 2021 00:41:12 +0200 Subject: [PATCH 31/36] sys: Add some GNUStep objc_msg_X functions --- objc/src/message/gnustep.rs | 13 +-- objc_sys/src/message.rs | 7 ++ objc_sys/src/tmp_gnustep.rs | 185 ------------------------------------ objc_sys/src/various.rs | 3 + 4 files changed, 14 insertions(+), 194 deletions(-) delete mode 100644 objc_sys/src/tmp_gnustep.rs diff --git a/objc/src/message/gnustep.rs b/objc/src/message/gnustep.rs index e20b31595..5f9fca026 100644 --- a/objc/src/message/gnustep.rs +++ b/objc/src/message/gnustep.rs @@ -1,13 +1,8 @@ use core::mem; -use objc_sys::objc_super; +use objc_sys::{objc_msg_lookup, objc_msg_lookup_super, objc_super}; use super::{Encode, Message, MessageArguments, MessageError}; -use crate::runtime::{Class, Imp, Object, Sel}; - -extern "C" { - fn objc_msg_lookup(receiver: *mut Object, op: Sel) -> Imp; - fn objc_msg_lookup_super(sup: *const objc_super, sel: Sel) -> Imp; -} +use crate::runtime::{Class, Object, Sel}; pub unsafe fn send_unverified(obj: *const T, sel: Sel, args: A) -> Result where @@ -20,7 +15,7 @@ where } let receiver = obj as *mut T as *mut Object; - let msg_send_fn = objc_msg_lookup(receiver, sel); + let msg_send_fn = objc_msg_lookup(receiver as *mut _, sel.as_ptr() as *const _); objc_try!({ A::invoke(msg_send_fn, receiver, sel, args) }) } @@ -40,6 +35,6 @@ where receiver: receiver as *mut _, super_class: superclass as *const Class as *const _, }; - let msg_send_fn = objc_msg_lookup_super(&sup, sel); + let msg_send_fn = objc_msg_lookup_super(&sup, sel.as_ptr() as *const _); objc_try!({ A::invoke(msg_send_fn, receiver, sel, args) }) } diff --git a/objc_sys/src/message.rs b/objc_sys/src/message.rs index 7a690a455..f93429b19 100644 --- a/objc_sys/src/message.rs +++ b/objc_sys/src/message.rs @@ -18,6 +18,13 @@ pub struct objc_super { pub super_class: *const objc_class, } +#[cfg(gnustep)] +extern "C" { + pub fn objc_msg_lookup(receiver: *mut objc_object, sel: *const objc_selector) -> IMP; + pub fn objc_msg_lookup_super(super: *const objc_super, sel: *const objc_selector) -> IMP; + // objc_msg_lookup_sender +} + extern "C" { pub fn objc_msgSend(); #[cfg(apple)] diff --git a/objc_sys/src/tmp_gnustep.rs b/objc_sys/src/tmp_gnustep.rs deleted file mode 100644 index 3971f47c7..000000000 --- a/objc_sys/src/tmp_gnustep.rs +++ /dev/null @@ -1,185 +0,0 @@ -/* automatically generated by rust-bindgen 0.59.1 */ - -pub const OBJC_SMALL_OBJECT_MASK: u32 = 7; -pub const OBJC_SMALL_OBJECT_SHIFT: u32 = 3; -pub const OBJC_CAP_EXCEPTIONS: u32 = 0; -pub const OBJC_CAP_SYNCRONIZE: u32 = 1; -pub const OBJC_CAP_PROPERTIES: u32 = 2; -pub const OBJC_CAP_PROPERTY_INTROSPECTION: u32 = 3; -pub const OBJC_CAP_OPTIONAL_PROTOCOLS: u32 = 4; -pub const OBJC_CAP_NONFRAGILE_IVARS: u32 = 5; -pub const OBJC_CAP_TYPE_DEPENDENT_DISPATCH: u32 = 6; -pub const OBJC_CAP_LOW_MEMORY: u32 = 7; -pub const OBJC_DEVELOPER_MODE: u32 = 8; -pub const OBJC_UNIFIED_EXCEPTION_MODEL: u32 = 9; -pub const OBJC_CAP_REGISTERED_COMPATIBILITY_ALIASES: u32 = 10; -pub const OBJC_CAP_ARC: u32 = 11; -pub const OBJC_CAP_GARBAGE_COLLECTION: u32 = 12; -pub const OBJC_CAP_ASSOCIATED_REFERENCES: u32 = 13; -pub const OBJC_CAP_SMALL_OBJECTS: u32 = 14; -pub const OBJC_CAP_PROTOTYPES: u32 = 15; -pub const OBJC_ARC_AUTORELEASE_DEBUG: u32 = 16; -pub const OBJC_CAP_TRACING: u32 = 17; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_slot2 { - pub method: IMP, -} -extern "C" { - pub static mut objc_method_cache_version: u64; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_slot { - pub owner: Class, - pub cachedFor: Class, - pub types: *const ::std::os::raw::c_char, - pub version: ::std::os::raw::c_int, - pub method: IMP, - pub selector: SEL, -} -extern "C" { - pub fn objc_msg_lookup(arg1: id, arg2: SEL) -> IMP; -} -extern "C" { - pub fn objc_msg_lookup_super(arg1: *mut objc_super, arg2: SEL) -> IMP; -} -extern "C" { - pub fn objc_msg_lookup_sender(receiver: *mut id, selector: SEL, sender: id) -> *mut objc_slot; -} -extern "C" { - pub fn objc_get_slot(arg1: Class, arg2: SEL) -> *mut objc_slot; -} -extern "C" { - pub fn objc_get_slot2(arg1: Class, arg2: SEL, arg3: *mut u64) -> *mut objc_slot2; -} -extern "C" { - pub fn objc_slot_lookup_version( - receiver: *mut id, - selector: SEL, - arg1: *mut u64, - ) -> *mut objc_slot2; -} -extern "C" { - pub fn objc_msg_lookup2(receiver: *mut id, selector: SEL) -> IMP; -} -extern "C" { - pub fn objc_test_capability(x: ::std::os::raw::c_int) -> ::std::os::raw::c_int; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_category { - _unused: [u8; 0], -} -extern "C" { - pub static mut _objc_lookup_class: - ::std::option::Option Class>; -} -extern "C" { - pub static mut _objc_load_callback: - ::std::option::Option; -} -extern "C" { - pub static mut objc_proxy_lookup: - ::std::option::Option id>; -} -extern "C" { - pub static mut __objc_msg_forward3: - ::std::option::Option *mut objc_slot>; -} -extern "C" { - pub static mut __objc_msg_forward2: - ::std::option::Option IMP>; -} -extern "C" { - pub static mut _objc_unexpected_exception: - ::std::option::Option; -} -extern "C" { - pub static mut _objc_class_for_boxing_foreign_exception: - ::std::option::Option Class>; -} -extern "C" { - pub static mut _objc_selector_type_mismatch2: ::std::option::Option< - unsafe extern "C" fn(cls: Class, selector: SEL, result: *mut objc_slot2) -> IMP, - >; -} -extern "C" { - pub static mut _objc_selector_type_mismatch: ::std::option::Option< - unsafe extern "C" fn(cls: Class, selector: SEL, result: *mut objc_slot) -> *mut objc_slot, - >; -} -extern "C" { - pub static mut _objc_weak_load: ::std::option::Option id>; -} -pub type objc_tracing_hook = ::std::option::Option< - unsafe extern "C" fn( - arg1: id, - arg2: SEL, - arg3: IMP, - arg4: ::std::os::raw::c_int, - arg5: *mut ::std::os::raw::c_void, - ) -> IMP, ->; -extern "C" { - pub fn objc_registerTracingHook(arg1: SEL, arg2: objc_tracing_hook) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn objc_skip_type_qualifiers( - type_: *const ::std::os::raw::c_char, - ) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn objc_skip_typespec( - type_: *const ::std::os::raw::c_char, - ) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn objc_skip_argspec(type_: *const ::std::os::raw::c_char) - -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn objc_sizeof_type(type_: *const ::std::os::raw::c_char) -> usize; -} -extern "C" { - pub fn objc_alignof_type(type_: *const ::std::os::raw::c_char) -> usize; -} -extern "C" { - pub fn objc_aligned_size(type_: *const ::std::os::raw::c_char) -> usize; -} -extern "C" { - pub fn objc_promoted_size(type_: *const ::std::os::raw::c_char) -> usize; -} -extern "C" { - pub fn method_get_number_of_arguments(method: *mut objc_method) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn objc_get_type_qualifiers(type_: *const ::std::os::raw::c_char) - -> ::std::os::raw::c_uint; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct objc_struct_layout { - pub original_type: *const ::std::os::raw::c_char, - pub type_: *const ::std::os::raw::c_char, - pub prev_type: *const ::std::os::raw::c_char, - pub record_size: ::std::os::raw::c_uint, - pub record_align: ::std::os::raw::c_uint, -} -extern "C" { - pub fn objc_layout_structure( - type_: *const ::std::os::raw::c_char, - layout: *mut objc_struct_layout, - ); -} -extern "C" { - pub fn objc_layout_structure_next_member(layout: *mut objc_struct_layout) -> BOOL; -} -extern "C" { - pub fn objc_layout_structure_get_info( - layout: *mut objc_struct_layout, - offset: *mut ::std::os::raw::c_uint, - align: *mut ::std::os::raw::c_uint, - type_: *mut *const ::std::os::raw::c_char, - ); -} diff --git a/objc_sys/src/various.rs b/objc_sys/src/various.rs index 0c78da6bd..dfc882c80 100644 --- a/objc_sys/src/various.rs +++ b/objc_sys/src/various.rs @@ -91,4 +91,7 @@ extern "C" { // #[deprecated = "not recommended"] // #[cfg(apple)] // pub fn _objc_flush_caches + + // #[cfg(gnustep)] + // objc_test_capability } From a275174797631452c6bf465b1ca15d6f4e399ef5 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 6 Sep 2021 00:52:45 +0200 Subject: [PATCH 32/36] Make objc_sys::IMP nullable Probably all of the underlying APIs can handle NULL values, so not having this possibility is restricting. And most of them can sometimes _return_ a NULL value, so not handling that is unsound! --- objc/src/declare.rs | 16 ++++++++++++---- objc/src/message/gnustep.rs | 4 ++-- objc/src/runtime.rs | 4 ++-- objc_sys/src/class.rs | 2 +- objc_sys/src/various.rs | 6 +++--- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/objc/src/declare.rs b/objc/src/declare.rs index 0cfbe0c8e..072cc4345 100644 --- a/objc/src/declare.rs +++ b/objc/src/declare.rs @@ -182,8 +182,12 @@ impl ClassDecl { ); let types = method_type_encoding(&F::Ret::ENCODING, encs); - let success = - runtime::class_addMethod(self.cls as _, sel.as_ptr() as _, func.imp(), types.as_ptr()); + let success = runtime::class_addMethod( + self.cls as _, + sel.as_ptr() as _, + Some(func.imp()), + types.as_ptr(), + ); assert!(success != NO, "Failed to add method {:?}", sel); } @@ -213,8 +217,12 @@ impl ClassDecl { let types = method_type_encoding(&F::Ret::ENCODING, encs); let metaclass = (*self.cls).metaclass() as *const _ as *mut _; - let success = - runtime::class_addMethod(metaclass, sel.as_ptr() as _, func.imp(), types.as_ptr()); + let success = runtime::class_addMethod( + metaclass, + sel.as_ptr() as _, + Some(func.imp()), + types.as_ptr(), + ); assert!(success != NO, "Failed to add class method {:?}", sel); } diff --git a/objc/src/message/gnustep.rs b/objc/src/message/gnustep.rs index 5f9fca026..2d0474184 100644 --- a/objc/src/message/gnustep.rs +++ b/objc/src/message/gnustep.rs @@ -16,7 +16,7 @@ where 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, receiver, sel, args) }) + objc_try!({ A::invoke(msg_send_fn.expect("Null IMP"), receiver, sel, args) }) } pub unsafe fn send_super_unverified( @@ -36,5 +36,5 @@ where 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, receiver, sel, args) }) + objc_try!({ A::invoke(msg_send_fn.expect("Null IMP"), receiver, sel, args) }) } diff --git a/objc/src/runtime.rs b/objc/src/runtime.rs index 1c0d43686..bb3367197 100644 --- a/objc/src/runtime.rs +++ b/objc/src/runtime.rs @@ -60,7 +60,7 @@ pub struct Protocol(objc_sys::Protocol); pub struct Object(objc_sys::objc_object); /// A pointer to the start of a method implementation. -pub type Imp = objc_sys::IMP; +pub type Imp = unsafe extern "C" fn(); impl Sel { /// Registers a method with the Objective-C runtime system, @@ -189,7 +189,7 @@ impl Method { /// Returns the implementation of self. pub fn implementation(&self) -> Imp { - unsafe { method_getImplementation(self.as_ptr()) } + unsafe { method_getImplementation(self.as_ptr()).expect("Null IMP") } } } diff --git a/objc_sys/src/class.rs b/objc_sys/src/class.rs index bc5c43db6..3c8dfe84a 100644 --- a/objc_sys/src/class.rs +++ b/objc_sys/src/class.rs @@ -113,7 +113,7 @@ extern "C" { name: *const objc_selector, imp: IMP, types: *const c_char, - ) -> Option; + ) -> IMP; pub fn class_replaceProperty( cls: *mut objc_class, name: *const c_char, diff --git a/objc_sys/src/various.rs b/objc_sys/src/various.rs index dfc882c80..6d0cb1fe4 100644 --- a/objc_sys/src/various.rs +++ b/objc_sys/src/various.rs @@ -10,10 +10,10 @@ pub struct objc_ivar { _p: OpaqueData, } -/// A pointer to the start of a method implementation. +/// A nullable pointer to the start of a method implementation. /// -/// This must be non-null. Use `Option` when nullability is desired. -pub type IMP = unsafe extern "C" fn(); +/// Not all APIs are guaranteed to take NULL values; read the docs! +pub type IMP = Option; /// Not available on macOS x86. /// From 216b1b47cd84ef429a6c691dc8763192ae53b363 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 6 Sep 2021 01:06:37 +0200 Subject: [PATCH 33/36] sys: Fix GNUStep imports --- objc/src/runtime.rs | 1 + objc_sys/src/constants.rs | 3 ++- objc_sys/src/exception.rs | 5 ++++- objc_sys/src/message.rs | 6 ++++-- objc_sys/src/various.rs | 8 ++++++-- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/objc/src/runtime.rs b/objc/src/runtime.rs index bb3367197..36509a217 100644 --- a/objc/src/runtime.rs +++ b/objc/src/runtime.rs @@ -14,6 +14,7 @@ use std::os::raw::c_uint; use crate::Encode; use objc_sys; +#[cfg(target_vendor = "apple")] #[allow(deprecated)] pub use objc_sys::object_dispose; pub use objc_sys::{ diff --git a/objc_sys/src/constants.rs b/objc_sys/src/constants.rs index fad034c11..bf2e713c3 100644 --- a/objc_sys/src/constants.rs +++ b/objc_sys/src/constants.rs @@ -1,8 +1,9 @@ //! Various common #defines and enum constants. +#[cfg(apple)] use std::os::raw::c_int; -use super::{id, Class, BOOL}; +use crate::{id, Class, BOOL}; /// The equivalent of true for Objective-C's [`BOOL`][`super::BOOL`] type. #[cfg(not(target_arch = "aarch64"))] diff --git a/objc_sys/src/exception.rs b/objc_sys/src/exception.rs index 3c58eff14..49f9b7379 100644 --- a/objc_sys/src/exception.rs +++ b/objc_sys/src/exception.rs @@ -3,9 +3,12 @@ //! GNUStep: `eh_personality.c`, which is a bit brittle to rely on, but I //! think it's fine... use core::ffi::c_void; +#[cfg(any(apple, gnustep))] use std::os::raw::c_int; -use crate::{objc_class, objc_object}; +#[cfg(apple)] +use crate::objc_class; +use crate::objc_object; /// Remember that this is non-null! #[cfg(apple)] diff --git a/objc_sys/src/message.rs b/objc_sys/src/message.rs index f93429b19..8f1b1ef0a 100644 --- a/objc_sys/src/message.rs +++ b/objc_sys/src/message.rs @@ -3,7 +3,9 @@ //! Most of these are `cfg`-gated, these configs are semver-stable. //! //! TODO: Some of these are only supported on _some_ GNUStep targets! -use super::{objc_class, objc_object}; +use crate::{objc_class, objc_object}; +#[cfg(gnustep)] +use crate::{objc_selector, IMP}; /// Specifies data used when sending messages to superclasses. #[repr(C)] @@ -21,7 +23,7 @@ pub struct objc_super { #[cfg(gnustep)] extern "C" { pub fn objc_msg_lookup(receiver: *mut objc_object, sel: *const objc_selector) -> IMP; - pub fn objc_msg_lookup_super(super: *const objc_super, sel: *const objc_selector) -> IMP; + pub fn objc_msg_lookup_super(sup: *const objc_super, sel: *const objc_selector) -> IMP; // objc_msg_lookup_sender } diff --git a/objc_sys/src/various.rs b/objc_sys/src/various.rs index 6d0cb1fe4..460a1974a 100644 --- a/objc_sys/src/various.rs +++ b/objc_sys/src/various.rs @@ -1,7 +1,11 @@ use core::ffi::c_void; -use std::os::raw::{c_char, c_int, c_uint}; +use std::os::raw::c_char; +#[cfg(apple)] +use std::os::raw::{c_int, c_uint}; -use crate::{objc_AssociationPolicy, objc_class, objc_object, OpaqueData, BOOL}; +#[cfg(apple)] +use crate::objc_class; +use crate::{objc_AssociationPolicy, objc_object, OpaqueData, BOOL}; /// A type that represents an instance variable. #[repr(C)] From 991b50f4f992afa03caa682d742ca8df180d3f46 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 6 Sep 2021 09:38:59 +0200 Subject: [PATCH 34/36] sys: Fix a few mistakes --- objc/src/runtime.rs | 1 - objc_sys/src/object.rs | 1 - objc_sys/src/various.rs | 12 +++++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/objc/src/runtime.rs b/objc/src/runtime.rs index 36509a217..bb3367197 100644 --- a/objc/src/runtime.rs +++ b/objc/src/runtime.rs @@ -14,7 +14,6 @@ use std::os::raw::c_uint; use crate::Encode; use objc_sys; -#[cfg(target_vendor = "apple")] #[allow(deprecated)] pub use objc_sys::object_dispose; pub use objc_sys::{ diff --git a/objc_sys/src/object.rs b/objc_sys/src/object.rs index c9976869c..c44361b24 100644 --- a/objc_sys/src/object.rs +++ b/objc_sys/src/object.rs @@ -25,7 +25,6 @@ extern "C" { #[cfg(apple)] pub fn object_copy(obj: *const objc_object, size: usize) -> *mut objc_object; #[deprecated = "Not needed since ARC"] - #[cfg(apple)] pub fn object_dispose(obj: *mut objc_object) -> *mut objc_object; #[deprecated = "Not needed since ARC"] pub fn object_setInstanceVariable( diff --git a/objc_sys/src/various.rs b/objc_sys/src/various.rs index 460a1974a..6da437a50 100644 --- a/objc_sys/src/various.rs +++ b/objc_sys/src/various.rs @@ -1,7 +1,7 @@ use core::ffi::c_void; -use std::os::raw::c_char; #[cfg(apple)] -use std::os::raw::{c_int, c_uint}; +use std::os::raw::c_uint; +use std::os::raw::{c_char, c_int}; #[cfg(apple)] use crate::objc_class; @@ -49,11 +49,12 @@ extern "C" { #[cfg(apple)] pub fn objc_copyImageNames(out_len: *mut c_uint) -> *mut *const c_char; + // Instead of being able to change this, it's a weak symbol on GNUStep. #[cfg(apple)] pub fn objc_enumerationMutation(obj: *mut objc_object); #[cfg(apple)] pub fn objc_setEnumerationMutationHandler( - handler: Option, + handler: Option, ); pub fn objc_getAssociatedObject( @@ -70,9 +71,10 @@ extern "C" { #[cfg(apple)] pub fn objc_setForwardHandler(fwd: *mut c_void, fwd_stret: *mut c_void); - #[cfg(apple)] + // These two are defined in: + // - Apple: objc-sync.h + // - GNUStep: dtable.h / associate.m pub fn objc_sync_enter(obj: *mut objc_object) -> c_int; - #[cfg(apple)] pub fn objc_sync_exit(obj: *mut objc_object) -> c_int; /// Not available on macOS x86. From e63fc13aeb42c15f1f9933d30bb99b007379947a Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Tue, 7 Sep 2021 11:56:06 +0200 Subject: [PATCH 35/36] sys: Add a few comments mentioning private functions in objc-abi.h It's unclear how much these are part of the ABI stability, and whether they're actually useful --- objc_sys/src/message.rs | 16 ++++++++++++++++ objc_sys/src/object.rs | 25 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/objc_sys/src/message.rs b/objc_sys/src/message.rs index 8f1b1ef0a..1695e07b7 100644 --- a/objc_sys/src/message.rs +++ b/objc_sys/src/message.rs @@ -25,12 +25,21 @@ extern "C" { pub fn objc_msg_lookup(receiver: *mut objc_object, sel: *const objc_selector) -> IMP; pub fn objc_msg_lookup_super(sup: *const objc_super, sel: *const objc_selector) -> IMP; // objc_msg_lookup_sender + + // objc_msgLookup family available in macOS >= 10.12 } extern "C" { + // objc_msgSend_noarg + pub fn objc_msgSend(); + // objc_msgSend_debug + #[cfg(apple)] pub fn objc_msgSendSuper(); + // objc_msgSendSuper2 + // objc_msgSendSuper2_debug + #[cfg(apple)] pub fn method_invoke(); #[cfg(apple)] @@ -42,9 +51,14 @@ extern "C" { extern "C" { /// Not available on `target_arch = "aarch64"` pub fn objc_msgSend_stret(); + // objc_msgSend_stret_debug + /// Not available on `target_arch = "aarch64"` #[cfg(apple)] pub fn objc_msgSendSuper_stret(); + // objc_msgSendSuper2_stret + // objc_msgSendSuper2_stret_debug + /// Not available on `target_arch = "aarch64"` #[cfg(apple)] pub fn method_invoke_stret(); @@ -59,6 +73,7 @@ extern "C" { extern "C" { /// Only available on `target_arch = "x86_64"` or `target_arch = "x86"` pub fn objc_msgSend_fpret(); + // objc_msgSend_fpret_debug } #[cfg(target_arch = "x86_64")] // __x86_64__ @@ -66,4 +81,5 @@ extern "C" { /// Only available on `target_arch = "x86_64"` #[cfg(apple)] pub fn objc_msgSend_fp2ret(); + // objc_msgSend_fp2ret_debug } diff --git a/objc_sys/src/object.rs b/objc_sys/src/object.rs index c44361b24..118005e73 100644 --- a/objc_sys/src/object.rs +++ b/objc_sys/src/object.rs @@ -55,6 +55,31 @@ extern "C" { #[cfg(apple)] pub fn objc_destructInstance(obj: *mut objc_object) -> *mut c_void; + // TODO: Unsure if we should expose these; are they useful, and stable? + // Defined in objc-abi.h + // pub fn objc_getProperty( + // obj: *const objc_object, + // sel: *const objc_selector, + // offset: isize, + // atomic: BOOL, + // ) -> *mut c_void; + // pub fn objc_setProperty( + // obj: *const objc_object, + // sel: *const objc_selector, + // offset: isize, + // newValue: *const c_void, + // atomic: BOOL, + // shouldCopy: i8, + // ); + // This is generated in setters to struct properties. + // pub fn objc_copyStruct( + // dest: *mut c_void, + // src: *const c_void, + // size: isize, + // atomic: BOOL, + // hasStrong: BOOL, + // ); + // #[deprecated = "use object_copy instead"] // #[cfg(all(apple, target_os = "macos"))] // object_copyFromZone From a97a2ea2352d12fe43523ad8ad17c5754bd50948 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Tue, 7 Sep 2021 14:47:15 +0200 Subject: [PATCH 36/36] sys: Add README --- objc_sys/Cargo.toml | 5 +- objc_sys/README.md | 100 +++++++++++++++++++++++++++ objc_sys/helper-scripts/gen-git.fish | 2 +- objc_sys/src/constants.rs | 6 +- objc_sys/src/lib.rs | 26 ++++--- objc_sys/src/message.rs | 2 +- objc_sys/src/method.rs | 3 + objc_sys/src/object.rs | 2 +- objc_sys/src/property.rs | 6 ++ objc_sys/src/selector.rs | 4 +- objc_sys/src/types.rs | 26 ++++--- objc_sys/src/various.rs | 2 +- 12 files changed, 157 insertions(+), 27 deletions(-) create mode 100644 objc_sys/README.md diff --git a/objc_sys/Cargo.toml b/objc_sys/Cargo.toml index f79473ae4..8da275f82 100644 --- a/objc_sys/Cargo.toml +++ b/objc_sys/Cargo.toml @@ -4,10 +4,11 @@ version = "0.0.0" # Remember to update html_root_url in lib.rs authors = ["Mads Marquart "] edition = "2018" -description = "Bindings to the Objective-C core runtime" +description = "Raw bindings to Objective-C runtimes" keywords = ["objective-c", "macos", "ios", "objc_msgSend", "sys"] categories = [ "external-ffi-bindings", + # "no_std" # TODO "os::macos-apis", ] repository = "https://github.com/madsmtm/objc" @@ -20,6 +21,8 @@ exclude = [ "helper-scripts/*", ] +readme = "README.md" + # Downstream users can customize the linking to libobjc! # See https://doc.rust-lang.org/cargo/reference/build-scripts.html#overriding-build-scripts links = "objc" diff --git a/objc_sys/README.md b/objc_sys/README.md new file mode 100644 index 000000000..064b4507f --- /dev/null +++ b/objc_sys/README.md @@ -0,0 +1,100 @@ +# `objc_sys` + +[![Latest version](https://badgen.net/crates/v/objc_sys)](https://crates.io/crates/objc_sys) +[![License](https://badgen.net/badge/license/MIT/blue)](../LICENSE.txt) +[![Documentation](https://docs.rs/objc_sys/badge.svg)](https://docs.rs/objc_sys/) +[![CI Status](https://github.com/madsmtm/objc/workflows/CI/badge.svg)](https://github.com/madsmtm/objc/actions) + +Raw Rust bindings to core Objective-C runtimes and ABIs. + +## Runtime Support + +`objc_sys` currently supports two runtimes (support for [`ObjFW`] and +[`WinObjC`] may be added): +- Apple's [`objc4`] on `cfg(target_vendor = "apple")` targets. +- GNUStep's [`libobjc2`] on all other targets. See their [Objective-C Compiler + and Runtime FAQ][gnustep-faq]. + +This library will probably only ever support ["Modern"][modern] Objective-C +runtimes, since support for reference-counting primitives like `objc_retain` +and `objc_autoreleasePoolPop` is a vital requirement for most applications. + +Just so we're being clear, this rules out the GCC [`libobjc`][gcc-libobjc] +runtime (see [this][gcc-objc-support]), and the [`mulle-objc`] runtime. + +[`ObjFW`]: https://github.com/ObjFW/ObjFW +[`WinObjC`]: https://github.com/microsoft/WinObjC +[`objc4`]: https://opensource.apple.com/source/objc4/ +[`libobjc2`]: https://github.com/gnustep/libobjc2 +[gnustep-faq]: http://wiki.gnustep.org/index.php/Objective-C_Compiler_and_Runtime_FAQ +[modern]: https://en.wikipedia.org/wiki/Objective-C#Modern_Objective-C +[gcc-libobjc]: https://github.com/gcc-mirror/gcc/tree/master/libobjc +[gcc-objc-support]: https://gcc.gnu.org/onlinedocs/gcc/Standards.html#Objective-C-and-Objective-C_002b_002b-Languages +[`mulle-objc`]: https://github.com/mulle-objc/mulle-objc-runtime + + +## Required Versions + +At least `libobjc2` [version 1.7][libobjc2-1.7] or `objc4` +[version 493.9][objc4-493.9] is required. + +`objc4` version 493.9 is available with: +- **macOS 10.7** +- **iOS 5.0** +- **tvOS 9.0** +- **watchOS 1.0** +- **bridgeOS 2.0** + +So those are the **minimum supported Apple versions**. Functionality that was +added after these versions are not (yet?) available in `objc_sys`. + +[libobjc2-1.7]: https://github.com/gnustep/libobjc2/tree/1.7 +[objc4-493.9]: https://opensource.apple.com/source/objc4/ + + +## Configuring linking + +This crate defines the `links` key in `Cargo.toml` so it's possible to +change the linking to `libobjc`, see [the relevant cargo docs][overriding]. + +In the future, this crate may vendor the required source code to automatically +build and link to the runtimes. Choosing static vs. dynamic linking here may +also become an option. + +[overriding]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#overriding-build-scripts + + +## Objective-C compiler ABI configuration + +Objective-C compilers like `clang` and `gcc` requires configuring the calling +ABI to the runtime you're using: +- `clang` uses the [`-fobjc-runtime`] flag, of which there are a few different + [options][clang-objc-kinds]. +- `gcc` uses the [`-fgnu-runtime` or `-fnext-runtime`][gcc-flags] options. + Note that Modern Objective-C features are ill supported. + +This is relevant if you're building and linking to custom Objective-C sources +in a build script. In the future, this crate may expose build script metadata +to help with selecting these (and other required) flags. + +[`-fobjc-runtime`]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fobjc-runtime +[clang-objc-kinds]: https://clang.llvm.org/doxygen/classclang_1_1ObjCRuntime.html#af19fe070a7073df4ecc666b44137c4e5 +[gcc-flags]: https://gcc.gnu.org/onlinedocs/gcc/Objective-C-and-Objective-C_002b_002b-Dialect-Options.html + + +## Design choices + +It is recognized that the most primary consumer of this library will be macOS +and secondly iOS applications. Therefore it was chosen not to use `bindgen` in +our build script to not add compilation cost to those targets.1 + +Deprecated functions are also not included for future compability, since they +could be removed in any macOS release, and then our code would break. If you +have a need for these, please open an issue and we can discuss it! + +Some items (in particular the `objc_msgSend_X` family) have `cfg`s that prevent +their usage on different platforms; these are **semver-stable** in the sense +that they will only get less restrictive, never more. + +1 That said, most of this is created with the help of `bindgen`'s +commandline interface, so huge thanks to them! diff --git a/objc_sys/helper-scripts/gen-git.fish b/objc_sys/helper-scripts/gen-git.fish index 1f64b28f1..2a6eca1de 100755 --- a/objc_sys/helper-scripts/gen-git.fish +++ b/objc_sys/helper-scripts/gen-git.fish @@ -2,7 +2,7 @@ # Yup, this is terrible, but was a great help in creating the correct implementations -# Source repo should be a path to https://github.com/madsmtm/objc4.git +# Source repo should be a path to https://github.com/madsmtm/objc4-mirror.git set source_repo $argv[1] set to_repo $argv[2] diff --git a/objc_sys/src/constants.rs b/objc_sys/src/constants.rs index bf2e713c3..3cfed1220 100644 --- a/objc_sys/src/constants.rs +++ b/objc_sys/src/constants.rs @@ -5,16 +5,18 @@ use std::os::raw::c_int; use crate::{id, Class, BOOL}; -/// The equivalent of true for Objective-C's [`BOOL`][`super::BOOL`] type. #[cfg(not(target_arch = "aarch64"))] +/// The equivalent of `true` for Objective-C's [`BOOL`][`super::BOOL`] type. pub const YES: BOOL = 1; #[cfg(target_arch = "aarch64")] +/// The equivalent of `true` for Objective-C's [`BOOL`][`super::BOOL`] type. pub const YES: BOOL = true; -/// The equivalent of false for Objective-C's [`BOOL`][`super::BOOL`] type. #[cfg(not(target_arch = "aarch64"))] +/// The equivalent of `false` for Objective-C's [`BOOL`][`super::BOOL`] type. pub const NO: BOOL = 0; #[cfg(target_arch = "aarch64")] +/// The equivalent of `false` for Objective-C's [`BOOL`][`super::BOOL`] type. pub const NO: BOOL = false; /// A quick alias for a [`null_mut`][`core::ptr::null_mut`] object / instance. diff --git a/objc_sys/src/lib.rs b/objc_sys/src/lib.rs index 11c4b4a18..406496e3b 100644 --- a/objc_sys/src/lib.rs +++ b/objc_sys/src/lib.rs @@ -1,22 +1,28 @@ -//! # Bindings to the objc_objective-C core runtime +//! # Raw bindings to Objective-C runtimes //! -//! # Notable differences +//! These bindings contain almost no documentation, so it is highly +//! recommended to read the documentation of the original libraries: +//! - Apple's [official documentation][apple]. +//! - Apple's `objc4` [source code][objc4] ([`git` mirror][objc4-mirror]), in +//! particular `runtime.h`. +//! - GNUStep's `libobjc2` [source code][libobjc2], in particular `runtime.h`. //! -//! Protocol / objc_protocol is no longer a type alias of objc_object, for -//! better type safety. Their internal representation is the same, so the -//! functionality is just a cast away. -//! -//! Deprecated functions are not included for future compability, since they -//! could be removed at any macOS release, and then our code would break. - -// TODO: Replace `extern "C"` with `extern "C-unwind"`. +//! [apple]: https://developer.apple.com/documentation/objectivec/objective-c_runtime?language=objc +//! [libobjc2]: https://github.com/gnustep/libobjc2/tree/v2.1/objc +//! [objc4]: https://opensource.apple.com/source/objc4/objc4-818.2/runtime/ +//! [objc4-mirror]: https://github.com/madsmtm/objc4-mirror.git #![no_std] #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] #![doc(html_root_url = "https://docs.rs/objc_sys/0.0.0")] +// TODO: Replace `extern "C"` with `extern "C-unwind"` where applicable. +// See https://rust-lang.github.io/rfcs/2945-c-unwind-abi.html. + // TODO: Remove this and add "no-std" category to Cargo.toml +// Requires a better solution for C-types in `no_std` crates. +// See https://github.com/japaric/cty/issues/14. extern crate std; use core::cell::UnsafeCell; diff --git a/objc_sys/src/message.rs b/objc_sys/src/message.rs index 1695e07b7..e21b5f53d 100644 --- a/objc_sys/src/message.rs +++ b/objc_sys/src/message.rs @@ -16,7 +16,7 @@ pub struct objc_super { pub receiver: *mut objc_object, /// The particular superclass of the instance to message. /// - /// Named `class` in GNUStep and in older Objective-C versions. + /// Named `class` in older Objective-C versions. pub super_class: *const objc_class, } diff --git a/objc_sys/src/method.rs b/objc_sys/src/method.rs index 055f4f597..af1612506 100644 --- a/objc_sys/src/method.rs +++ b/objc_sys/src/method.rs @@ -9,10 +9,13 @@ pub struct objc_method { _p: OpaqueData, } +/// Describes an Objective-C method. #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct objc_method_description { + /// The name of the method. pub name: *const objc_selector, + /// The types of the method arguments. pub types: *const c_char, } diff --git a/objc_sys/src/object.rs b/objc_sys/src/object.rs index 118005e73..491e90538 100644 --- a/objc_sys/src/object.rs +++ b/objc_sys/src/object.rs @@ -3,7 +3,7 @@ use std::os::raw::c_char; use crate::{objc_class, objc_ivar, OpaqueData}; -/// An opaque type that represents an instance of a class. +/// An opaque type that represents an object / an instance of a class. #[repr(C)] pub struct objc_object { // `isa` field is deprecated, so we don't expose it here. diff --git a/objc_sys/src/property.rs b/objc_sys/src/property.rs index 3be35d048..950e2e479 100644 --- a/objc_sys/src/property.rs +++ b/objc_sys/src/property.rs @@ -2,16 +2,22 @@ use std::os::raw::{c_char, c_uint}; use crate::OpaqueData; +/// An opaque type that describes a property in a class. #[repr(C)] pub struct objc_property { _priv: [u8; 0], _p: OpaqueData, } +/// Describes an Objective-C property attribute. #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct objc_property_attribute_t { + /// The name of the attribute. pub name: *const c_char, + /// The value of the attribute + /// + /// Usually NULL. pub value: *const c_char, } diff --git a/objc_sys/src/selector.rs b/objc_sys/src/selector.rs index 92b3318f2..3338eea51 100644 --- a/objc_sys/src/selector.rs +++ b/objc_sys/src/selector.rs @@ -2,7 +2,9 @@ use std::os::raw::c_char; use crate::{OpaqueData, BOOL}; -/// A type that represents a method selector. +/// An opaque type that represents a method selector. +/// +/// Selectors are immutable. #[repr(C)] pub struct objc_selector { _priv: [u8; 0], diff --git a/objc_sys/src/types.rs b/objc_sys/src/types.rs index f98e151c1..4047cd60c 100644 --- a/objc_sys/src/types.rs +++ b/objc_sys/src/types.rs @@ -4,18 +4,22 @@ use crate::{ objc_class, objc_ivar, objc_method, objc_object, objc_property, objc_protocol, objc_selector, }; -/// The Objective-C `BOOL` type. -/// -/// To convert an Objective-C `BOOL` into a Rust [`bool`], compare it with -/// [`NO`][`super::NO`]. #[cfg(all(apple, not(target_arch = "aarch64")))] -pub type BOOL = i8; -/// TODO: Only if STRICT_APPLE_COMPATIBILITY is NOT defined. -/// TODO: (__vxworks || _WIN32) becomes BOOL = c_int. +type BOOL_INNER = i8; + #[cfg(all(gnustep, not(target_arch = "aarch64")))] -pub type BOOL = u8; +// TODO: Only if STRICT_APPLE_COMPATIBILITY is NOT defined. +// TODO: (__vxworks || _WIN32) becomes BOOL = c_int. +type BOOL_INNER = u8; + #[cfg(target_arch = "aarch64")] -pub type BOOL = bool; +type BOOL_INNER = bool; + +/// The Objective-C `BOOL` type. +/// +/// The type of this varies across platforms, so to convert an it into a Rust +/// [`bool`], always compare it with [`YES`][`crate::YES`] or [`NO`][`crate::NO`]. +pub type BOOL = BOOL_INNER; /// An immutable pointer to a selector. /// @@ -44,6 +48,10 @@ pub type Method = *mut objc_method; /// An opaque type that represents a protocol. /// +/// This is not just a type alias of [`objc_object`], but of [`objc_protocol`] +/// instead, for better type safety. Their internal representation is the same, +/// so the functionality is just a cast away. +/// /// Type alias provided for convenience. pub type Protocol = objc_protocol; diff --git a/objc_sys/src/various.rs b/objc_sys/src/various.rs index 6da437a50..0ad6ecb40 100644 --- a/objc_sys/src/various.rs +++ b/objc_sys/src/various.rs @@ -7,7 +7,7 @@ use std::os::raw::{c_char, c_int}; use crate::objc_class; use crate::{objc_AssociationPolicy, objc_object, OpaqueData, BOOL}; -/// A type that represents an instance variable. +/// An opaque type that represents an instance variable. #[repr(C)] pub struct objc_ivar { _priv: [u8; 0],