Erstellen von Windows-Runtime-Komponenten in C++
In diesem Artikel wird beschrieben, wie eine Windows-Runtime-Komponente mit C++ erstellt wird. Hierbei handelt es sich um eine DLL, die von einer Windows Store-App aus aufgerufen werden kann, die mit JavaScript (oder C#, Visual Basic oder C++ entwickelt wurde. Im Folgenden einige Gründe für das Erstellen einer solchen Komponente:
Leistungsvorteil von C++ in komplexen oder rechenintensiven Vorgängen
Erneutes Verwenden von Code, der bereits geschrieben und getestet wurde
Wenn Sie eine Projektmappe erstellen, die ein JavaScript- oder .NET-Projekt und ein Windows-Runtime-Komponentenprojekt enthält, werden die JavaScript-Projektdateien und die kompilierte DLL in ein Paket zusammengeführt, das Sie lokal, im Simulator oder remote auf einem verbundenen Gerät debuggen können. Außerdem können Sie nur das Komponentenprojekt als SDK-Erweiterung verteilen. Weitere Informationen finden Sie unter Gewusst wie: Erstellen eines Software Development Kit (SDK).
Wenn Sie die C++-Komponente codieren, verwenden Sie im Allgemeinen die reguläre C++-Bibliothek und integrierte Typen außer an der Grenze der abstrakten binären Schnittstelle (ABI), an der Sie Daten an und von Code in einem anderen .winmd-Paket übergeben. Verwenden Sie dort Windows-Runtime-Typen und die spezielle Syntax, die Visual C++ zum Erstellen und Bearbeiten dieser Typen unterstützt. Verwenden Sie außerdem Typen wie delegate und event im Visual C++-Code, um Ereignisse zu implementieren, die von der Komponente ausgelöst und in JavaScript, Visual Basic oder C# bearbeitet werden können. Weitere Informationen zur neuen Visual C++-Syntax finden Sie unter Sprachreferenz zu Visual C++ (C++/CX).
Groß-/Kleinschreibung und Benennungsregeln
JavaScript
Bei JavaScript muss die Groß-/Kleinschreibung beachtet werden. Daher müssen die folgenden Konventionen für die Groß- und Kleinschreibung eingehalten werden:
Wenn Sie auf C++-Namespaces und -Klassen verweisen, verwenden Sie die gleiche Schreibweise wie auf der C++-Seite.
Wenn Sie Methoden aufrufen, verwenden Sie die Kamel-Schreibweise, auch wenn der Methodennamen auf der C++-Seite großgeschrieben wird. Beispielsweise muss eine C++-Methode GetDate() von JavaScript aus als getDate() aufgerufen werden.
Ein aktivierbarer Klassenname und ein Namespacename dürfen keine UNICODE-Zeichen enthalten.
.NET
Die .NET-Sprachen folgen ihren üblichen Regeln zur Groß-/Kleinschreibung.
Instanziieren des Objekts
Nur Windows-Runtime-Typen können über die ABI-Grenze übergeben werden. Der Compiler löst einen Fehler aus, wenn die Komponente über einen Typ wie std::wstring als Rückgabetyp oder Parameter in einer öffentlichen Methode verfügt. Die integrierten Typen Komponentenerweiterungen für Visual C++ (C++/CX) enthalten die üblichen Skalare wie int und double sowie ihre Typedef-Entsprechungen int32, float64, usw. Weitere Informationen finden Sie unter Typsystem (C++/CX).
C++
// ref class definition in C++
public ref class SampleRefClass sealed
{
// Class members...
// #include <valarray>
public:
double LogCalc(double input)
{
// Use C++ standard library as usual.
return std::log(input);
}
};
JavaScript
//Instantiation in JavaScript (requires "Add reference > Project reference")
var nativeObject = new CppComponent.SampleRefClass();
.NET
//Call a method and display result in a XAML TextBlock
var num = nativeObject.LogCalc(21.5);
ResultText.Text = num.ToString();
Integrierte C++-Typen, Bibliothektypen und Windows-Runtime-Typen
Eine aktivierbare Klasse (auch als Verweisklasse bezeichnet) ist eine Klasse, die von einer anderen Sprache wie JavaScript, C# oder Visual Basic instanziiert werden kann. Um in einer anderen Sprache verwendet werden zu können, muss eine Komponente mindestens eine aktivierbare Klasse enthalten.
Eine Windows-Runtime-Komponente kann mehrere aktivierbare öffentliche Klassen sowie zusätzliche Klassen enthalten, die der Komponente nur intern bekannt sind. Alle öffentlichen Klassen müssen sich im gleichen Stammnamespace befinden, dessen Name dem Namen der Komponentenmetadatendatei gleicht. Wenden Sie das [WebHostHidden]-Attribut auf C++-Typen an, die in JavaScript nicht sichtbar sein sollen.
Der Clientcode erstellt eine Instanz der Komponente, mittels des Schlüsselworts new (New in Visual Basic) so wie für jede andere Klasse auch.
Eine aktivierbare Klasse muss als public ref class sealed deklariert werden. Das Schlüsselwort der ref-Klasse teilt dem Compiler mit, die Klasse als kompatiblen Windows-Runtime-Typ zu erstellen, und das Schlüsselwort sealed gibt an, dass die Klasse nicht geerbt werden kann. Windows-Runtime unterstützt derzeit kein generalisiertes Vererbungsmodell. Ein begrenztes Vererbungsmodell unterstützt die Erstellung von benutzerdefinierten XAML-Kontrollen. Weitere Informationen finden Sie unter Verweisklassen und Verweisstrukturen (C++/CX).
Bei C++ werden alle numerischen Primitive im Standardnamespace definiert. Der Platform Namespace enthält C++-Klassen, die sich speziell auf das Windows-Runtime-Typsystem beziehen. Dazu gehören Platform::String-Klasse und Platform::Object-Klasse. Die konkreten Auflistungstypen wie Platform::Collections::Map-Klasse und Platform::Collections::Vector-Klasse werden im Platform::Collections-Namespace definiert. Die öffentlichen Schnittstellen, die diese Typen implementieren, werden im Windows::Foundation::Collections-Namespace (C++/CX) definiert. Diese Schnittstellentypen werden von JavaScript, C# und Visual Basic genutzt. Weitere Informationen finden Sie unter Typsystem (C++/CX).
Methode, die einen Wert des integrierten Typs zurückgibt
C++
// #include <valarray>
public:
double LogCalc(double input)
{
// Use C++ standard library as usual.
return std::log(input);
}
JavaScript
//Call a method
var nativeObject = new CppComponent.SampleRefClass;
var num = nativeObject.logCalc(21.5);
document.getElementById('P2').innerHTML = num;
.NET
Methode, die eine Struktur des benutzerdefinierten Werts zurückgibt
value struct ist ein schlichtes Datenobjekt, das Felder enthalten kann, die standardmäßig öffentlich sind. value struct wird von einem Wert übergeben.
C++
namespace CppComponent
{
// Custom struct
public value struct PlayerData
{
Platform::String^ Name;
int Number;
double ScoringAverage;
};
public ref class Player sealed
{
private:
PlayerData m_player;
public:
property PlayerData PlayerStats
{
PlayerData get(){ return m_player; }
void set(PlayerData data) {m_player = data;}
}
};
}
JavaScript
Um benutzerdefinierte Wertstrukturen über ABI zu übergeben, definieren Sie ein JavaScript-Objekt, das dieselben Member wie die Wertstruktur hat, die in C++ definiert ist. Sie können dieses Objekt dann als Argument an eine C++-Methode übergeben, sodass das Objekt implizit in den C++-Typ konvertiert wird.
// Get and set the value struct
function GetAndSetPlayerData() {
// Create an object to pass to C++
var myData =
{ name: "Bob Homer", number: 12, scoringAverage: .357 };
var nativeObject = new CppComponent.Player();
nativeObject.playerStats = myData;
// Retrieve C++ value struct into new JavaScript object
var myData2 = nativeObject.playerStats;
document.getElementById('P3').innerHTML = myData.name + " , " + myData.number + " , " + myData.scoringAverage.toPrecision(3);
}
Ein anderer Ansatz besteht darin, eine Klasse zu definieren, die IPropertySet implementiert (nicht dargestellt).
C#
In den .NET-Sprachen erstellen Sie einfach eine Variable des in der C++-Komponente definierten Typs.
private void GetAndSetPlayerData()
{
// Create a ref class
var player = new CppComponent.Player();
// Create a variable of a value struct
// type that is defined in C++
CppComponent.PlayerData myPlayer;
myPlayer.Name = "Babe Ruth";
myPlayer.Number = 12;
myPlayer.ScoringAverage = .398;
// Set the property
player.PlayerStats = myPlayer;
// Get the property and store it in a new variable
CppComponent.PlayerData myPlayer2 = player.PlayerStats;
ResultText.Text += myPlayer.Name + " , " + myPlayer.Number.ToString() +
" , " + myPlayer.ScoringAverage.ToString();
}
Überladene Methoden
Eine öffentliche Verweisklasse in C++ kann überladene Methoden enthalten, allerdings verfügt JavaScript nur über eingeschränkt Möglichkeiten zur Unterscheidung überladener Methoden. So kann beispielsweise der Unterschied zwischen folgenden Signaturen erkannt werden:
public ref class NumberClass sealed
{
public:
int GetNumber(int i);
int GetNumber(int i, Platform::String^ str);
double GetNumber(int i, MyData^ d);
};
Der Unterschied zwischen diesen Signaturen wird hingegen nicht erkannt:
int GetNumber(int i);
double GetNumber(double d);
Oder zwischen diesen Signaturen:
Bei Mehrdeutigkeit können Sie sicherstellen, dass JavaScript immer eine bestimmte Überladung aufruft, indem das Windows::Foundation::Metadata::DefaultOverload-Attribut auf die Methodensignatur in der Headerdatei angewendet wird.
Dieses JavaScript ruft immer die attributierte Überladung auf:
var nativeObject = new CppComponent.NumberClass();
var num = nativeObject.getNumber(9);
document.getElementById('P4').innerHTML = num;
.NET
.NET-Sprachen erkennen Überladungen in einer Verweisklasse von C++ ebenso, wie in jeder .NET Framework-Klasse.
DateTime
In Windows-Runtime handelt es sich bei einem Windows::Foundation::DateTime-Objekt nur um eine ganze 64-Bit-Zahl mit Vorzeichen, die die Anzahl von 100 Nanosekundenintervalle entweder vor oder nach dem 1. Januar 1601 darstellt. Es gibt keine Methoden für ein Windows:Foundation::DateTime-Objekt. Stattdessen wird DateTime in jeder Sprache auf die systemeigene Weise berechnet: das Date-Objekt in JavaScript sowie die Typen System.DateTime und System.DateTimeOffset in .NET Framework.
C++
public ref class MyDateClass sealed
{
public:
property Windows::Foundation::DateTime TimeStamp;
void SetTime(Windows::Foundation::DateTime dt)
{
auto cal = ref new Windows::Globalization::Calendar();
cal->SetDateTime(dt);
TimeStamp = cal->GetDateTime(); // or TimeStamp = dt;
}
};
JavaScript
Wenn Sie einen DateTime-Wert von C++ an JavaScript übergeben, akzeptiert JavaScript diesen als Date-Objekt und zeigt ihn standardmäßig als lange Formulardatenzeichenfolge an.
function SetAndGetDate() {
var nativeObject = new CppComponent.MyDateClass();
var myDate = new Date(1956, 4, 21);
nativeObject.setTime(myDate);
var myDate2 = nativeObject.timeStamp;
//prints long form date string
document.getElementById('P5').innerHTML = myDate2;
}
.NET
Wenn eine .NET-Sprache System.DateTime an eine C++-Komponente übergibt, akzeptiert die Methode das Element als Windows::Foundation::DateTime. Wenn die Komponente Windows::Foundation::DateTime an eine .NET Framework-Methode übergibt, akzeptiert die Framework-Methode das Element als DateTimeOffset.
private void DateTimeExample()
{
// Pass a System.DateTime to a C++ method
// that takes a Windows::Foundation::DateTime
DateTime dt = DateTime.Now;
var nativeObject = new CppComponent.MyDateClass();
nativeObject.SetTime(dt);
// Retrieve a Windows::Foundation::DateTime as a
// System.DateTimeOffset
DateTimeOffset myDate = nativeObject.TimeStamp;
// Print the long-form date string
ResultText.Text += myDate.ToString();
}
Auflistungen und Arrays
Auflistungen werden immer als Handles über die ABI-Grenze an Windows-Runtime-Typen, wie Windows::Foundation::Collections::IVector^ und Windows::Foundation::Collections::IMap^ übergeben. Wenn Sie beispielsweise ein Handle für Platform::Collections::Map zurückgeben, wird es implizit in Windows::Foundation::Collections::IMap^ konvertiert. Die Auflistungsschnittstellen werden in einem Namespace definiert, der von den C++-Klassen, die die konkreten Implementierungen bereitstellen, getrennt ist. Die Schnittstellen werden von JavaScript und .NET-Sprachen genutzt. Weitere Informationen finden Sie unter Auflistungen (C++/CX) und Array und WriteOnlyArray (C++/CX).
Übergeben von IVector
C++
// Windows::Foundation::Collections::IVector across the ABI.
//#include <algorithm>
//#include <collection.h>
Windows::Foundation::Collections::IVector<int>^ SortVector(Windows::Foundation::Collections::IVector<int>^ vec)
{
std::sort(begin(vec), end(vec));
return vec;
}
JavaScript
var nativeObject = new CppComponent.CollectionExample();
// Call the method to sort an integer array
var inVector = [14, 12, 45, 89, 23];
var outVector = nativeObject.sortVector(inVector);
var result = "Sorted vector to array:";
for (var i = 0; i < outVector.length; i++)
{
outVector[i];
result += outVector[i].toString() + ",";
}
document.getElementById('P6').innerHTML = result;
.NET
In den .NET-Sprachen wird IVector<T> als IList<T> betrachtet.
private void SortListItems()
{
IList<int> myList = new List<int>();
myList.Add(5);
myList.Add(9);
myList.Add(17);
myList.Add(2);
var nativeObject = new CppComponent.CollectionExample();
IList<int> mySortedList = nativeObject.SortVector(myList);
foreach (var item in mySortedList)
{
ResultText.Text += " " + item.ToString();
}
}
Übergeben von IMap
C++
// #include <map>
//#include <collection.h>
Windows::Foundation::Collections::IMap<int, Platform::String^> ^GetMap(void)
{
Windows::Foundation::Collections::IMap<int, Platform::String^> ^ret =
ref new Platform::Collections::Map<int, Platform::String^>;
ret->Insert(1, "One ");
ret->Insert(2, "Two ");
ret->Insert(3, "Three ");
ret->Insert(4, "Four ");
ret->Insert(5, "Five ");
return ret;
}
JavaScript
// Call the method to get the map
var outputMap = nativeObject.getMap();
var mStr = "Map result:" + outputMap.lookup(1) + outputMap.lookup(2)
+ outputMap.lookup(3) + outputMap.lookup(4) + outputMap.lookup(5);
document.getElementById('P7').innerHTML = mStr;
.NET
In den .NET-Sprachen wird IMap als IDictionary<K,V> betrachtet.
private void GetDictionary()
{
var nativeObject = new CppComponent.CollectionExample();
IDictionary<int, string> d = nativeObject.GetMap();
ResultText.Text += d[2].ToString();
}
Properties
Eine öffentliche Verweisklasse macht Datenmember in Komponentenerweiterungen für Visual C++ mithilfe des property-Schlüsselworts als öffentliche Eigenschaften verfügbar. Das Konzept ist mit .NET Framework-Eigenschaften identisch. Eine triviale Eigenschaft ähnelt einem Datenmember, da die Funktionen implizit sind. Eine nicht triviale Eigenschaft verfügt über explizite get- und set-Accessoren und eine benannte private Variable, die den "Sicherungsspeicher" für den Wert darstellt. In diesem Beispiel ist der private Member variable _propertyAValue der Sicherungsspeicher für PropertyA. Eine Eigenschaft kann ein Ereignis auslösen, wenn dessen Wert sich ändert, und eine Client-App kann registriert werden, um dieses Ereignis zu empfangen.
C++
//Properties
public delegate void PropertyChangedHandler(Platform::Object^ sender, int arg);
public ref class PropertyExample sealed
{
public:
PropertyExample(){}
// Event that is fired when PropetyA changes
event PropertyChangedHandler^ PropertyChangedEvent;
// Property that has custom setter/getter
property int PropertyA
{
int get() { return m_propertyAValue; }
void set(int propertyAValue)
{
if (propertyAValue != m_propertyAValue)
{
m_propertyAValue = propertyAValue;
// Fire event. (See event example below.)
PropertyChangedEvent(this, propertyAValue);
}
}
}
// Trivial get/set property that has a compiler-generated backing store.
property Platform::String^ PropertyB;
private:
// Backing store for propertyA.
int m_propertyAValue;
};
JavaScript
var nativeObject = new CppComponent.PropertyExample();
var propValue = nativeObject.propertyA;
document.getElementById('P8').innerHTML = propValue;
//Set the string property
nativeObject.propertyB = "What is the meaning of the universe?";
document.getElementById('P9').innerHTML += nativeObject.propertyB;
.NET
.NET-Sprachen greifen auf Eigenschaften auf einem systemeigenen C++-Objekt genauso zu, wie sie es bei einem .NET Framework-Objekt tun.
private void GetAProperty()
{
// Get the value of the integer property
// Instantiate the C++ object
var obj = new CppComponent.PropertyExample();
// Get an integer property
var propValue = obj.PropertyA;
ResultText.Text += propValue.ToString();
// Set a string property
obj.PropertyB = " What is the meaning of the universe?";
ResultText.Text += obj.PropertyB;
}
Delegaten und Ereignisse
Ein delegate ist ein Windows-Runtime-Typ, der ein Funktionsobjekt darstellt. Sie können Delegaten in Verbindung mit Ereignissen, Rückrufen und asynchronen Methodenaufrufen verwenden, um eine Aktion anzugeben, die später ausgeführt werden soll. Der Delegat bietet genau wie ein Funktionsobjekt Typsicherheit, indem er es dem Compiler ermöglicht, den Rückgabetyp und die Parametertypen der Funktion zu überprüfen. Die Deklaration eines Delegaten ähnelt einer Funktionssignatur, die Implementierung entspricht einer Klassendefinition, und der Aufruf ähnelt einem Funktionsaufruf.
Hinzufügen eines Ereignislisteners
Sie können das Schlüsselwort event verwenden, um einen öffentlichen Member eines angegebenen Delegattyps zu deklarieren. Der Client abonniert das Ereignis, indem er die Standardmechanismen verwendet, die in einer bestimmten Sprache bereitgestellt werden.
C++
public:
event SomeHandler^ someEvent;
In diesem Beispiel wird der gleiche C++-Code verwendet, wie im vorherigen Abschnitt "Eigenschaften".
JavaScript
function Button_Click() {
var nativeObj = new CppComponent.PropertyExample();
// Define an event handler method
var singlecasthandler = function (ev) {
document.getElementById('P10').innerHTML = "The button was clicked and the value is " + ev;
};
// Subscribe to the event
nativeObj.onpropertychangedevent = singlecasthandler;
// Set the value of the property and fire the event
var propValue = 21;
nativeObj.propertyA = 2 * propValue;
}
.NET
Bei den .NET-Sprachen ist das Abonnieren eines Ereignisses in einer C++-Komponente mit dem Abonnieren eines Ereignisses in einer .NET Framework-Klasse identisch:
//Subscribe to event and call method that causes it to be fired.
private void TestMethod()
{
var objWithEvent = new CppComponent.PropertyExample();
objWithEvent.PropertyChangedEvent += objWithEvent_PropertyChangedEvent;
objWithEvent.PropertyA = 42;
}
//Event handler method
private void objWithEvent_PropertyChangedEvent(object __param0, int __param1)
{
ResultText.Text = "the event was fired and the result is " +
__param1.ToString();
}
Hinzufügen von mehreren Ereignislistenern für ein Ereignis
JavaScript besitzt eine addEventListener-Methode, die mehreren Handlern das Abonnieren eines einzelnen Ereignisses ermöglicht.
C++
public delegate void SomeHandler(Platform::String^ str);
public ref class LangSample sealed
{
public:
event SomeHandler^ someEvent;
property Platform::String^ PropertyA;
// Method that fires an event
void FireEvent(Platform::String^ str)
{
someEvent(Platform::String::Concat(str, PropertyA->ToString()));
}
//...
};
JavaScript
// Add two event handlers
var multicast1 = function (ev) {
document.getElementById('P11').innerHTML = "Handler 1: " + ev.target;
};
var multicast2 = function (ev) {
document.getElementById('P12').innerHTML = "Handler 2: " + ev.target;
};
var nativeObject = new CppComponent.LangSample();
//Subscribe to the same event
nativeObject.addEventListener("someevent", multicast1);
nativeObject.addEventListener("someevent", multicast2);
nativeObject.propertyA = "42";
// This method should fire an event
nativeObject.fireEvent("The answer is ");
.NET
In C# kann eine beliebige Anzahl von Ereignishandlern das Ereignis, wie im vorherigen Beispiel gezeigt, mithilfe des +=-Operators abonnieren.
Enumerationen
Eine Windows-Runtime-Enumeration in C++ wird mit einer public class enum deklariert. Das entspricht einer Enumeration mit Gültigkeitsbereich in Standard-C++.
C++
public enum class Direction {North, South, East, West};
public ref class EnumExampleClass sealed
{
public:
property Direction CurrentDirection
{
Direction get(){return m_direction; }
}
private:
Direction m_direction;
};
JavaScript
Enumerationswerte werden zwischen C++ und JavaScript als ganze Zahlen übergeben. Sie können ein JavaScript-Objekt, das die gleichen benannten Werte wie die C++-Enumeration enthält, optional deklarieren und es wie folgt verwenden.
var Direction = { 0: "North", 1: "South", 2: "East", 3: "West" };
//. . .
var nativeObject = new CppComponent.EnumExampleClass();
var curDirection = nativeObject.currentDirection;
document.getElementById('P13').innerHTML =
Direction[curDirection];
.NET
C# und Visual Basic verfügen über Sprachunterstützung für Enumerationen. In diesen Sprachen werden öffentliche Enumerationsklassen in C++ genauso betrachtet, wie eine .NET Framework-Enumeration.
Asynchrone Methoden
Um die asynchronen Methoden zu nutzen, die von anderen Windows-Runtime-Objekten verfügbar gemacht werden, verwenden Sie die task-Klasse (Concurrency Runtime). Weitere Informationen finden Sie unter Asychronous Programming in C++ und Aufgabenparallelität (Concurrency Runtime).
Verwenden Sie zur Implementierung von asynchronen Methoden in C++ die Funktion create_async, die in ppltasks.h definiert ist. Weitere Informationen finden Sie unter Erstellen von asynchronen Vorgängen in C++ für Windows Store-Apps. Ein Beispiel finden Sie unter Exemplarische Vorgehensweise: Erstellen einer grundlegenden Windows-Runtime-Komponente in C++ und Aufrufen dieser Komponente über JavaScript. .NET-Sprachen nutzen asynchrone C++-Methoden, genauso wie eine asynchrone Methode, die in .NET Framework definiert ist.
Ausnahmen
Sie können jeden Ausnahmetyp auslösen, der von Windows-Runtime definiert ist. Sie können keine benutzerdefinierten Typen von einem Windows-Runtime-Ausnahmetyp ableiten. Sie können jedoch eine COMException auslösen und ein benutzerdefiniertes HRESULT bereitstellen, auf das der Code, der die Ausnahme abfängt, zugreifen kann. Es gibt keine Möglichkeit, eine benutzerdefinierte Meldung in einer COMException anzugeben.
Tipps zum Debuggen
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, wählen Sie den JavaScript-Projektknoten unter Projektmappen-Explorer und dann Eigenschaften, Debugging, Debuggertyp aus.
Im Paket-Designer müssen die entsprechenden Funktionen ausgewählt sein. Wenn Sie beispielsweise versuchen, eine Datei mithilfe der Windows-Runtime-APIs zu öffnen, aktivieren Sie im Paket-Designer im Fenster Funktionen auf jeden Fall das Kontrollkästchen Dokumentbibliothek.
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 LogCalc-C++-Methode mit logCalc 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.
Siehe auch
Konzepte
Weitere Ressourcen
Roadmap for Windows Store apps using C++
Entwickeln des Reise-Optimierers von Bing Maps, einer Windows Store-App in JavaScript und C++