@@ -201,9 +201,9 @@ mod imp {
201201
202202    // As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs 
203203    // and use underscores in their names - they're most probably 
204-     // are considered private and therefore should be avoided 
205-     // Here is another way to get arguments using Objective  C 
206-     // runtime 
204+     // are considered private and therefore should be avoided.  
205+     // Here is another way to get arguments using the Objective- C 
206+     // runtime.  
207207    // 
208208    // In general it looks like: 
209209    // res = Vec::new() 
@@ -213,53 +213,60 @@ mod imp {
213213    // res 
214214    #[ cfg( any( target_os = "ios" ,  target_os = "tvos" ,  target_os = "watchos" ) ) ]  
215215    pub  fn  args ( )  -> Args  { 
216-         use  crate :: ffi:: OsString ; 
216+         use  crate :: ffi:: { c_char ,  c_void ,   OsString } ; 
217217        use  crate :: mem; 
218218        use  crate :: str; 
219219
220-         extern  "C"  { 
221-             fn  sel_registerName ( name :  * const  libc:: c_uchar )  -> Sel ; 
222-             fn  objc_getClass ( class_name :  * const  libc:: c_uchar )  -> NsId ; 
223-         } 
220+         type  Sel  = * const  c_void ; 
221+         type  NsId  = * const  c_void ; 
222+         type  NSUInteger  = usize ; 
224223
225-         #[ cfg( target_arch = "aarch64" ) ]  
226224        extern  "C"  { 
227-             fn  objc_msgSend ( obj :  NsId ,  sel :  Sel )  -> NsId ; 
228-             #[ allow( clashing_extern_declarations) ]  
229-             #[ link_name = "objc_msgSend" ]  
230-             fn  objc_msgSend_ul ( obj :  NsId ,  sel :  Sel ,  i :  libc:: c_ulong )  -> NsId ; 
231-         } 
225+             fn  sel_registerName ( name :  * const  c_char )  -> Sel ; 
226+             fn  objc_getClass ( class_name :  * const  c_char )  -> NsId ; 
232227
233-         #[ cfg( not( target_arch = "aarch64" ) ) ]  
234-         extern  "C"  { 
235-             fn  objc_msgSend ( obj :  NsId ,  sel :  Sel ,  ...)  -> NsId ; 
236-             #[ allow( clashing_extern_declarations) ]  
237-             #[ link_name = "objc_msgSend" ]  
238-             fn  objc_msgSend_ul ( obj :  NsId ,  sel :  Sel ,  ...)  -> NsId ; 
228+             // This must be transmuted to an appropriate function pointer type before being called. 
229+             fn  objc_msgSend ( ) ; 
239230        } 
240231
241-         type  Sel  = * const  libc:: c_void ; 
242-         type  NsId  = * const  libc:: c_void ; 
232+         const  MSG_SEND_PTR :  unsafe  extern  "C"  fn ( )  = objc_msgSend; 
233+         const  MSG_SEND_NO_ARGUMENTS_RETURN_PTR :  unsafe  extern  "C"  fn ( NsId ,  Sel )  -> * const  c_void  =
234+             unsafe  {  mem:: transmute ( MSG_SEND_PTR )  } ; 
235+         const  MSG_SEND_NO_ARGUMENTS_RETURN_NSUINTEGER :  unsafe  extern  "C"  fn ( 
236+             NsId , 
237+             Sel , 
238+         )  -> NSUInteger  = unsafe  {  mem:: transmute ( MSG_SEND_PTR )  } ; 
239+         const  MSG_SEND_NSINTEGER_ARGUMENT_RETURN_PTR :  unsafe  extern  "C"  fn ( 
240+             NsId , 
241+             Sel , 
242+             NSUInteger , 
243+         ) 
244+             -> * const  c_void  = unsafe  {  mem:: transmute ( MSG_SEND_PTR )  } ; 
243245
244246        let  mut  res = Vec :: new ( ) ; 
245247
246248        unsafe  { 
247-             let  process_info_sel =
248-                 sel_registerName ( c"processInfo" . as_ptr ( )  as  * const  libc:: c_uchar ) ; 
249-             let  arguments_sel = sel_registerName ( c"arguments" . as_ptr ( )  as  * const  libc:: c_uchar ) ; 
250-             let  utf8_sel = sel_registerName ( c"UTF8String" . as_ptr ( )  as  * const  libc:: c_uchar ) ; 
251-             let  count_sel = sel_registerName ( c"count" . as_ptr ( )  as  * const  libc:: c_uchar ) ; 
252-             let  object_at_sel =
253-                 sel_registerName ( c"objectAtIndex:" . as_ptr ( )  as  * const  libc:: c_uchar ) ; 
254- 
255-             let  klass = objc_getClass ( c"NSProcessInfo" . as_ptr ( )  as  * const  libc:: c_uchar ) ; 
256-             let  info = objc_msgSend ( klass,  process_info_sel) ; 
257-             let  args = objc_msgSend ( info,  arguments_sel) ; 
258- 
259-             let  cnt:  usize  = mem:: transmute ( objc_msgSend ( args,  count_sel) ) ; 
249+             let  process_info_sel = sel_registerName ( c"processInfo" . as_ptr ( ) ) ; 
250+             let  arguments_sel = sel_registerName ( c"arguments" . as_ptr ( ) ) ; 
251+             let  count_sel = sel_registerName ( c"count" . as_ptr ( ) ) ; 
252+             let  object_at_index_sel = sel_registerName ( c"objectAtIndex:" . as_ptr ( ) ) ; 
253+             let  utf8string_sel = sel_registerName ( c"UTF8String" . as_ptr ( ) ) ; 
254+ 
255+             let  klass = objc_getClass ( c"NSProcessInfo" . as_ptr ( ) ) ; 
256+             // `+[NSProcessInfo processInfo]` returns an object with +0 retain count, so no need to manually `retain/release`. 
257+             let  info = MSG_SEND_NO_ARGUMENTS_RETURN_PTR ( klass,  process_info_sel) ; 
258+ 
259+             // `-[NSProcessInfo arguments]` returns an object with +0 retain count, so no need to manually `retain/release`. 
260+             let  args = MSG_SEND_NO_ARGUMENTS_RETURN_PTR ( info,  arguments_sel) ; 
261+ 
262+             let  cnt = MSG_SEND_NO_ARGUMENTS_RETURN_NSUINTEGER ( args,  count_sel) ; 
260263            for  i in  0 ..cnt { 
261-                 let  tmp = objc_msgSend_ul ( args,  object_at_sel,  i as  libc:: c_ulong ) ; 
262-                 let  utf_c_str:  * const  libc:: c_char  = mem:: transmute ( objc_msgSend ( tmp,  utf8_sel) ) ; 
264+                 // `-[NSArray objectAtIndex:]` returns an object whose lifetime is tied to the array, so no need to manually `retain/release`. 
265+                 let  ns_string =
266+                     MSG_SEND_NSINTEGER_ARGUMENT_RETURN_PTR ( args,  object_at_index_sel,  i) ; 
267+                 // The lifetime of this pointer is tied to the NSString, as well as the current autorelease pool, which is why we heap-allocate the string below. 
268+                 let  utf_c_str:  * const  c_char  =
269+                     MSG_SEND_NO_ARGUMENTS_RETURN_PTR ( ns_string,  utf8string_sel) . cast ( ) ; 
263270                let  bytes = CStr :: from_ptr ( utf_c_str) . to_bytes ( ) ; 
264271                res. push ( OsString :: from ( str:: from_utf8 ( bytes) . unwrap ( ) ) ) 
265272            } 
0 commit comments