3 个版本
使用旧的 Rust 2015
0.0.2 | 2018 年 12 月 2 日 |
---|---|
0.0.1 | 2018 年 8 月 23 日 |
0.0.0 | 2018 年 5 月 14 日 |
在 macOS 和 iOS API 中排名 #53
每月下载量 76
用于 6 crate
72KB
1.5K SLoC
objrs
Objective-Rust:Rust 与 Objective-C 的不神圣结合。
objrs 是一个库,可以轻松编写与 Objective-C 代码交互的 Rust 代码。其主要目的是帮助 Rust 应用程序使用 Apple 的原生 Objective-C 框架。
除非你的代码是一堆垃圾,你想要助燃火焰,否则请不要在生产环境中使用 objrs! 项目处于起步阶段,处于一个非常实验性的阶段。API 不稳定,存在许多(已知和未知的)错误,故意引发未定义行为等。
话虽如此,试试 objrs 吧!玩玩它。非常欢迎反馈,尤其是如果你有任何关于如何更好地与 Objective-C 交互的聪明想法(例如,Objective-C 协议在 Rust 中的映射非常差,objrs 中的实现也是... 有缺陷)。
TL;DR:objrs 是什么,它做什么?
编写需要与 Objective-C 代码交互的 Rust 程序是一种痛苦的经历。不是创建 FFI 桥接(用 C 编写)(对于每一个小细节),就是要使用像 objc-rs 或 rust-objc 这样的东西来执行所有与 Objective-C 运行时的交互(在运行时!这增加了开销并减少了编译器的安全检查)。
objrs 与之不同。它提供了一组宏,这些宏在编译时对您的代码应用一系列(有问题的)转换,以便它编译成(大约)与纯 Objective-C 相同的机器代码。objrs 将您的纯 Rust 代码转换为与 Objective-C 兼容的 ABI。以下是一个示例
Objective-C
#import <Foundation/Foundation.h>
int main() {
NSObject *object = [NSObject new];
[object hash];
return 0;
}
以下 Objective-C 程序可以使用 objrs 在 Rust 中实现如下
Rust
extern crate objrs;
use objrs::objrs;
#[objrs(class, root_class)]
#[link(name = "Foundation", kind = "framework")]
struct NSObject;
#[objrs(impl)]
#[link(name = "Foundation", kind = "framework")]
impl NSObject {
// In practice you probably wouldn't want to use #[inline(always)] unless you knew what you were
// doing. Omitting it just results in an extra extern "C" wrapper fn being used, which introduces
// an extra jmp indirection.
#[objrs(selector = "new")]
#[inline(always)]
fn new() -> objrs::Strong<NSObject> {}
#[objrs(selector = "hash")]
#[inline(always)]
fn hash(&self) -> usize {}
}
fn main() {
let object = NSObject::new();
object.hash();
}
Objective-C 和 Rust 代码都将编译成相同的汇编代码(除了一些小的外观差异之外,请参阅 HOW_IT_WORKS.md 以获取更详细的说明)。
请查看demo
目录中的完整演示应用程序(完全用Rust编写)。
如何使用objrs
- 在macOS上使用最新的nightly版本的Rust。
- 在您的
Cargo.toml
的[dependencies]
部分中放入objrs = "0.0.2"
。 - 在您的crate的主Rust文件中放入
#![feature(rust_2018_preview)]
以启用objrs所需的nightly功能。 - 在您的代码中放入
use objrs::objrs
,以将objrs
宏属性引入作用域。 - 开始编写代码!
objrs还为Apple的框架提供了框架绑定。以下Apple框架有(不完整的)Rust绑定:
- AppKit(crate:
objrs_frameworks_app_kit
)。 - CoreGraphics(crate:
objrs_frameworks_core_graphics
)。 - Foundation(crate:
objrs_frameworks_foundation
)。 - Metal(crate:
objrs_frameworks_metal
)。 - MetalKit(crate:
objrs_frameworks_metal_kit
)。
有关更多详细信息,包括属性宏的实际语法,请参阅完整文档。这里的文档旨在简单易懂。
示例
使用现有的框架绑定
如果您不打算实现自己的Objective-C绑定或类,则不需要依赖于核心的objrs
crate。
extern crate objrs_frameworks_foundation;
use objrs_frameworks_foundation::NSObject;
fn main() {
// Create a new NSObject instance that is released when it goes out of scope.
let object = NSObject::new();
}
创建自己的类
您可以创建自己的类类型。实例变量受支持,但只能通过self
直接访问(例如,self.ivar
将工作,而some_other_ident.ivar
将不会工作)。
extern crate objrs;
extern crate objrs_frameworks_foundation;
use objrs::objrs;
use objrs_frameworks_foundation::NSObject;
// objrs supports instance variables, even if they have non-trivial constructors and destructors.
#[objrs(class, super = NSObject)]
pub struct StringCollection {
strings: Vec<String>,
}
#[objrs(impl)]
impl StringCollection {
// Using `no_impl` will tell objrs to just let the super class handle the message. Don't populate
// the method body; objrs will do that automatically.
#[objrs(selector = "new", no_impl)]
pub fn new() -> objrs::Strong<StringCollection> {}
// You can still use normal Rust methods. These methods are callable from Rust but not
// Objective-C.
pub fn add_string(&mut self, string: String) {
self.strings.push(string);
}
// This method is callable from Objective-C because it has been given a selector.
#[objrs(selector = "printStrings")]
pub fn print_strings(&self) {
for string in self.strings.iter() {
println!("String: {}", string);
}
}
}
fn main() {
let mut string_collection = StringCollection::new();
string_collection.add_string(String::from("Hello, world!"));
string_collection.print_strings();
}
待办事项列表
- 完全重写项目。这个版本是一个非常原始的原型。
- 找出更好的所有权和借用模型。我认为Rust的引用是澄清Objective-C API中所有权和可变性的好方法,但结果证明Objective-C中存在太多的可变别名。
- 找出如何正确支持协议。当前的实现既非常粗糙又难以使用。
- 正确支持自动释放和弱值。我有点忽略了它们。
- 自动将单元测试注入到使用objrs宏的代码中。单元测试将比较类名、继承结构、选择器、方法参数和返回值、协议一致性等。这一切都可以在今天自动完成。
- 块。目前完全不支持。
要求
- Nightly Rust。
- macOS。iOS和tvOS应该可以工作(希望如此),但尚未经过测试。watchOS支持取决于armv7支持。
- 最近的操作系统版本。只有macOS 10.14.1已经过测试。最低要求将在以后确定。
- 适用于x86_64或arm64(aarch64)的计算机。可能会添加armv7支持,但我没有armv7的Apple设备。可能会添加i386(32位x86)支持,但鉴于其过时,目前没有计划这么做。
许可证
请参阅COPYRIGHT文件。objrs根据Apache License 2.0、MIT License和Mozilla Public License 2.0的条款进行三重许可。
依赖关系
约2MB
约48K SLoC