Windows-Apps
Inhaltsverzeichnis reduzieren
Inhaltsverzeichnis erweitern

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 8.x 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 Erstellen eines Software Development Kits.

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).

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.

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();

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. Wenden Sie das [WebHostHidden]-Attribut auf C++-Typen an, die in JavaScript nicht sichtbar sein sollen.

Alle öffentlichen Klassen müssen sich im gleichen Stammnamespace befinden, dessen Name dem Namen der Komponentenmetadatendatei gleicht. Zum Beispiel kann eine Klasse namens A.B.C.MyClass nur instanziiert werden, wenn sie in einer Metadatendatei definiert ist, die A.winmd oder A.B.winmd oder A.B.C.winmd heißt. Der Name der DLL muss nicht mit dem Namen der WINMD-Datei übereinstimmen.

Der Clientcode erstellt eine Instanz der Komponente unter Verwendung 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 (NOTINBUILD) 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).

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;

Eine Wertstruktur ist ein schlichtes Datenobjekt, das Felder enthalten kann, die standardmäßig öffentlich sind. Eine Wertstruktur wird per 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();
}

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);

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.

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 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).

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();
    }
}

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();
}

Eine öffentliche Verweisklasse in Komponentenerweiterungen für Visual C++ macht öffentliche Datenmember mithilfe des property-Schlüsselworts als 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 PropertyA 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;

}

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.

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();
}

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.

Eine Windows-Runtime-Enumeration in C++ wird mit einer öffentlichen Enumerationsklasse 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.

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 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 oder C#. .NET-Sprachen nutzen asynchrone C++-Methoden, genauso wie eine asynchrone Methode, die in .NET Framework definiert ist.

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.

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 mit den Windows-Runtime-APIs eine Bilddatei in der Bildbibliothek des Benutzers öffnen möchten, müssen Sie im Paket-Designer im Bereich Funktionen das Kontrollkästchen Bildbibliothek aktivieren.

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.

Anzeigen:
© 2016 Microsoft