Delen via


Matrix en WriteOnlyArray (C++/CX)

U kunt vrijelijk reguliere C-achtige matrices of std::array in een C++/CX-programma gebruiken (hoewel std::vector dit vaak een betere keuze is), maar in elke API die wordt gepubliceerd in metagegevens, moet u een C-stijlmatrix of vector converteren naar een Platform::Array of Platform::WriteOnlyArray type, afhankelijk van hoe deze wordt gebruikt. Het Platform::Array type is niet zo efficiënt als zo krachtig als std::vector, dus als een algemene richtlijn moet u het gebruik ervan vermijden in interne code die veel bewerkingen op de matrixelementen uitvoert.

De volgende matrixtypen kunnen worden doorgegeven aan de ABI:

  1. const Platform::Array^

  2. Platform::Array^*

  3. Platform::WriteOnlyArray

  4. retourwaarde van Platform::Array^

U gebruikt deze matrixtypen om de drie soorten matrixpatronen te implementeren die zijn gedefinieerd door De Windows Runtime.

PassArray
Wordt gebruikt wanneer de aanroeper een matrix doorgeeft aan een methode. Het invoerparametertype C++ is constPlatform::Array<T.>

FillArray
Wordt gebruikt wanneer de aanroeper een matrix doorgeeft voor de methode die moet worden ingevuld. Het invoerparametertype C++ is Platform::WriteOnlyArray<T>.

ReceiveArray
Wordt gebruikt wanneer de aanroeper een matrix ontvangt die door de methode wordt toegewezen. In C++/CX kunt u de matrix in de retourwaarde retourneren als matrix^ of als een outparameter als type Matrix^*.

PassArray-patroon

Wanneer clientcode een matrix doorgeeft aan een C++-methode en de methode deze niet wijzigt, accepteert de methode de matrix als een const Array^. Op het niveau van de binaire interface (ABI) van de Windows Runtime-toepassing wordt dit een PassArray genoemd. In het volgende voorbeeld ziet u hoe u een matrix doorgeeft die in JavaScript is toegewezen aan een C++-functie die uit deze functie leest.

//JavaScript
function button2_click() {
    var obj = new JS-Array.Class1();
    var a = new Array(100);
    for (i = 0; i < 100; i++) {
        a[i] = i;
    }
    // Notice that method names are camelCased in JavaScript.
    var sum = obj.passArrayForReading(a);
    document.getElementById('results').innerText
        = "The sum of all the numbers is " + sum;
}

In het volgende codefragment ziet u de C++-methode:

double Class1::PassArrayForReading(const Array<double>^ arr)
{
    double sum = 0;
    for(unsigned int i = 0 ; i < arr->Length; i++)
    {
        sum += arr[i];
    }
    return sum;
}

ReceiveArray-patroon

In het ReceiveArray-patroon declareert de clientcode een matrix en geeft deze door aan een methode waarmee het geheugen wordt toegewezen en geïnitialiseerd. Het invoerparametertype C++ is een pointer-to-hat: Array<T>^*. In het volgende voorbeeld ziet u hoe u een matrixobject in JavaScript declareert en doorgeeft aan een C++-functie die het geheugen toewijst, de elementen initialiseert en retourneert naar JavaScript. JavaScript behandelt de toegewezen matrix als een retourwaarde, maar de C++-functie behandelt deze als een outparameter.

//JavaScript
function button3_click() {
    var obj = new JS-Array.Class1();

    // Remember to use camelCase for the function name.
    var array2 = obj.calleeAllocatedDemo2();
    for (j = 0; j < array2.length; j++) {
        document.getElementById('results').innerText += array2[j] + " ";
    }
}

In het volgende codefragment ziet u twee manieren om de C++-methode te implementeren:


// Return array as out parameter...
void Class1::CalleeAllocatedDemo(Array<int>^* arr)
{
    auto temp = ref new Array<int>(10);
    for(unsigned int i = 0; i < temp->Length; i++)
    {
        temp[i] = i;
    }

    *arr = temp;
}

// ...or return array as return value:
Array<int>^ Class1::CalleeAllocatedDemo2()
{
    auto temp = ref new Array<int>(10);    
    for(unsigned int i = 0; i < temp->Length; i++)
    {
        temp[i] = i;
    }

    return temp;
}

Matrices doorvoeren

Als u een matrix in de aanroeper wilt toewijzen en deze in de aanroep wilt initialiseren of wijzigen, gebruikt u WriteOnlyArray. In het volgende voorbeeld ziet u hoe u een C++-functie implementeert die deze gebruikt WriteOnlyArray en aanroept vanuit JavaScript.

// JavaScript
function button4_click() {
    var obj = new JS-Array.Class1();
    //Allocate the array.
    var a = new Array(10);

    //Pass the array to C++.
    obj.callerAllocatedDemo(a);

    var results = document.getElementById('results');
    // Display the modified contents.
    for (i = 0; i < 10; i++) {
        document.getElementById('results').innerText += a[i] + " ";
    }
}

In het volgende codefragment ziet u hoe u de C++-methode implementeert:

void Class1::CallerAllocatedDemo(Platform::WriteOnlyArray<int>^ arr)
{
    // You can write to the elements directly.
    for(unsigned int i = 0; i < arr->Length; i++)
    {
        arr[i] = i;
    }   
}

Matrixconversies

In dit voorbeeld ziet u hoe u een Platform::Array verzameling kunt gebruiken om andere soorten verzamelingen samen te stellen:

#include <vector>
#include <collection.h>
using namespace Platform;
using namespace std;
using namespace Platform::Collections;

void ArrayConversions(const Array<int>^ arr)
{
    // Construct an Array from another Array.
    Platform::Array<int>^ newArr = ref new Platform::Array<int>(arr);

    // Construct a Vector from an Array
    auto v = ref new Platform::Collections::Vector<int>(arr); 

    // Construct a std::vector. Two options.
    vector<int> v1(begin(arr), end(arr));
    vector<int> v2(arr->begin(), arr->end());

    // Initialize a vector one element at a time.
    // using a range for loop. Not as efficient as using begin/end.
    vector<int> v3;
    for(int i : arr)
    {
        v3.push_back(i);
    }   
}

In het volgende voorbeeld ziet u hoe u een matrix Platform::Array in C-stijl maakt en retourneert op basis van een openbare methode.

Array<int>^ GetNums()
{
    int nums[] = {0,1,2,3,4};
    //Use nums internally....

    // Convert to Platform::Array and return to caller.
    return ref new Array<int>(nums, 5);
}

Getrapte arrays

Het Windows Runtime-typesysteem biedt geen ondersteuning voor het concept van gelabelde matrices en u kunt daarom niet gebruiken IVector<Platform::Array<T>> als retourwaarde of methodeparameter in een openbare methode. Als u een gekartelde array of een sequentie van sequenties wilt doorgeven aan de ABI, gebruikt u IVector<IVector<T>^>.

ArrayReference gebruiken om te voorkomen dat gegevens worden gekopieerd

In sommige scenario's waarin gegevens worden doorgegeven aan de ABI in een Platform::Array, en u die gegevens uiteindelijk wilt verwerken in een C-stijlmatrix voor efficiëntie, kunt u Platform::ArrayReference gebruiken om de extra kopieerbewerking te voorkomen. Wanneer u een Platform::ArrayReference als argument doorgeeft aan een parameter die een Platform::Arraygebruikt, ArrayReference worden de gegevens rechtstreeks opgeslagen in een C-stijlmatrix die u opgeeft. Houd er rekening mee dat ArrayReference de brongegevens niet zijn vergrendeld, dus als deze gegevens worden gewijzigd of verwijderd in een andere thread voordat de aanroep is voltooid, worden de resultaten niet gedefinieerd.

In het volgende codefragment ziet u hoe u de resultaten van een DataReader bewerking kopieert naar een Platform::Array (het gebruikelijke patroon) en hoe u de gegevens vervolgens ArrayReference rechtstreeks naar een C-stijlmatrix kopieert:

public ref class TestReferenceArray sealed
{
public:

    // Assume dr is already initialized with a stream
    void GetArray(Windows::Storage::Streams::DataReader^ dr, int numBytesRemaining)
    {
        // Copy into Platform::Array
        auto bytes = ref new Platform::Array<unsigned char>(numBytesRemaining);            

        // Fill an Array.
        dr->ReadBytes(bytes);

        // Fill a C-style array
        uint8 data[1024];
        dr->ReadBytes( Platform::ArrayReference<uint8>(data, 1024) );
    }
};

Vermijd het weergeven van een matrix als een eigenschap

Over het algemeen moet u voorkomen dat een Platform::Array type als een eigenschap in een verw-klasse wordt weergegeven, omdat de hele matrix wordt geretourneerd, zelfs wanneer clientcode alleen toegang probeert te krijgen tot één element. Wanneer u een reekscontainer als een eigenschap in een openbare verw-klasse wilt weergeven, Windows::Foundation::IVector is dit een betere keuze. In privé- of interne API's (die niet naar metagegevens worden gepubliceerd), kunt u overwegen om een standaard C++-container zoals std::vector.

Zie ook

Typesysteem
Naslaginformatie over C++/CX-taal
Naslaginformatie over naamruimten