2017-09-04 2 views
1

Ich möchte wie eine Schnittstelle ein Merkmal in Rust verwenden.Mit Merkmale Methoden aus einer Struktur Implementierung

struct CPU { 
    r: u32, 
    pc: u32 
} 

trait Bus { 
    fn read(&self, address: u32) -> u32; 
    fn write(&self, address: u32, data: u32) -> u32; 
} 

impl CPU { 
    fn step() { 
     let opcode = self.read(0xffff); // use Bus trait method here 
    } 
} 

Ich muss wissen, wie man die Trait-Methoden innerhalb meiner Implementierung von CPU ohne Implementierung lesen oder schreiben in meiner CPU-Implementierung verwenden. Ich möchte diese in einer anderen Datei haben, da sie die Speicherabbildung definieren werden. Ich denke, das ist ein einfaches Problem, ich kann einfach nicht die Antwort finden, die für mich funktioniert.

+0

Es wird ** sehr empfohlen **, dass Sie die ** ausgezeichnete ** [* The Rust Programmiersprache *] lesen (https://doc.rust-lang.org/stable/book/second-edition/) Das deckt viele dieser einführenden Fragen ab. Dies wird im Kapitel [Merkmale] behandelt (https://doc.rust-lang.org/stable/book/second-edition/ch10-02-traits.html). – Shepmaster

+0

Ich habe die erste Ausgabe des Buches gelesen, wusste nicht, dass es eine zweite Ausgabe gab, ich muss es lesen, da sich Rust ein bisschen verändert hat, seit ich es zuletzt benutzt habe. Ich denke, mein Hauptproblem ist der Wechsel von vererbungsbasierten Sprachen zu Rust's kompositionsbasiertem Design. –

Antwort

2

Trait-Implementierungen sind immer in ihrem eigenen impl Block.

impl Bus for CPU { 
    fn read(&self, address: u32) -> u32 { unimplemented!() } 
    fn write(&self, address: u32, data: u32) -> u32 { unimplemented!() } 
} 

Ein wenig bekannter Trick ist, dass impl Blöcke können in jedem Modul in Ihrer Kiste geschrieben werden, solange sowohl das Merkmal und die Art zu diesem Modul sichtbar ist (das Modul, das die impl enthält nicht über öffentlich sein). Wenn sich die Implementierung in einem Submodul unter dem Modul Bus und CPU befindet, hat das Submodul automatisch Zugriff auf beide Typen. Andernfalls müssen Sie pub(crate) (oder eine andere Form von pub, die für Sie arbeitet) auf einer oder beiden Deklarationen hinzufügen. Natürlich müssen Sie möglicherweise die Eigenschaft use und den Typ, um sie in den Bereich des Moduls, das die impl enthält, oder verwenden Sie qualifizierte Pfade.

Zum Beispiel, wenn Sie die impl in Submodul setzen wollen, könnten Sie schreiben entweder:

use super::Bus; 
use super::CPU;  

impl Bus for CPU { 
    fn read(&self, address: u32) -> u32 { unimplemented!() } 
    fn write(&self, address: u32, data: u32) -> u32 { unimplemented!() } 
} 

oder

impl super::Bus for super::CPU { 
    fn read(&self, address: u32) -> u32 { unimplemented!() } 
    fn write(&self, address: u32, data: u32) -> u32 { unimplemented!() } 
} 
+0

Danke! Ich machte eine Pause von Rust und hatte Probleme damit. Das funktioniert perfekt. –

0

Ok hier so ist, was ich tun wollte.

// bus controls reads and writes to/from emulated cpu 
// a trait allows me to define the interface the cpu expects 
pub trait Bus { 
    fn read(&self, size: Size, address: u32) -> u32; 
    fn write(&self, size: Size, address: u32, data: u32); 
} 

// must have an object to implement the bus on 
pub struct Mem {} // this can be filled out later 

// implement Bus trait for our Mem 
impl Bus for Mem { 
    fn read(&self, size: Size, address: u32) -> u32 { unimplemented!() } 
    fn write(&self, size: Size, address: u32, data: u32) { unimplemented!() } 
} 

// here is our cpu struct with a generic Bus trait object in it 
pub struct M68K<A: Bus> { 
    pub d: [u32; 8], 
    pub a: [u32; 8], 

    pub x: bool, // extend 
    pub n: bool, // negative 
    pub z: bool, // zero 
    pub v: bool, // overflow 
    pub c: bool, // carry 

    pub bus: A // here is the Bus trait object 
} 

// when we implement our cpu we can use the Bus trait methods, this allows 
// multiple cpu's to be created with the same or different Bus objects. 
// possibly connect 2 cpu's to the same Bus object? 
impl M68K<Mem> { 
    pub fn step(&self, cycles: u32) { 
    let x = self.bus.read(Size::Byte, 0xffff); 
    } 
} 

Dieser Code ist nicht fertig. Mein Hauptziel ist es, einen einfach zu bedienenden 68k CPU Emulator für meine eigenen Projekte zu erstellen. Hier zeige ich alles in einer Datei, aber in Wirklichkeit kann jetzt der gesamte CPU-Emulator geschrieben werden, ohne dass von unserem der Bus implementiert ist. Ich hoffe, das macht Sinn, es macht mir und ich genieße Rust wieder!

Verwandte Themen