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

广告
将在 10 秒后关闭
bannerAds