Tastenkombinationen

Drücken Sie oder , um zwischen den Kapiteln zu navigieren

Drücken Sie S oder /, um im Buch zu suchen

Drücken Sie ?, um diese Hilfe anzuzeigen

Drücken Sie Esc, um diese Hilfe auszublenden

Ihren ersten COM-API-Aufruf tätigen

COM-APIs sind insofern einzigartig, als sie Funktionalität über Schnittstellen bereitstellen. Eine Schnittstelle ist lediglich eine Sammlung von Zeigern auf virtuelle Funktionen, die in einer sogenannten vtable oder virtuellen Funktionstabelle zusammengefasst sind. Dies ist nichts, was Rust direkt unterstützt, wie es C++ tut, aber das windows-Crate stellt die notwendige Code-Generierung bereit, um dies möglich und nahtlos zu machen. Eine COM-API beginnt in der Regel immer mit einem traditionellen Funktionsaufruf im C-Stil, um eine COM-Schnittstelle zu erhalten. Von dort aus können Sie über die Schnittstelle weitere Methoden aufrufen.

Einige COM-basierte APIs können sehr kompliziert werden, lassen Sie uns also mit einem sehr einfachen Beispiel beginnen. Die Funktion CreateUri ist offiziell auf MSDN dokumentiert und gibt die IUri-Schnittstelle zurück, die die Ergebnisse der Analyse der angegebenen URI darstellt. Die Rust-Dokumentation für das windows-Crate gibt an, dass sie sich im Modul Win32::System::Com befindet, sodass wir unsere windows-Crate-Abhängigkeit entsprechend konfigurieren können.

[dependencies.windows]
version = "0.52"
features = [
    "Win32_System_Com",
]

Und wir können eine use-Deklaration verwenden, um diese API etwas zugänglicher zu machen. Das core-Modul des windows-Crates stellt auch einige Hilfsmittel bereit, um die Arbeit mit COM-Schnittstellen zu erleichtern. Wir werden dies also auch einbeziehen.

#![allow(unused)]
fn main() {
use windows::{core::*, Win32::System::Com::*};
}

Für dieses Beispiel verwende ich einfach eine einfache main-Funktion mit einem großen unsafe-Block, da praktisch alles hier unsafe sein wird. Warum ist das so? Nun, das windows-Crate erlaubt Ihnen, externe Funktionen aufzurufen, und diese werden im Allgemeinen als unsafe angenommen.

fn main() -> Result<()> {
    unsafe {
        
        Ok(())
    }
}

Der einzige "interessante" Punkt hier ist die Verwendung des Result-Typs aus dem windows::core-Modul, der die Windows-Fehlerbehandlung bereitstellt, um die folgenden API-Aufrufe zu vereinfachen. Und damit können wir die Funktion CreateUri wie folgt aufrufen:

#![allow(unused)]
fn main() {
let uri = CreateUri(w!("http://kennykerr.ca"), Uri_CREATE_CANONICALIZE, 0)?;
}

Hier passiert eine ganze Menge. Der erste Parameter ist tatsächlich ein PCWSTR, der eine nullterminierte breite Zeichenkette darstellt, die von vielen Windows-APIs verwendet wird. Das windows-Crate bietet das praktische w!-Makro, um zur Kompilierzeit eine gültige nullterminierte breite Zeichenkette zu erstellen. Der zweite Parameter ist lediglich das Standardflag, das in der offiziellen Dokumentation angegeben ist. Der dritte Parameter ist reserviert und sollte daher Null sein.

Das resultierende IUri-Objekt verfügt über verschiedene Methoden, mit denen wir nun die URI untersuchen können. Die offizielle Dokumentation beschreibt die verschiedenen Schnittstellenmethoden, und die Rust-Dokumentation gibt Ihnen einen schnellen Überblick über deren verschiedene Signaturen, sodass Sie schnell herausfinden können, wie Sie sie in Rust aufrufen können. Für dieses Beispiel rufen wir einfach zwei davon auf, um die Domain der URI und die HTTP-Portnummer auszugeben.

#![allow(unused)]
fn main() {
let domain = uri.GetDomain()?;
let port = uri.GetPort()?;

println!("{domain} ({port})");
}

Unter der Haube rufen diese Methoden die virtuellen Funktionen über die COM-Schnittstelle auf und greifen auf die vom API bereitgestellte Implementierung zu. Sie bieten auch eine Reihe von Fehler- und Signaturtransformationen, um die Verwendung aus Rust sehr natürlich zu gestalten. Und das ist alles. Wenn Sie das Beispiel ausführen, sollte etwas Ähnliches wie dies ausgegeben werden:

kennykerr.ca (80)

Hier ist das vollständige Beispiel als Referenz.