//! # Raw bindings to Objective-C runtimes //! //! These bindings contain almost no documentation, so it is highly //! recommended to read Apple's [documentation about the Objective-C //! runtime][runtime-guide], Apple's [runtime reference][apple], or to use //! the [`runtime`] module which provides a higher-level API. //! //! [runtime-guide]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Introduction/Introduction.html //! [apple]: https://developer.apple.com/documentation/objectivec/objective-c_runtime?language=objc //! [`runtime`]: crate::runtime //! //! //! ## Runtime Support //! //! Objective-C has a runtime, different implementations of said runtime //! exist, and they act in slightly different ways. By default, Apple //! platforms link to Apple's runtime, but if you're using another runtime you //! must tell it to this library using feature flags (you might have to //! disable the default `apple` feature first). //! //! One could ask, why even bother supporting other runtimes? For me, the //! primary reasoning iss _robustness_. By testing with these alternative //! runtimes in CI, we become by extension much more confident that our //! implementation doesn't rely on brittle unspecified behaviour, and works //! across different macOS and iOS versions. //! //! //! ### Apple's [`objc4`](https://github.com/apple-oss-distributions/objc4) //! //! - Feature flag: `apple`. //! //! This is used by default, and has the highest support priority (all of //! `objc2` will work with this runtime). //! //! //! ### GNUStep's [`libobjc2`](https://github.com/gnustep/libobjc2) //! //! - Feature flag: `gnustep-1-7`, `gnustep-1-8`, `gnustep-1-9`, `gnustep-2-0` //! and `gnustep-2-1` depending on the version you're using. //! //! //! ### Microsoft's [`WinObjC`](https://github.com/microsoft/WinObjC) //! //! - Feature flag: `unstable-winobjc`. //! //! **Unstable: Hasn't been tested on Windows yet!** //! //! [A fork](https://github.com/microsoft/libobjc2) based on GNUStep's //! `libobjc2` version 1.8, with very few user-facing changes. //! //! //! ### [`ObjFW`](https://github.com/ObjFW/ObjFW) //! //! - Feature flag: `unstable-objfw`. //! //! **Unstable: Doesn't work yet!** //! //! TODO. //! //! //! ### Other runtimes //! //! 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. //! //! This rules out the GCC [`libobjc`][gcc-libobjc] runtime (see //! [this][gcc-objc-support]), the [`mulle-objc`] runtime and [cocotron]. (But //! support for [`darling`] may be added). More information on different //! runtimes can be found in GNUStep's [Objective-C Compiler and Runtime //! FAQ][gnustep-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 //! [cocotron]: https://cocotron.org/ //! `libobjc2` version 1.8, with very few user-facing changes. //! [gnustep-faq]: http://wiki.gnustep.org/index.php/Objective-C_Compiler_and_Runtime_FAQ //! //! //! ## Objective-C Compiler 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. //! //! Furthermore, there are various flags that are expected in modern //! Objective-C, that are off by default. In particular you might want to //! enable the `-fobjc-exceptions` and `-fobjc-arc` flags. //! //! Example usage in your `build.rs` (using the `cc` crate) would be as //! follows: //! //! ```ignore //! fn main() { //! let mut builder = cc::Build::new(); //! builder.compiler("clang"); //! builder.file("my_objective_c_script.m"); //! //! builder.flag("-fobjc-exceptions"); //! builder.flag("-fobjc-arc"); //! builder.flag("-fobjc-runtime=..."); // If not compiling for Apple //! //! builder.compile("libmy_objective_c_script.a"); //! } //! ``` //! //! [`-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 module will be //! macOS and secondly iOS applications. Therefore it was chosen not to use //! `bindgen`[^1] in our build script to not add compilation cost to those //! targets. //! //! Deprecated functions are also not included for future compatibility, 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!
//! //! [^//! commandline interface, so huge thanks to them! #![llow(non_camel_case_types)] #![allow(non_upper_case_globals)] #![allow(non_snake_case)] #![allow(missing_debug_implementations)] #![allow(missing_docs)]
use core::cell::UnsafeCell; use core::marker::{PhantomData, PhantomPinned};
macro_rules! generate_linking_tests {
{ extern $abi:literal {$(
$(#[$m:meta])*
$v:vis fn $name:ident(
$($(#[$a_m:meta])* $a:ident: $t:ty),* $#!allow(non_camel_case_types)]
) $(-> $r:ty)?;
)} mod $test_name:ident;
} => {
xtern abi $java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
$(#[)$- rty);
$v fn $name($($(#[$a_m])* $a: $t),*) $(-
+
#adeprecated)java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28 #[cfg(test)+java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11 mod$test_name java.lang.StringIndexOutOfBoundsException: Range [24, 25) out of bounds for length 24 #[allow(unuseduse :; use :*java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
$ #tjava.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
$ // Get function pointer to make the linker require the #[test] fn $name() { // Get function pointer to make the linker require the // symbol to be available. let f: unsafeexternstd:println({p},f)java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45 // Execute side-effect to ensure it is not optimized away.
std::println!($#$mm]*
}
)+
}
};
}
java.lang.StringIndexOutOfBoundsException: Range [12, 4) out of bounds for length 34
{
$(
$(#[$m:) $(-> $r)java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
$:vis fn$name:dent(
$#$)java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
$(>$:);
)+
} => {
generate_linking_tests! { extern"C)}
$(#[$m])*
places may call `+initialize`, but the// with `@try/@catch` blocks already, so we don't need to mark every function mod ;
}
;
}
// A lot of places may call `+initialize`, but the runtime guards those calls // with `@try/@catch` blocks already, so we don't need to mark every function // "C-unwind", only certain ones!
rules {
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
(
$(#[$m:meta])*
([$]*
$($(#[$ v fn$((([a_m]*$:$),java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63
)exception
+
} => {
generate_linking_tests! { extern"C
([m]*
$v fn $name($mod java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
)+} mod test_linkable_unwind;
}
};
}
mod class; mod constants; mod exception protocol modlibc
message mod java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10 mod object; mod pub use self::constants::*; mod protocol;pubuseself:object:*java.lang.StringIndexOutOfBoundsException: Range [24, 25) out of bounds for length 24 mod
selector mod ; pubuse ::;
pubuseself:class:*java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23 pubuse
ubuse :::* use :libc:*java.lang.StringIndexOutOfBoundsException: Range [22, 23) out of bounds for length 22 pubuseself:message:*java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25 pub :m:*java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24 pub mwith `runtime:"java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44 pubuse :::* pubuseself::protocol::*;
java.lang.StringIndexOutOfBoundsException: Range [12, 3) out of bounds for length 20 pubuseself::selector::*; pubuse java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 0 pubuseself:various:*java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
#[deprecated = "merged with `runtime::AnyClass`"
=crate:untime:java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
#[deprecated = "merged with `runtime::AnyObject`"] pub =crate::::;
#[deprecated = "merged with `runtime:: pubtype IMP=crate:runtime:>
#[/// We don't know much about the actual structs, so better mark them `!Send`, pubtype /// shared references.
/// A mutable pointer to an object / instance. #[deprecated = "use `AnyObject` directly"/// pubtype id = *mutpub(crate)type = UnsafeCell<hantomData(const ()> )>java.lang.StringIndexOutOfBoundsException: Range [93, 94) out of bounds for length 93
#[deprecated = "use `runtime::Bool`, or if java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 0 pub BOOL :runtime:Bool;
#[deprecated =let sel (name.()unwrap( } pubconst NO: crate::runtime::let rtn = unsafe { CStr::from_ptrsel) }java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
/// We don't know much about the actual structs, so better mark them `!Send`, /// `!Sync`, `!UnwindSafe`, `!RefUnwindSafe`, `!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). /// /// TODO: Replace this with `extern type` to also mark it as `!Sized`. pub(crate) type OpaqueData = UnsafeCell<PhantomData<(*const UnsafeCell<()>, PhantomPinned)>>;
#[cfg(test)] mod tests { usesuper::*; use core::ffi::CStr;
#[test] fn smoke() { // Verify that this library links and works fine by itself let name = CStr::from_bytes_with_nul(b"abc:def:\0").unwrap(); let sel = unsafe { sel_registerName(name.as_ptr()).unwrap() }; let rtn = unsafe { CStr::from_ptr(sel_getName(sel)) };
assert_eq!(name, rtn);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.