Array et WriteOnlyArray (C++/CX)
Vous pouvez librement utiliser des tableaux de style C ou std::array
dans un programme C++/CX (bien que ce soit std::vector
souvent un meilleur choix), mais dans toute API publiée dans les métadonnées, vous devez convertir un tableau ou un vecteur de style C en un type Platform::Array
ou Platform::WriteOnlyArray
un autre, en fonction de la manière dont il est utilisé. Le type Platform::Array
n’est pas aussi efficace ni aussi puissant que le type std::vector
, donc en règle générale, vous devez éviter de l’utiliser dans le code interne qui exécute un grand nombre d’opérations sur les éléments de tableau.
Les types de tableau suivants peuvent être passés à travers l'ABI :
const Platform::Array^
Platform::Array^*
Platform::WriteOnlyArray
valeur de retour de
Platform::Array^
Utilisez ces types de tableau 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 const
Platform::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 passe un tableau à une méthode C++ et que la méthode ne le modifie pas, la méthode accepte le tableau comme un const Array^
. Au niveau de l’interface binaire d’application (ABI) Windows Runtime (ABI), cela s’appelle 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 passe à une méthode qui lui alloue de la mémoire et l’initialise. Le type de paramètre d’entrée C++ est un pointeur 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
L’exemple ci-dessous montre comment utiliser un objet 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 ci-dessous montre comment construire un objet Platform::Array
à partir d’un 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 où vous voulez finalement traiter ces données dans un tableau de style C pour plus d’efficacité, vous pouvez utiliser Platform::ArrayReference pour éviter l’opération de copie supplémentaire. Lorsque vous passez un type Platform::ArrayReference
comme argument à un paramètre qui accepte un Platform::Array
, le 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 opération DataReader
dans un Platform::Array
(le modèle habituel), puis comment substituer ArrayReference
pour copier les 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. Quand vous devez exposer un conteneur de séquence en tant que propriété dans une classe ref publique, choisissez plutôt Windows::Foundation::IVector
. Dans les API privées ou internes (qui ne sont pas publiées en métadonnées), envisagez d’utiliser un conteneur C++ standard tel que le type 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