2016-07-11 11 views
-1

は、構造体を考える:C opaqueポインタを指すフィールドを定義するRustイディオムとは何ですか?

#[repr(C)] 
pub struct User { 
    pub name: *const c_char, 
    pub age: u8, 
    pub ctx: ??, 
} 

フィールドctxのみCコードによって操作されるであろう。 Cの構造体UserAttrへのポインタです。

the Rust FFI documentationによれば、選択は、不透明タイプpub enum UserAttr {}と定義される。しかし、私はRustがその値をコピーすることができないことを発見しました。 why does the address of an object change across methods

そのような不透明なポインタを定義するためにRustの正しい方法があります。その値は(ポインタとして)メソッド間でコピーされるようになりますか?

+2

「錆はその価値をコピーすることができません」というわけではありません。錆やCなどの言語がどのように機能するかだけです。あなたは他の質問の答え、特に 'Box'について読んだことがありますか? – mcarton

答えて

5

The documentationはあなたに嘘をついていません。

ルーストにこれを行うには、のはenumと私たち自身の不透明タイプを作成してみましょう:

pub enum Foo {} 
pub enum Bar {} 

extern "C" { 
    pub fn foo(arg: *mut Foo); 
    pub fn bar(arg: *mut Bar); 
} 

なし変種でenumを使用することにより、我々は作成私たちが である不透明な型は、それが変種を持たないので、インスタンス化できません。しかし、FooBar の型が異なるので、2つの型の間で型の安全性が確保されるので、 Fooへのポインタを誤ってbar()に渡すことはできません。

通常、このようなタイプを作成する通常の方法はないため、不透明なポインタはenum Foo {}です。あなたはそれへのポインタを作成することしかできません。

mod ffi { 
    use std::ptr; 

    pub enum MyTypeFromC {} 

    pub fn constructor() -> *mut MyTypeFromC { 
     ptr::null_mut() 
    } 

    pub fn something(_thing: *mut MyTypeFromC) { 
     println!("Doing a thing"); 
    } 
} 

use ffi::*; 

struct MyRustType { 
    score: u8, 
    the_c_thing: *mut MyTypeFromC, 
} 

impl MyRustType { 
    fn new() -> MyRustType { 
     MyRustType { 
      score: 42, 
      the_c_thing: constructor(), 
     } 
    } 

    fn something(&mut self) { 
     println!("My score is {}", self.score); 
     ffi::something(self.the_c_thing); 
     self.score += 1; 
    } 
} 

fn main() { 
    let mut my_thing = MyRustType::new(); 
    my_thing.something(); 
} 

少しそれを破壊:

// opaque -----V~~~~~~~~~V 
      *mut MyTypeFromC 
//  ^~~^ ------------ pointer 

は、したがって、不透明なポインタです。構造体MyRustTypeを移動しても、ポインタの値は変更されません。

関連する問題