C言語と互換性があれば、rustのプログラムをSwiftのプログラムとlinkすることができます。しかし、enumの各Variantがデータを持っていた場合は、どうしますか? C言語ではenumの各Variantにデータが存在しません。この記事では、そのlink方法を紹介します。
サンプルコードはこちら
rustで書かれたenumを用意しましょう。
#[repr(C)]
pub enum NiwakaEnum {
Variant1(i32, u32),
Variant2,
}
これとメモリの配置が等価な表現をSwiftで用意するには、
//これはヘッダーファイルです。
typedef enum NiwakaEnumTag { Variant1, Variant2} NiwakaEnumTag;
typedef struct NiwakaVariant1Fields{
int32_t _0;
uint32_t _1;
} NiwakaVariant1Fields;
union NiwakaEnumFields { NiwakaVariant1Fields Variant1;};
typedef struct NiwakaEnum { NiwakaEnumTag tag; union NiwakaEnumFields payload;} NiwakaEnum;
Swiftのstruct NiwakaEnumが、Rustのenum NiwakaEnumとメモリ表現が同じです。試しに、Rust側で用意した関数に、struct NiwakaEnumを渡してみましょう。
#[no_mangle]
pub extern "C" fn print_niwaka_enum(niwaka_enum: NiwakaEnum) {
match niwaka_enum {
NiwakaEnum::Variant1(value_i32, value_u32) => println!("NiwakaEnum::Variant1({}, {})", value_i32, value_u32),
NiwakaEnum::Variant2 => println!("NiwakaEnum::Variant2")
}
}
これをSwift側で(フォーマットツール適用してません。ベタ書きですみません。)
print_niwaka_enum(NiwakaEnum(tag: Variant1, payload: NiwakaEnumFields(Variant1: NiwakaVariant1Fields(_0: 10, _1: 100))))
実行結果は、
NiwakaEnum::Variant1(10, 100)
です。
なぜ同じなのか?
詳細は、Enums With FieldsとUsing Imported C Structs and Unions in Swiftを読みましょう。
参考
Enums With Fields
Using Imported C Structs and Unions in Swift