Tablica i WriteOnlyArray (C++/CX)

Można swobodnie używać zwykłych tablic w stylu C lub std::array w programie C++/CX (choć std::vector często jest lepszym wyborem), ale w każdym interfejsie API opublikowanym w metadanych należy przekonwertować tablicę w stylu C lub wektor na Platform::Array typ lub Platform::WriteOnlyArray w zależności od tego, jak jest używany. Typ Platform::Array nie jest tak wydajny, jak i tak zaawansowany, jak std::vector, więc ogólne wytyczne należy unikać jego użycia w kodzie wewnętrznym, który wykonuje wiele operacji na elementach tablicy.

W usłudze ABI można przekazać następujące typy tablic:

  1. const Platform::Array^

  2. Platform::Array^*

  3. Platform::WriteOnlyArray

  4. zwracana wartość Platform::Array^

Te typy tablic służą do implementowania trzech rodzajów wzorców tablicy zdefiniowanych przez środowisko wykonawcze systemu Windows.

PassArray
Używany, gdy obiekt wywołujący przekazuje tablicę do metody. Typ parametru wejściowego języka C++ to constPlatform::Array<T.>

FillArray
Używany, gdy obiekt wywołujący przekazuje tablicę, aby wypełnić metodę . Typ parametru wejściowego języka C++ to Platform::WriteOnlyArray<T>.

ReceiveArray
Używany, gdy obiekt wywołujący odbiera tablicę przydzielaną przez metodę. W języku C++/CX można zwrócić tablicę w zwracanej wartości jako Tablica^ lub zwrócić ją jako parametr wyjściowy jako typ Array^*.

Wzorzec PassArray

Gdy kod klienta przekazuje tablicę do metody C++ i metoda nie modyfikuje jej, metoda akceptuje tablicę const Array^jako . Na poziomie środowisko wykonawcze systemu Windows interfejsu binarnego aplikacji (ABI) jest to nazywane PassArray. W następnym przykładzie pokazano, jak przekazać tablicę przydzieloną w języku JavaScript do funkcji języka C++, która z niej odczytuje.

//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;
}

Poniższy fragment kodu przedstawia metodę C++:

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

Wzorzec ReceiveArray

We wzorcu ReceiveArray kod klienta deklaruje tablicę i przekazuje ją do metody, która przydziela pamięć i inicjuje ją. Typ parametru wejściowego języka C++ jest wskaźnikiem do kapelusza: Array<T>^*. W poniższym przykładzie pokazano, jak zadeklarować obiekt tablicy w języku JavaScript i przekazać go do funkcji języka C++, która przydziela pamięć, inicjuje elementy i zwraca ją do języka JavaScript. Język JavaScript traktuje przydzieloną tablicę jako wartość zwracaną, ale funkcja języka C++ traktuje ją jako parametr wyjściowy.

//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] + " ";
    }
}

Poniższy fragment kodu przedstawia dwa sposoby implementowania metody C++:


// 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;
}

Wypełnianie tablic

Jeśli chcesz przydzielić tablicę w obiekcie wywołującym i zainicjować lub zmodyfikować ją w obiekcie wywoływanym, użyj polecenia WriteOnlyArray. W następnym przykładzie pokazano, jak zaimplementować funkcję języka C++, która używa WriteOnlyArray i wywołuje ją z poziomu języka 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] + " ";
    }
}

Poniższy fragment kodu pokazuje, jak zaimplementować metodę języka C++:

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

Konwersje tablic

W tym przykładzie pokazano, jak używać obiektu Platform::Array do konstruowania innych rodzajów kolekcji:

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

W następnym przykładzie pokazano, jak utworzyć tablicę Platform::Array w stylu C i zwrócić ją z metody publicznej.

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

Tablice postrzępione

System typów środowisko wykonawcze systemu Windows nie obsługuje koncepcji tablic postrzępionych i dlatego nie można użyć IVector<Platform::Array<T>> jako wartości zwracanej lub parametru metody w metodzie publicznej. Aby przekazać tablicę postrzępionych lub sekwencję sekwencji w usłudze ABI, użyj polecenia IVector<IVector<T>^>.

Użyj funkcji ArrayReference, aby uniknąć kopiowania danych

W niektórych scenariuszach, w których dane są przekazywane przez usługę Platform::ArrayABI do klasy , i ostatecznie chcesz przetwarzać te dane w tablicy w stylu C w celu zapewnienia wydajności, możesz użyć metody Platform::ArrayReference , aby uniknąć dodatkowej operacji kopiowania. Po przekazaniu argumentu Platform::ArrayReference jako do parametru, który przyjmuje Platform::Arrayparametr , ArrayReference dane będą przechowywane bezpośrednio w określonej tablicy w stylu C. Należy pamiętać, że ArrayReference nie ma blokady danych źródłowych, więc jeśli dane są modyfikowane lub usuwane w innym wątku przed zakończeniem wywołania, wyniki będą niezdefiniowane.

Poniższy fragment kodu pokazuje, jak skopiować wyniki DataReader operacji do Platform::Array (zwykły wzorzec), a następnie zastąpić ArrayReference skopiowanie danych bezpośrednio do tablicy w stylu C:

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

Unikaj uwidaczniania tablicy jako właściwości

Ogólnie rzecz biorąc, należy unikać uwidaczniania Platform::Array typu jako właściwości w klasie ref, ponieważ cała tablica jest zwracana nawet wtedy, gdy kod klienta próbuje uzyskać dostęp tylko do jednego elementu. Jeśli konieczne jest uwidocznienie kontenera sekwencji jako właściwości w klasie publicznej ref, Windows::Foundation::IVector jest lepszym wyborem. W prywatnych lub wewnętrznych interfejsach API (które nie są publikowane w metadanych), rozważ użycie standardowego kontenera języka C++, takiego jak std::vector.

Zobacz też

System typów
Dokumentacja języka C++/CX
Dokumentacja przestrzeni nazw