Sdílet prostřednictvím


Pole a WriteOnlyArray (C++/CX)

V programu C++/CX můžete volně používat běžná pole std::array ve stylu jazyka C++/CX (i když std::vector je to často lepší volba), ale v libovolném rozhraní API, které je publikováno v metadatech, je nutné převést pole nebo vektor ve stylu jazyka C na Platform::Array typ v Platform::WriteOnlyArray závislosti na tom, jak se používá. Typ Platform::Array není tak efektivní ani tak výkonný jako std::vector, takže jako obecné vodítko byste se měli vyhnout jeho použití v interním kódu, který provádí velké množství operací s prvky pole.

Mezi ABI je možné předat následující typy polí:

  1. const Platform::Array^

  2. Platform::Array^*

  3. Platform::WriteOnlyArray

  4. návratová hodnota Platform::Array^

Tyto typy polí použijete k implementaci tří druhů vzorů polí, které jsou definovány prostředí Windows Runtime.

PassArray
Používá se, když volající předá matici metodě. Typ vstupního parametru jazyka C++ je const Platform::Array<T.>

FillArray
Používá se, když volající předá pole pro metodu, která se má vyplnit. Typ vstupního parametru jazyka C++ je Platform::WriteOnlyArray<T>.

ReceiveArray
Používá se, když volající obdrží pole, které metoda přidělí. V jazyce C++/CX můžete vrátit matici ve návratové hodnotě jako Array^ nebo ji můžete vrátit jako výstupní parametr jako typ Array^*.

Model PassArray

Když klientský kód předá pole do metody C++ a metoda ho nezmění, metoda přijme pole jako const Array^. Na úrovni prostředí Windows Runtime binárního rozhraní aplikace (ABI) se označuje jako PassArray. Další příklad ukazuje, jak předat pole přidělené v JavaScriptu funkci C++, která z ní čte.

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

Následující fragment kódu ukazuje metodu 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;
}

Model ReceiveArray

V modelu ReceiveArray kód klienta deklaruje pole a předá ho metodě, která přidělí paměť pro ni a inicializuje ji. Typ vstupního parametru jazyka C++ je ukazatel na hat: Array<T>^*. Následující příklad ukazuje, jak deklarovat objekt pole v JavaScriptu a předat ho funkci C++, která přidělí paměť, inicializuje prvky a vrátí ho do JavaScriptu. JavaScript považuje přidělené pole za návratovou hodnotu, ale funkce jazyka C++ s ním pracuje jako s výstupním parametrem.

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

Následující fragment kódu ukazuje dva způsoby implementace 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;
}

Vyplnění polí

Pokud chcete přidělit pole v volajícím a inicializovat nebo upravit volaný, použijte WriteOnlyArray. Následující příklad ukazuje, jak implementovat funkci C++, která ji používá WriteOnlyArray a volat z JavaScriptu.

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

Následující fragment kódu ukazuje, jak implementovat metodu 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;
    }   
}

Převody polí

Tento příklad ukazuje, jak použít Platform::Array k vytvoření dalších druhů kolekcí:

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

Další příklad ukazuje, jak vytvořit z pole ve stylu jazyka Platform::Array C a vrátit ho z veřejné metody.

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

Jagged arrays

Systém typů prostředí Windows Runtime nepodporuje koncept agregovaných polí, a proto nelze použít IVector<Platform::Array<T>> jako návratovou hodnotu nebo parametr metody ve veřejné metodě. Pokud chcete předat agregované pole nebo posloupnost sekvencí napříč ABI, použijte IVector<IVector<T>^>.

Použití ArrayReference k zabránění kopírování dat

V některých scénářích, kdy se data předávají přes ABI do ABI Platform::Array, a v konečném důsledku chcete tato data zpracovat v poli stylu jazyka C kvůli efektivitě, můžete použít platformu::ArrayReference , abyste zabránili další operaci kopírování. Když předáte Platform::ArrayReference jako argument parametru, který přebírá Platform::Arrayhodnotu , ArrayReference uloží data přímo do zadaného pole ve stylu jazyka C. Jen mějte na paměti, že ArrayReference nemá žádný zámek na zdrojových datech, takže pokud jsou data upravena nebo odstraněna v jiném vlákně před dokončením volání, výsledky nebudou definovány.

Následující fragment kódu ukazuje, jak zkopírovat výsledky DataReader operace do Platform::Array (obvyklého vzoru) a jak pak nahradit ArrayReference kopírování dat přímo do pole ve stylu jazyka 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) );
    }
};

Vyhněte se zveřejnění pole jako vlastnosti

Obecně platí, že byste se měli vyhnout zveřejnění Platform::Array typu jako vlastnosti v ref třídě, protože celé pole je vráceno, i když se klientský kód pokouší získat přístup pouze k jednomu prvku. Pokud potřebujete zveřejnit kontejner sekvence jako vlastnost ve veřejné třídě ref, Windows::Foundation::IVector je lepší volbou. V privátních nebo interních rozhraních API (která nejsou publikovaná do metadat) zvažte použití standardního kontejneru jazyka C++, například std::vector.

Viz také

Systém typů
Referenční zdroje k jazyku C++/CX
Referenční informace o oborech názvů