22 个版本
0.5.2 | 2024 年 5 月 21 日 |
---|---|
0.5.0 | 2023 年 12 月 3 日 |
0.4.1 | 2023 年 7 月 31 日 |
0.3.0-beta.5 | 2023 年 2 月 7 日 |
0.3.0-alpha.4 | 2021 年 11 月 22 日 |
在 macOS 和 iOS API 中排名第 13
每月下载量 452,816
在 1,838 个crate (126 个直接使用) 中使用
1MB
15K SLoC
objc2
Rust 中的 Objective-C 接口和运行时绑定。
大多数在 Apple 系统上使用的核心库和框架都是用 Objective-C 编写的;这个crate使您能够与之交互。
这个 README 故意保持较小,以便于整合文档,更多信息请参阅 Rust 文档。
这个crate是objc2
项目的一部分,有关相关crate的信息请参阅该项目。
lib.rs
:
Objective-C 接口和运行时绑定
快速链接
Objective-C 曾经是 macOS、iOS、iPadOS、tvOS 和 watchOS 等Apple平台的标准编程语言。它是一种以“向实例发送消息”为中心的面向对象语言——这可以大部分被视为函数调用。
它已经被 Swift 取代,但大多数在 Apple 系统上使用的核心库和框架仍然是用 Objective-C 编写的,因此我们希望能够使用 Rust 与这些库进行交互。这个crate使您能够以尽可能安全的方式做到这一点。
基本用法
此示例演示了此crate中的主要功能部分
首先,我们使用 ClassType::alloc
分配一个新的 NSObject
。接下来,我们初始化这个对象。它确保使用 rc::Retained
来释放它。现在我们可以自由地向对象发送我们想要的消息,使用 msg_send!
或 msg_send_id!
宏(取决于方法的返回类型)。最后,当 Retained
超出作用域时,对象将被释放并销毁。
use objc2::{msg_send, msg_send_id, ClassType};
use objc2::ffi::NSUInteger;
use objc2::rc::Retained;
use objc2::runtime::{NSObject, NSObjectProtocol};
// Creation
let obj1: Retained<NSObject> = unsafe {
msg_send_id![NSObject::alloc(), init]
};
// Or
let obj2 = NSObject::new();
// Usage
let hash1: NSUInteger = unsafe { msg_send![&obj1, hash] };
let hash2: NSUInteger = unsafe { msg_send![&obj2, hash] };
assert_ne!(hash1, hash2);
let is_kind: bool = unsafe {
msg_send![&obj1, isKindOfClass: NSObject::class()]
};
assert!(is_kind);
let obj1_self: Retained<NSObject> = unsafe { msg_send_id![&obj1, self] };
assert_eq!(obj1, obj1_self);
// Deallocation on drop
注意,这个例子包含很多 unsafe
(理想情况下都应该用 // SAFETY
注释来证明)。这是必需的,因为我们的编译器几乎无法验证 Objective-C 调用,包括 msg_send!
中使用的所有参数和返回类型。我们可能不小心将 hash
的返回类型改为 f32
或其他任何类型,这将触发未定义的行为!
有关如何更方便地使用类似 Foundation
、AppKit
、UIKit
等系统框架的示例,请参阅 框架存储库。
无论如何,所有这些 unsafe
都很好地引出了这个存储库的另一个功能
编码和消息类型验证
Objective-C 运行时为每个方法包含编码,描述了参数和返回类型。有关此内容的全面概述,请参阅 encode
模块。
重要的是:为了使消息发送更安全,所有消息的参数和返回值都必须实现 encode::Encode
。这允许 Rust 编译器防止你将例如 Vec
传递给 Objective-C,这将既是不确定的,又会泄露向量。
此外,我们可以利用运行时提供的编码来验证 Rust 中使用的类型实际上与为该方法编码的类型匹配。这并不是确保安全性的完美解决方案(一些 Rust 类型具有相同的 Objective-C 编码,但不是等价的,例如 &T
和 *const T
),但它让我们更接近它!
当启用 debug_assertions
时,我们会在每次发送消息时检查编码,如果它们不匹配,消息发送将引发恐慌。
以上面的例子为例,如果我们更改 hash
方法的返回类型,如下所示,如果启用调试断言,它将引发恐慌
#
#
// Wrong return type - this is UB!
let hash1: f32 = unsafe { msg_send![&obj1, hash] };
#
这个库包含更多此类调试检查。
存储库功能
这个存储库导出了一些可选的 cargo 功能,请参阅 Cargo.toml
以了解概述和描述。
对其他操作系统的支持
这些绑定可以在使用 GNUstep Objective-C 运行时 的 Linux 或 *BSD 上使用,请参阅 objc-sys
存储库了解如何配置。
其他功能
这是一次简短的介绍,这个库还支持异常处理、[声明Objective-C类][declare_class!]、高级引用计数工具等更多功能——请随意查阅文档!