Array et WriteOnlyArray (C++/CX)

Vous pouvez utiliser librement des tableaux de style C standard ou std::array dans un programme C++/CX (bien qu’il std::vector soit souvent préférable), mais dans toute API publiée dans les métadonnées, vous devez convertir un tableau ou un vecteur de style C en un ou Platform::WriteOnlyArray un Platform::Array type selon la façon dont il est utilisé. Le Platform::Array type n’est ni aussi efficace ni aussi puissant que std::vector, de sorte que comme une directive générale, vous devez éviter son utilisation dans le code interne qui effectue de nombreuses opérations sur les éléments de tableau.

Les types de tableau suivants peuvent être passés à travers l'ABI :

  1. const Platform::Array^

  2. Platform::Array^*

  3. Platform::WriteOnlyArray

  4. valeur de retour de Platform::Array^

Vous utilisez ces types de tableaux pour implémenter les trois types de modèles de tableau définis par Windows Runtime.

PassArray
Utilisé lorsque l'appelant passe un tableau à une méthode. Le type de paramètre d’entrée C++ est constPlatform::Array<T.>

FillArray
Utilisé lorsque l'appelant passe un tableau à remplir par la méthode. Le type de paramètre d’entrée C++ est Platform::WriteOnlyArray<T>.

ReceiveArray
Utilisé lorsque l'appelant reçoit un tableau que la méthode alloue. En langage C++/CX, vous pouvez retourner un tableau en valeur de retour comme un Array^, ou vous pouvez le retourner comme paramètre de sortie de type Array^*.

Modèle PassArray

Lorsque le code client transmet un tableau à une méthode C++ et que la méthode ne la modifie pas, la méthode accepte le tableau en tant que const Array^. Au niveau de l’interface binaire d’application Windows Runtime (ABI), il s’agit d’un PassArray. L'exemple ci-dessous montre comment passer un tableau alloué en JavaScript à la fonction C++ qui le lit.

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

L'extrait de code suivant illustre la méthode 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;
}

Modèle ReceiveArray

Dans le modèle ReceiveArray, le code client déclare un tableau et le transmet à une méthode qui alloue la mémoire pour elle et l’initialise. Le type de paramètre d’entrée C++ est un pointeur vers chapeau : Array<T>^*. L'exemple suivant indique comment déclarer un objet tableau dans JavaScript et le passer à une fonction C++ qui alloue de la mémoire, initialise les éléments et le retourne à JavaScript. JavaScript traite le tableau alloué comme une valeur de retour, mais la fonction C++ le traite comme un paramètre de sortie.

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

L'extrait de code suivant montre deux façons d'implémenter la méthode 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;
}

Remplir les tableaux

Lorsque vous souhaitez allouer un tableau dans l'appelant et l'initialiser ou le modifier dans l'appelé, utilisez WriteOnlyArray. L'exemple ci-dessous indique comment implémenter une fonction c++ qui utilise WriteOnlyArray et l'appelle à partir de 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] + " ";
    }
}

L'extrait de code suivant montre comment implémenter la méthode 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;
    }   
}

Conversions de tableau

Cet exemple montre comment utiliser un Platform::Array pour construire d’autres types de collections :

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

L’exemple suivant montre comment construire un Platform::Array tableau de style C et le retourner à partir d’une méthode publique.

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

Tableaux en escalier

Le système de types Windows Runtime ne prend pas en charge le concept des tableaux en escalier et vous ne pouvez pas donc pas utiliser IVector<Platform::Array<T>> comme valeur de retour ou paramètre de méthode dans une méthode publique. Pour passer un tableau en escalier ou une séquence de séquences à travers l'ABI, utilisez IVector<IVector<T>^>.

Utilisez le type ArrayReference pour éviter de copier les données.

Dans certains scénarios où les données sont passées à travers l’ABI dans un Platform::Array, et que vous souhaitez finalement traiter ces données dans un tableau de style C pour une efficacité, vous pouvez utiliser Platform ::ArrayReference pour éviter l’opération de copie supplémentaire. Lorsque vous passez un Platform::ArrayReference argument à un paramètre qui prend un Platform::Array, il ArrayReference stocke les données directement dans un tableau de style C que vous spécifiez. Gardez à l'esprit que le type ArrayReference ne peut effectuer aucun verrouillage sur les données sources. Ainsi, si ces données sont modifiées ou supprimées sur un autre thread avant l'appel, les résultats seront non définis.

L’extrait de code suivant montre comment copier les résultats d’une DataReader opération dans un Platform::Array (modèle habituel), puis comment remplacer ArrayReference la copie des données directement dans un tableau de style 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) );
    }
};

Évitez d'exposer un tableau comme propriété

En général, vous devez éviter d'exposer un type Platform::Array en tant que propriété dans une classe ref, car le tableau entier est retourné même si le code client tente uniquement d'accéder à un seul élément. Lorsque vous devez exposer un conteneur de séquences en tant que propriété dans une classe ref publique, Windows::Foundation::IVector il est préférable de choisir. Dans les API privées ou internes (qui ne sont pas publiées dans les métadonnées), envisagez d’utiliser un conteneur C++ standard tel que std::vector.

Voir aussi

Système de type
Informations de référence sur le langage C++/CX
Référence aux espaces de noms