45 个版本
新版本 0.4.5 | 2024年8月24日 |
---|---|
0.4.3 | 2024年7月13日 |
0.3.3 | 2024年3月25日 |
0.2.11 | 2023年11月16日 |
0.0.0 |
|
#1242 在 游戏开发
每月224 次下载
在 17 个crate中 使用
5MB
112K SLoC
模块化低级Playdate API
低级绑定到Playdate API,可选适配官方文档和可选lang-items。
论文陈述中的主要概念
- 当我们遇到错误且无法恢复时必须panic。例如,当我们在api中遇到空指针时,这是致命的。
- 当API返回错误时,我们必须返回错误。
这看起来相当硬核。这就是为什么有四种以上的方式可以访问API端点,其中包括返回 Option
或 Result
。
我已经在将整个API包装在结果中的每个步骤中进行了足够的实验,然后痛苦地优化了它们的展开。最终,我得出结论,在这个特定的项目中,错误/结果的数量应该最小化。
内容
- cffi绑定
- 预生成的cffi绑定
- 最小必需部分,如lang-items
- 简单的入口点
- 额外的工具,如
println
宏
先决条件
MNRV是 1.81.0
from 2024-06-30
- Rust nightly 工具链 (rustup是可选的)
- Playdate SDK
- 确保环境变量
PLAYDATE_SDK_PATH
指向SDK根目录
- 确保环境变量
- 遵循 官方文档
- 确保在您的
PATH
中有arm-none-eabi-gcc
或gcc-arm-none-eabi
- 确保在您的
用法
应用程序的最小示例
- 使用crate-type设置库
- 添加playdate-sys依赖项
Cargo.toml
[lib]
name = "example"
path = "src/lib.rs"
crate-type = [
"dylib", # for simulator
"staticlib", # for hardware
]
[dependencies.pd]
package = "playdate-sys"
git = "this/repo/path.git"
- 接下来是初始化代码和打印所有接收事件代码的最小要求
src/lib.rs
#![no_std]
use core::ffi::*;
#[macro_use]
extern crate alloc;
#[macro_use]
extern crate pd;
use pd::ffi::*;
#[no_mangle]
// Note: `_arg` is a key-code in simulator, otherwise it's just zero.
pub extern "C" fn eventHandlerShim(api: *const PlaydateAPI, event: PDSystemEvent, _arg: u32) -> c_int {
match event {
PDSystemEvent::kEventInit => unsafe {
// register the API entry point
pd::API = api;
// get `setUpdateCallback` fn
let f = (*(*api).system).setUpdateCallback.unwrap();
// register update callback
f(Some(on_update), core::ptr::null_mut());
// `println` uses `API` internally, that set above
println!("Init, Hello world!");
},
PDSystemEvent::kEventLock => println!("Lock"),
PDSystemEvent::kEventUnlock => println!("Unlock"),
PDSystemEvent::kEventPause => println!("Pause"),
PDSystemEvent::kEventResume => println!("Resume"),
PDSystemEvent::kEventLowPower => println!("LowPower"),
PDSystemEvent::kEventTerminate => println!("Terminate"),
PDSystemEvent::kEventInitLua => println!("InitLua"),
// simulator only, keyboard events:
PDSystemEvent::kEventKeyPressed => println!("KeyPressed"),
PDSystemEvent::kEventKeyReleased => println!("KeyReleased"),
}
0 // zero means "OK, no error, continue please"
}
unsafe extern "C" fn on_update(_: *mut c_void) -> i32 { 1 /* `1` means "OK, continue updates" */ }
- 还要添加以下必要的配置
.cargo/config.toml
[target.thumbv7em-none-eabihf]
rustflags = [
"-Ctarget-cpu=cortex-m7",
"-Ctarget-feature=-fp64",
"-Clink-args=--emit-relocs",
"-Crelocation-model=pic",
"-Csoft-float=no",
"-Clink-arg=--cref",
"-Clink-arg=--gc-sections",
"-Clink-arg=--entry=eventHandlerShim"
]
# Also I recommend to allow unstable options here:
[unstable]
unstable-options = true
- 现在构建它
cargo build --lib --release --target=thumbv7em-none-eabihf -Zbuild-std=core,alloc -Zunstable-options
# Note: on windows use gcc-arm-none-eabi instead
arm-none-eabi-gcc ./target/thumbv7em-none-eabihf/release/libexample.a \
-nostartfiles -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-sp-d16 -D__FPU_USED=1 \
-Wl,--cref,--gc-sections,--no-warn-mismatch,--emit-relocs -mword-relocations \
-fno-common -fno-exceptions \
-T$PLAYDATE_SDK_PATH/C_API/buildsupport/link_map.ld \
-o ./target/thumbv7em-none-eabihf/release/example.elf \
--entry eventHandlerShim
# Then prepare package with manifest and assets, place into it example.elf and call
# `$PLAYDATE_SDK_PATH/bin/pdc` with path of prepared package.
- 然后准备带有清单和资产的包,将其中的example.elf放入其中,然后使用准备好的包的路径调用
$PLAYDATE_SDK_PATH/bin/pdc
。 - 在设备上安装并运行。
⚠️ 注意,cargo-playdate 可以轻松完成所有操作。它还可以构建可执行二进制文件。
请参阅 示例。
配置配置文件
一个小建议是将以下内容添加到您的Cargo.toml中
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
opt-level = "s" # optimize for binary size (or use `3`, play with it)
overflow-checks = false # runtime integer overflow checks. (optionally, as you wish)
lto = "fat"
incremental = false
codegen-units = 1
debug = 0
strip = "symbols" # or debuginfo
debug-assertions = false
这只是建议,因为这是完全可选的,包括例如 panic = "abort"
(撤销在这里具有挑战性但并非不可能)。
配置
您可以控制的一些主要功能类型
bindgen-...
控制绑定生成器和额外的代码生成功能bindings-...
用于为类型启用derive
以及一些代码生成,如文档- lang-items 和其他手工制作的事物。
控制包含的部分
此包包含构建您的应用程序所需的一些最小“部分”。
您可以禁用功能以防止它们被启用,这样您就可以使用其他分配器或 panic-handler 等。
allocator
:全局分配器panic-handler
:全局 panic 处理器eh-personality
:模拟器目标的 eh_personality,空,无操作
非默认功能
entry-point
:简单的最小代理入口点,在应用程序初始化时缓存 API 端点。
控制绑定生成
默认情况下,如果为您的配置(目标、配置文件、派生等)预生成了绑定,则使用它而不是构建新的。
⚠️ 环境变量 PLAYDATE_SDK_PATH
必须指向 PlayDate SDK 目录,如官方文档中所述。
要防止这种行为,请仅使用 预构建 绑定设置环境变量 IGNORE_EXISTING_PLAYDATE_SDK=1
。
这里使用 bindgen
生成绑定,并重新导出一些功能
- 使用
bindgen-runtime
开启/关闭使用 libclang 的运行时链接(dlopen)。同样适用于bindgen-static
。有关更多信息,请参阅bindgen 文档。 - 使用类似
bindings-derive-{name}
的功能来请求 bindgen 将{name}
派生到所有实体(如果可能的话)-
派生功能的完整列表
- bindings-derive-default
- bindings-derive-eq
- bindings-derive-copy
- bindings-derive-debug
- bindings-derive-hash
- bindings-derive-ord
- bindings-derive-partialeq
- bindings-derive-partialord
-
开发
此包应尽可能保持低级。
只有在它是
- 绝对必要的小东西的情况下
- 才有可能添加额外的东西
- 为 api 类型实现第三方 traits(包括核心的其他包)
- 功能门控,如果该事物有依赖项或不是如此之小。
扩展开发
您可以根据此包添加功能。只需创建一个新的您自己的包并重新导出所有功能即可。
我必须重复一遍,我为打扰您表示歉意。
⚠️ 如果您想创建一个基于此库的库,请分享以下该包的功能,以便每个人都能正确配置整个依赖树
bindgen-runtime
bindgen-static
如果用户使用这些扩展中的多个,这一点尤为重要。如果它们指定不同的配置,可能会造成混乱。
cargo创建一个新的扩展名称
cargo添加 playdate-sys
- 将上述所有功能复制并粘贴到您的 Cargo.toml 中,如下所示
[features] default = ["playdate-sys/default"] bindgen-runtime = ["playdate-sys/bindgen-runtime"] bindgen-static = ["playdate-sys/bindgen-static"] bindings-derive-debug = ["playdate-sys/bindings-derive-debug"]
例如,请参阅 repo/api 中现有的 crates。
如何生成预构建绑定?
这是一个完整的示例,展示如何生成带有文档注释的绑定,但文档是可选的,因此您可以省略它 - 只需删除所有关于文档的内容
bindings-documentation
功能- 执行
playdate-docs-parser
- 执行
rustfmt
mk dir -p ./api/sys/gen
export PD_BUILD_PREBUILT=1
# all features excluding static- or runtime- linking bingen with libclang:
DERIVES_ALL=bindings-derive-default,bindings-derive-eq,bindings-derive-copy,bindings-derive-debug,bindings-derive-hash,bindings-derive-ord,bindings-derive-partialeq,bindings-derive-partialord
DERIVES_DEF=bindings-derive-debug
FEATURES_DEF=--features=bindings-documentation,$DERIVES_DEF
FEATURES_ALL=--features=bindings-documentation,$DERIVES_ALL
cargo build -p=playdate-sys $FEATURES_DEF
cargo build -p=playdate-sys $FEATURES_DEF --target=thumbv7em-none-eabihf
cargo build -p=playdate-sys $FEATURES_ALL
cargo build -p=playdate-sys $FEATURES_ALL --target=thumbv7em-none-eabihf
# optionally format bindings:
rustfmt ./api/sys/gen/*.rs
重要提示: 要触发预构建绑定的更改,您需要设置环境变量:PD_BUILD_PREBUILT
,这允许在 OUT_DIR
之外进行更改。
本软件未获得 Panic 的赞助或支持。