Windows-Apps
Inhaltsverzeichnis reduzieren
Inhaltsverzeichnis erweitern

Exemplarische Vorgehensweise: Erstellen einer grundlegenden Windows-Runtime-Komponente in C++ und Aufrufen dieser Komponente über JavaScript oder C#

 

Veröffentlicht: März 2016

In dieser exemplarischen Vorgehensweise wird die Erstellung einer grundlegenden Windows-Runtime-Komponenten-DLL erläutert, die aus JavaScript, C# oder Visual Basic aufgerufen werden kann. Bevor Sie die einzelnen Schritte durcharbeiten, machen Sie sich mit Konzepten wie der abstrakten binären Schnittstelle (ABI), Verweisklassen und der Komponentenerweiterungen von Visual C++ vertraut, die das Arbeiten mit Verweisklassen vereinfachen. Weitere Informationen finden Sie unter Erstellen von Windows-Runtime-Komponenten in C++ und Sprachreferenz zu Visual C++ (C++/CX).

In diesem Beispiel wird zuerst das Komponentenprojekt erstellt, Sie können aber auch erst das JavaScript-Projekt erstellen. Die Reihenfolge spielt keine Rolle.

Beachten Sie, dass die Hauptklasse der Komponente Beispiele für Definitionen von Eigenschaften und Methoden sowie eine Ereignisdeklaration enthält. Dies dient nur zur Veranschaulichung der Vorgehensweise. Die Beispiele sind nicht erforderlich, und in diesem Beispiel wird der gesamte generierte Code durch eigenen Code ersetzt.

So erstellen Sie das C++-Komponentenprojekt

  1. Wählen Sie auf der Visual Studio-Menüleiste Datei, Neu und Projekt aus.

  2. Erweitern Sie im Dialogfeld Neues Projekt links den Eintrag Visual C++, und wählen Sie den Knoten für Windows Store aus.

  3. Wählen Sie in der Mitte Komponente für Windows-Runtime aus, und benennen Sie das Projekt in WinRT_CPP.

  4. Klicken Sie auf die Schaltfläche OK.

So fügen Sie eine aktivierbare Klasse zur Komponente hinzu

  1. Eine aktivierbare Klasse ist eine Klasse, die der Clientcode mithilfe eines new-Ausdrucks (New in Visual Basic oder ref new in C++) erstellen kann. In der Komponente wird sie als public ref class sealed deklariert. Tatsächlich haben die Dateien "Class1.h" und "Class1.cpp" bereits eine Verweisklasse. Der Name kann geändert werden. In diesem Beispiel wird aber der Standardname Class1 verwendet. Bei Bedarf können Sie in der Komponente zusätzliche Verweisklassen oder reguläre Klassen definieren. Weitere Informationen über ref-Klassen finden Sie unter Typsystem (C++/CX).

So fügen Sie die erforderlichen #include-Direktiven hinzu

  • Fügen Sie der Datei "Class1.h" diese #include-Direktiven hinzu:

    collection.h ist die Headerdatei für konkrete C++-Klassen wie Platform::Collections::Vector-Klasse und Platform::Collections::Map-Klasse, die sprachneutrale Schnittstellen implementieren, die von der Windows-Runtime definiert werden. Mit amp-Headern werden Berechnungen auf dem GPU ausgeführt. Sie haben keine Windows-Runtime-Äquivalente, was aufgrund ihrer privaten Natur sinnvoll ist. Aus Leistungsgründen sollten Sie ISO-C++-Code und Standardbibliotheken allgemein intern innerhalb der Komponente verwenden; lediglich die Windows-Runtime-Schnittstelle muss in Windows-Runtime-Typen ausgedrückt werden.

So fügen Sie einen Delegaten zum Namespacebereich hinzu

  1. Ein Delegat ist ein Konstrukt, das die Parameter und den Rückgabetyp für Methoden definiert. Ein Ereignis ist eine Instanz eines bestimmten Delegattyps, und jede Ereignishandlermethode, die das Ereignis abonniert, muss über die Signatur verfügen, die im Delegaten angegeben ist. Der folgende Code definiert einen Delegattyp, der int akzeptiert und void zurückgibt. Anschließend deklariert der Code ein öffentliches event dieses Typs; dadurch kann Clientcode Methoden bereitstellen, die aufgerufen werden, wenn das Ereignis ausgelöst wird.

    Fügen Sie in Class1.h die folgende Delegatdeklaration im Namespacebereich hinzu, direkt vor der Class1-Deklaration.

    System_CAPS_tipTipp

    Sollte der Code beim Einfügen in Visual Studio nicht korrekt aneinandergereiht werden, drücken Sie einfach STRG+K+D, um den Einzug für die gesamte Datei zu korrigieren.

So fügen Sie öffentliche Member hinzu

  1. Die Klasse macht drei öffentliche Methoden und ein öffentliches Ereignis verfügbar. Die erste Methode erfolgt synchron, da sie immer sehr schnell ausgeführt wird. Da die anderen beiden Methoden einige Zeit in Anspruch nehmen können, sind sie asynchron, damit sie den UI-Thread nicht blockieren. Diese Methoden geben IAsyncOperationWithProgress und IAsyncActionWithProgress zurück. Erstere definiert eine asynchrone Methode, die ein Ergebnis zurückgibt, letztere definiert eine asynchrone Methode, die "void" zurückgibt. Über diese Schnittstellen kann Clientcode auch Aktualisierungen zum Status des Vorgangs empfangen.

So fügen Sie private Member hinzu

  1. Die Klasse enthält drei private Member: zwei Hilfsmethoden für die numerischen Berechnungen und ein CoreDispatcher-Objekt, mit dem die Ereignisaufrufe von den Arbeitsthreads zum UI-Thread zurückgemarshallt werden.

So fügen Sie die Header- und Namespace-Direktiven hinzu

  1. Fügen Sie in Class1.cpp diese #include-Direktiven hinzu:

  2. Fügen Sie nun diese using-Anweisungen hinzu, um die erforderlichen Namespaces zu erhalten:

So fügen Sie die Implementierung für ComputeResult hinzu

  1. Fügen Sie in Class1.cpp die folgende Methodenimplementierung hinzu. Diese Methode wird synchron im aufrufenden Thread ausgeführt. Dies erfolgt jedoch sehr schnell, da C++ AMP verwendet wird, um die Berechnung auf dem GPU zu parallelisieren. Weitere Informationen finden Sie unter Übersicht über C++ AMP. Die Ergebnisse werden an einen konkreten Platform::Collections::Vector<T>-Typ angefügt, der bei der Rückgabe implizit in Windows::Foundation::Collections::IVector<T> konvertiert wird.

So fügen Sie die Implementierung für GetPrimesOrdered und die zugehörige Hilfsmethode hinzu

  1. Fügen Sie in Class1.cpp die Implementierungen für GetPrimesOrdered und die is_prime - Hilfsmethode hinzu.GetPrimesOrdered verwendet eine concurrent_vector-Klasse- und eine parallel_for-Funktion-Schleife zum Aufteilen der Aufgaben und zur Nutzung aller Ressourcen des Computers, auf dem das Programm ausgeführt wird, um Ergebnisse zu erzielen. Nachdem die Ergebnisse berechnet, gespeichert und sortiert wurden, werden sie zu Platform::Collections::Vector<T> hinzugefügt und als Windows::Foundation::Collections::IVector<T> an Clientcode zurückgegeben.

    Beachten Sie den Code für den Status-Reporter, der dem Client ermöglicht, eine Statusanzeige oder eine andere Benutzeroberfläche zu verknüpfen, um dem Benutzer anzuzeigen, wie lange der Vorgang noch andauert. Die Fortschrittsberichterstellung hat jedoch auch Nachteile. Auf der Komponentenseite muss ein Ereignis ausgelöst und im UI-Thread behandelt werden, und der Statuswert muss in jeder Iteration gespeichert werden. Diesem kann begegnet werden, indem z. B. die Häufigkeit, mit der ein Statusereignis ausgelöst wird, beschränkt wird. Wenn der Aufwand noch immer zu hoch ist oder Sie die Dauer des Vorgangs nicht abschätzen können, sollten Sie die Verwendung eines Statusrings erwägen, der anzeigt, dass der Vorgang gerade ausgeführt wird, nicht jedoch die verbleibende Zeit bis zur Fertigstellung.

So fügen Sie die Implementierung für GetPrimesUnordered hinzu

  1. Im letzten Schritt der Erstellung der C++-Komponente wird die Implementierung für GetPrimesUnordered in Class1.cpp hinzugefügt. Diese Methode gibt jedes gefundene Ergebnis zurück, ohne zu warten, bis alle Ergebnisse gefunden wurden. Jedes Ergebnis wird im Ereignishandler zurückgegeben und in Echtzeit in der Benutzeroberfläche angezeigt. Beachten Sie, dass auch hier ein Status-Reporter verwendet wird. Diese Methode verwendet auch die is_prime-Hilfsmethode.

  2. Drücken Sie STRG+UMSCHALT+B, um die Komponente zu erstellen.

So erstellen Sie ein JavaScript-Projekt

  1. System_CAPS_noteHinweis

    Wenn Sie nur einen C#-Client erstellen möchten, können Sie diesen Abschnitt überspringen.

    Öffnen Sie in Projektmappen-Explorer das Kontextmenü des Knotens Projektmappe und wählen Sie die Option Hinzufügen, Neues Projekt aus.

  2. Erweitern Sie JavaScript (ggf. geschachtelt unter Andere Sprachen) und wählen Sie Leere App aus.

  3. Übernehmen Sie den Standardnamen – App1 – durch Auswählen der Schaltfläche OK.

  4. Öffnen Sie das Kontextmenü für den App1-Projektknoten, und wählen Sie dann Als Startprojekt festlegen aus.

  5. Ergänzen Sie WinRT_CPP mit einem Projektverweis:

    1. Öffnen Sie das Kontextmenü des Knotens Verweise und wählen Sie Verweis hinzufügen aus.

    2. Wählen Sie links im Dialogfeld Verweis-Manager die Option Projektmappe und dann Projekte aus.

    3. Wählen Sie in der Mitte WinRT_CPP aus, und wählen Sie dann die Schaltfläche OK.

So fügen Sie HTML-Code hinzu, mit dem die JavaScript-Ereignishandler aufgerufen werden

  1. Fügen Sie auf der Seite "default.html" den folgenden HTML-Code in den <body>-Knoten ein:

So fügen Sie Stile hinzu

  1. Entfernen Sie in der Datei "default.css" den body-Stil, und fügen Sie die folgenden Stile hinzu:

    
    #LogButtonDiv { border: orange solid 1px; -ms-grid-row: 1; /* default is 1 */ -ms-grid-column: 1; /* default is 1 */ } #LogResultDiv { background: black; border: red solid 1px; -ms-grid-row: 1; -ms-grid-column: 2; } #UnorderedPrimeButtonDiv, #OrderedPrimeButtonDiv { border: orange solid 1px; -ms-grid-row: 2; -ms-grid-column:1; } #UnorderedPrimeProgress, #OrderedPrimeProgress { border: red solid 1px; -ms-grid-column-span: 2; height: 40px; } #UnorderedPrimeResult, #OrderedPrimeResult { border: red solid 1px; font-size:smaller; -ms-grid-row: 2; -ms-grid-column: 3; -ms-overflow-style:scrollbar; }
    
    

So fügen Sie die JavaScript-Ereignishandler hinzu, welche die Komponenten-DLL aufrufen

  1. Fügen Sie am Ende der Datei "default.js" die folgenden Funktionen hinzu: Diese Funktionen werden bei Auswahl der Schaltflächen auf der Hauptseite aufgerufen. Beachten Sie, wie JavaScript die C++-Klasse aktiviert und dann die zugehörigen Methoden aufruft und mithilfe der Rückgabewerte die HTML-Bezeichnungen ausfüllt.

  2. Drücken Sie F5, um die App auszuführen.

Die Komponenten-DLL für Windows-Runtime in C++ kann von einem C#-Client ebenso problemlos aufgerufen werden wie von einem JavaScript-Client. In den folgenden Schritten wird gezeigt, wie ein C#-Client erstellt wird, der dem JavaScript-Client im vorherigen Abschnitt weitgehend ähnelt.

So erstellen Sie ein C#-Projekt

  1. Öffnen Sie in Projektmappen-Explorer das Kontextmenü des Knotens Projektmappe, und wählen Sie dann die Option Hinzufügen, Neues Projekt aus.

  2. Erweitern Sie Visual C# (ggf. geschachtelt unter Andere Sprachen), wählen Sie links Windows Store aus, und wählen Sie dann in der Mitte Leere App aus.

  3. Nennen Sie diese App CS_Client, und wählen Sie dann die Schaltfläche OK.

  4. Öffnen Sie das Kontextmenü für den CS_Client-Projektknoten, und wählen Sie dann Als Startprojekt festlegen aus.

  5. Ergänzen Sie WinRT_CPP mit einem Projektverweis:

    1. Öffnen Sie das Kontextmenü des Knotens Verweise und wählen Sie Verweis hinzufügen aus.

    2. Wählen Sie links im Dialogfeld Verweis-Manager die Option Projektmappe und dann Projekte aus.

    3. Wählen Sie in der Mitte WinRT_CPP aus, und wählen Sie dann die Schaltfläche OK.

So fügen Sie XAML hinzu, das die Benutzeroberfläche definiert

  1. Fügen Sie das folgende ScrollViewer-Objekt sowie den zugehörigen Inhalt zum Raster in "mainpage.xaml" hinzu:

    <ScrollViewer> <StackPanel Width="1400"> <Button x:Name="Button1" Width="340" Height="50"  Margin="0,20,20,20" Content="Synchronous Logarithm Calculation" FontSize="16" Click="Button1_Click_1"/> <TextBlock x:Name="Result1" Height="100" FontSize="14"></TextBlock> <Button x:Name="PrimesOrderedButton" Content="Prime Numbers Ordered" FontSize="16" Width="340" Height="50" Margin="0,20,20,20" Click="PrimesOrderedButton_Click_1"></Button> <ProgressBar x:Name="PrimesOrderedProgress" IsIndeterminate="false" Height="40"></ProgressBar> <TextBlock x:Name="PrimesOrderedResult" MinHeight="100" FontSize="10" TextWrapping="Wrap"></TextBlock> <Button x:Name="PrimesUnOrderedButton" Width="340" Height="50" Margin="0,20,20,20" Click="PrimesUnOrderedButton_Click_1" Content="Prime Numbers Unordered" FontSize="16"></Button> <ProgressBar x:Name="PrimesUnOrderedProgress" IsIndeterminate="false" Height="40" ></ProgressBar> <TextBlock x:Name="PrimesUnOrderedResult" MinHeight="100" FontSize="10" TextWrapping="Wrap"></TextBlock> <Button x:Name="Clear_Button" Content="Clear" HorizontalAlignment="Left" Margin="0,20,20,20" VerticalAlignment="Top" Width="341" Click="Clear_Button_Click" FontSize="16"/> </StackPanel> </ScrollViewer>
    

So fügen Sie die Ereignishandler für die Schaltflächen hinzu

  1. Öffnen Sie im Projektmappen-Explorer die Datei "mainpage.xaml.cs". (Die Datei ist ggf. unter "mainpage.xaml" geschachtelt.) Fügen Sie eine using-Direktive für System.Text hinzu, und fügen Sie dann den Ereignishandler für die Logarithmusberechnung in der MainPage-Klasse direkt nach OnNavigateTo hinzu.

  2. Fügen Sie den Ereignishandler für das geordnete Ergebnis hinzu:

  3. Fügen Sie den Ereignishandler für das ungeordnete Ergebnis und für die Schaltfläche hinzu. Letztere löscht die Ergebnisse, damit Sie den Code erneut ausführen können.

Wählen Sie entweder das C#-Projekt oder das JavaScript-Projekt als Startprojekt aus, indem Sie das Kontextmenü für den Projektknoten in Projektmappen-Explorer öffnen und Als Startprojekt festlegen auswählen. Drücken Sie anschließend F5, um die Seite mit Debuggen auszuführen, oder drücken Sie STRG+F5, um die Seite ohne Debuggen auszuführen.

Im Objektkatalog können Sie alle Windows-Runtime-Typen überprüfen, die in WINMD-Dateien definiert werden. Dazu gehören auch die Typen im Platform-Namespace und im Standard-Namespace. Da die Typen im Platform::Collections-Namespace in der Headerdatei "collections.h" und nicht in einer WINMD-Datei definiert sind, werden sie nicht in Objektkatalog angezeigt.

So überprüfen Sie die Komponente

  1. Wählen Sie in der Menüleiste Ansicht, Weitere Fenster, Objektkatalog aus.

  2. Erweitern Sie links im Objektkatalog den Knoten WinRT_CPP, um die in der Komponente definierten Typen und Methoden einzusehen.

Eine bessere Debugleistung erzielen Sie, wenn Sie die Debugsymbole von den öffentlichen Microsoft-Symbolservern herunterladen:

  1. Wählen Sie in der Menüleiste Extras, Optionen.

  2. Erweitern Sie im Dialogfeld Optionen den Eintrag Debugging, und wählen Sie Symbole aus.

  3. Wählen Sie Microsoft-Symbolserver aus, und wählen Sie dann die Schaltfläche OK.

Das erstmalige Herunterladen der Symbole kann etwas dauern. Wenn Sie das nächste Mal F5 drücken, können Sie den Vorgang etwas beschleunigen, indem Sie ein lokales Verzeichnis angeben, in dem die Symbole zwischengespeichert werden sollen.

Wenn Sie eine JavaScript-Projektmappe debuggen, die über eine Komponenten-DLL verfügt, können Sie den Debugger so festlegen, dass entweder das schrittweise Ausführen des Skripts oder das schrittweise Ausführen des systemeigenen Codes in der Komponente, nicht jedoch beides aktiviert wird. Um die Einstellung zu ändern, öffnen Sie in Projektmappen-Explorer das Kontextmenü des JavaScript-Projektknotens, und wählen Sie dann Eigenschaften, Debugging, Debuggertyp aus.

Im Paket-Designer müssen die entsprechenden Funktionen ausgewählt sein. Wenn Sie beispielsweise versuchen, programmgesteuert auf eine Datei im Ordner "Bilder" zuzugreifen, aktivieren Sie auf jeden Fall das Kontrollkästchen Bildbibliothek im Bereich Funktionen.

Werden die öffentlichen Eigenschaften oder Methoden der Komponente mithilfe des JavaScript-Codes nicht erkannt, überprüfen Sie, dass in JavaScript die Kamel-Schreibweise verwendet wird. Beispielsweise muss in JavaScript auf die ComputeResult-C++-Methode mit computeResult verwiesen werden.

Wenn Sie ein Windows-Runtime-Komponentenprojekt in C++ aus einer Projektmappe löschen, muss auch der Projektverweis manuell aus dem JavaScript-Projekt entfernt werden. Andernfalls können anschließend keine Debugging- oder Erstellungsvorgänge ausgeführt werden. Bei Bedarf können Sie dann einen Assemblyverweis auf die DLL hinzufügen.

Anzeigen:
© 2017 Microsoft