22//! Apple: `objc-exception.h`
33//! GNUStep: `eh_personality.c`, which is a bit brittle to rely on, but I
44//! think it's fine...
5- #[ cfg( not( objfw) ) ]
5+ #[ cfg( any ( not( objfw) , feature = "unstable-exception" ) ) ]
66use core:: ffi:: c_void;
7- #[ cfg( apple ) ]
7+ #[ cfg( apple_new ) ]
88use std:: os:: raw:: c_int;
9+ #[ cfg( feature = "unstable-exception" ) ]
10+ use std:: os:: raw:: c_uchar;
911
10- #[ cfg( apple ) ]
12+ #[ cfg( apple_new ) ]
1113use crate :: objc_class;
1214use crate :: objc_object;
1315
1416/// Remember that this is non-null!
15- #[ cfg( apple ) ]
17+ #[ cfg( apple_new ) ]
1618pub type objc_exception_matcher =
1719 unsafe extern "C" fn ( catch_type : * mut objc_class , exception : * mut objc_object ) -> c_int ;
1820
1921/// Remember that this is non-null!
20- #[ cfg( apple ) ]
22+ #[ cfg( apple_new ) ]
2123pub type objc_exception_preprocessor =
2224 unsafe extern "C" fn ( exception : * mut objc_object ) -> * mut objc_object ;
2325
2426/// Remember that this is non-null!
25- #[ cfg( apple ) ]
27+ #[ cfg( apple_new ) ]
2628pub type objc_uncaught_exception_handler = unsafe extern "C" fn ( exception : * mut objc_object ) ;
2729
2830#[ cfg( objfw) ]
@@ -32,45 +34,79 @@ pub type objc_uncaught_exception_handler =
3234/// Only available on macOS.
3335///
3436/// Remember that this is non-null!
35- #[ cfg( all( apple , target_os = "macos" ) ) ]
37+ #[ cfg( all( apple_new , target_os = "macos" ) ) ]
3638pub type objc_exception_handler =
3739 unsafe extern "C" fn ( unused : * mut objc_object , context : * mut c_void ) ;
3840
3941extern_c ! {
40- #[ cfg( not ( objfw ) ) ]
42+ #[ cfg( any ( gnustep , apple_new ) ) ]
4143 pub fn objc_begin_catch( exc_buf: * mut c_void) -> * mut objc_object;
42- #[ cfg( not ( objfw ) ) ]
44+ #[ cfg( any ( gnustep , apple_new ) ) ]
4345 pub fn objc_end_catch( ) ;
4446 /// See [`objc-exception.h`].
4547 ///
4648 /// [`objc-exception.h`]: https://github.com/apple-oss-distributions/objc4/blob/objc4-818.2/runtime/objc-exception.h
4749 pub fn objc_exception_throw( exception: * mut objc_object) -> !;
48- #[ cfg( apple ) ]
50+ #[ cfg( apple_new ) ]
4951 pub fn objc_exception_rethrow( ) -> !;
52+
53+ #[ cfg( apple_old) ]
54+ pub fn objc_exception_try_enter( exception_data: * const c_void) ;
55+
56+ #[ cfg( apple_old) ]
57+ pub fn objc_exception_try_exit( exception_data: * const c_void) ;
58+
59+ // objc_exception_extract
60+ // objc_exception_match
61+ // objc_exception_get_functions
62+ // objc_exception_set_functions
63+
5064 #[ cfg( any( gnustep, winobjc) ) ]
5165 pub fn objc_exception_rethrow( exc_buf: * mut c_void) -> !;
5266
53- #[ cfg( apple ) ]
67+ #[ cfg( apple_new ) ]
5468 pub fn objc_setExceptionMatcher( f: objc_exception_matcher) -> objc_exception_matcher;
55- #[ cfg( apple ) ]
69+ #[ cfg( apple_new ) ]
5670 pub fn objc_setExceptionPreprocessor(
5771 f: objc_exception_preprocessor,
5872 ) -> objc_exception_preprocessor;
59- #[ cfg( any( apple , objfw) ) ]
73+ #[ cfg( any( apple_new , objfw) ) ]
6074 pub fn objc_setUncaughtExceptionHandler(
6175 f: objc_uncaught_exception_handler,
6276 ) -> objc_uncaught_exception_handler;
6377
6478 /// Only available on macOS.
65- #[ cfg( all( apple , target_os = "macos" ) ) ]
79+ #[ cfg( all( apple_new , target_os = "macos" ) ) ]
6680 pub fn objc_addExceptionHandler( f: objc_exception_handler, context: * mut c_void) -> usize ;
6781 /// Only available on macOS.
68- #[ cfg( all( apple , target_os = "macos" ) ) ]
82+ #[ cfg( all( apple_new , target_os = "macos" ) ) ]
6983 pub fn objc_removeExceptionHandler( token: usize ) ;
7084
7185 // Only available when ENABLE_OBJCXX is set, and a useable C++ runtime is
7286 // present when building libobjc2.
7387 //
7488 // #[cfg(gnustep)]
7589 // pub fn objc_set_apple_compatible_objcxx_exceptions(newValue: c_int) -> c_int;
90+
91+ /// Call the given function inside an Objective-C `@try/@catch` block.
92+ ///
93+ /// Defined in `extern/exception.m` and compiled in `build.rs`.
94+ ///
95+ /// Alternatively, we could manually write assembly for this function like
96+ /// [`objrs` does][manual-asm] does, that would cut down on a build stage
97+ /// (and would probably give us a bit better performance), but it gets
98+ /// unwieldy _very_ quickly, so I chose the much more stable option.
99+ ///
100+ /// Another thing to remember: While Rust's and Objective-C's unwinding
101+ /// mechanisms are similar now, Rust's is explicitly unspecified, and they
102+ /// may diverge significantly in the future; so handling this in pure Rust
103+ /// (using mechanisms like core::intrinsics::r#try) is not an option!
104+ ///
105+ /// [manual-asm]: https://gitlab.com/objrs/objrs/-/blob/b4f6598696b3fa622e6fddce7aff281770b0a8c2/src/exception.rs
106+ #[ cfg( feature = "unstable-exception" ) ]
107+ pub fn rust_objc_sys_0_2_try_catch_exception(
108+ f: extern "C" fn ( * mut c_void) ,
109+ context: * mut c_void,
110+ error: * mut * mut objc_object,
111+ ) -> c_uchar;
76112}
0 commit comments