2016-06-12 8 views
1

私はrust-eflプロジェクトに取り組んでいます。これはEnlightenment EFL Cライブラリへのバインディングです。2つの列挙型パラメータを使用して関数を定義するには、2番目の型は1番目の?

2つのCスタイルの列挙型を使用してライブラリを構成する関数があります。私は最初の引数の値に基づいて2番目の引数を特定の列挙型に制限したい。

この例の実際のコードは、使用例を少し分かりやすくするために使用します。

例コール:

elementary::policy_set(ElmPolicy::Quit, ElmPolicyQuit::LastWindowClosed as i32); 

ライブラリさびコード:

#[repr(C)] 
pub enum ElmPolicy { 
    /// under which circumstances the application should quit automatically. See ElmPolicyQuit 
    Quit = 0, 
    /// defines elm_exit() behaviour. See ElmPolicyExit 
    Exit, 
    /// defines how throttling should work. See ElmPolicyThrottle 
    Throttle 
} 
#[repr(C)] 
pub enum ElmPolicyQuit { 
    /// never quit the application automatically 
    None = 0, 
    /// quit when the application's last window is closed 
    LastWindowClosed, 
    /// quit when the application's last window is hidden 
    LastWindowHidden 
} 

pub fn policy_set(policy: ElmPolicy, value: i32) { 

ElmPolicyの値ごとElmPolicyQuitと同様列挙があります。 policy_setの2番目の引数は、対応する列挙型でなければなりません。

valueの型を定義して、呼び出し元がi32に値をキャストする必要がないように、policy_setを修正したいと考えています。理想的には、Rustに、第2引数が指定されたpolicy引数の正しい型であることを確認したいと思います。

実装しようとしました

私は錆に新たなんだ、これは遠く離れてかもしれないが、これは私の現在の試みです:

pub fn policy_set<P: ElmPolicy, V: ElmPolicyValue<P>>(policy: P, value: V) { 
    unsafe { elm_policy_set(policy as c_int, value as c_int) } 
} 

trait ElmPolicyValue<P> {} 
impl ElmPolicyValue<ElmPolicy::Quit> for ElmPolicyQuit {} 

しかし、私はこのエラーを取得する:

src/elementary.rs:246:22: 246:31 error: ElmPolicy is not a trait [E0404] src/elementary.rs:246 pub fn policy_set>(policy: P, value: V) {

(最初の引数の型を指す矢印)

私はElmPolicyのためのダミー形質を作ったが、私はこのように一般的なタイプのために列挙型を使用することはできませんように、私は

src/elementary.rs:111:21: 111:36 error: found value elementary::ElmPolicy::Quit used as a type [E0248] src/elementary.rs:111 impl ElmPolicyValue for ElmPolicyQuit {}

を取得するだから、そうです。 これを実装する正しい方法は何ですか?

実際に列挙型にする必要はありません。私は、EFLライブラリのC enumに対応するc_intに変換可能な値が必要です。

また、私は代わりに1つの引数について考えました。

elementary::policy_set(elementary::Policy::Quit::LastWindowClosed); 

しかし、ネストされたC-のような列挙型は、私が見つけた文書にもかかわらず動作するようには思えませんし、私は、ネストされた列挙型で#[repr(C)]の使用についての不確実です。

答えて

1

ElmPolicyenumと定義する代わりに、ポリシーの値のパラメータタイプを指定する関連タイプの特性として定義したいと思います。各ポリシーは、ElmPolicyを実装するユニット構造体を定義します。

​​

あなたは、必要に応じてElmPolicy::Valueにメソッドまたはsupertraits ElmPolicyへとcontraintsを追加することができます。たとえば、ElmPolicy::Valueに制約としてInto<i32>を追加すると、value.into()policy_setに入力してi32に変換することができます。

2

私は両方の問題を一挙に解決しようとはしません。 APIをそのまま公開するCライブラリへの直接的なRustバインディングを作成します(*-sys package)。その上に、より慣用的な錆のAPIを提供します。

enum ElmPolicy { 
    Quit(QuitDetail), 
    Exit(ExitDetail), 
    Throttle(ThrottleDetail), 
} 

enum QuitDetail { 
    None, 
    LastWindowClosed, 
    LastWindowHidden, 
} 

その後、あなたはCの列挙型のタプルを生成ElmPolicyのメソッドを作成することができ、または必要に応じて直接、適切なC関数を呼び出します。

*-sysクレートの列挙型が慣用的なAPIの列挙型を反映しており、それらの間で変換する必要があるため、少しの定型文が存在する可能性があることに注意してください。マクロはそれを減らすのに役立ちます。

+0

私はAPIをより多くのRustフレンドリーなものに変更することを考えています。この* -sysパターンやその記事に従ったプロジェクトの良い例がありますか? – Arlo

+0

@Arlo私は以前は少し怠惰で、今はリソースにリンクしています。それは役に立ちますか? – Shepmaster

関連する問題