Array e WriteOnlyArray (C++/CX)
È possibile usare liberamente matrici di tipo C o std::array
in un programma C++/CX (anche se std::vector
spesso è una scelta migliore), ma in qualsiasi API pubblicata nei metadati, è necessario convertire una matrice o un vettore di tipo C in un Platform::Array
tipo o Platform::WriteOnlyArray
a seconda della modalità di utilizzo. Il Platform::Array
tipo non è così efficiente né potente come std::vector
, quindi è consigliabile evitare l'uso nel codice interno che esegue molte operazioni sugli elementi della matrice.
I seguenti tipi di matrice possono essere passati attraverso l'ABI:
const Platform::Array^
Platform::Array^*
Platform::WriteOnlyArray
valore restituito di
Platform::Array^
Questi tipi di matrice vengono usati per implementare i tre tipi di modelli di matrice definiti da Windows Runtime.
PassArray
Utilizzato quando il chiamante passa una matrice a un metodo. Il tipo di parametro di input C++ è const
Platform::Array
<T.>
FillArray
Utilizzato quando il chiamante passa una matrice per il metodo da riempire. Il tipo di parametro di input C++ è Platform::WriteOnlyArray
<T>.
ReceiveArray
Utilizzato quando il chiamante riceve una matrice che il metodo alloca. In C++/CX è possibile restituire la matrice nel valore restituito come Array^ oppure come parametro out come tipo Array^*.
Modello PassArray
Quando il codice client passa una matrice a un metodo C++ e il metodo non lo modifica, il metodo accetta la matrice come .const Array^
A livello di ABI (Application Binary Interface) di Windows Runtime, questa operazione è nota come PassArray. Nell'esempio riportato di seguito viene illustrato come passare una matrice allocata in JavaScript a una funzione di C++ che la legge.
//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;
}
Nel frammento riportato di seguito viene mostrato il metodo 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;
}
Modello ReceiveArray
Nel modello ReceiveArray il codice client dichiara una matrice e lo passa a un metodo che alloca la memoria per essa e la inizializza. Il tipo di parametro di input C++ è un puntatore a hat: Array<T>^*
. Nell'esempio riportato di seguito viene illustrato come dichiarare un oggetto matrice in JavaScript e passarlo a una funzione di C++ che alloca la memoria, inizializza gli elementi e lo restituisce al linguaggio JavaScript. JavaScript tratta la matrice allocata come un valore restituito, mentre la funzione di C++ la tratta come un parametro out.
//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] + " ";
}
}
Nel frammento riportato di seguito vengono illustrati due modi per implementare il metodo 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;
}
Matrici di riempimento
Per allocare una matrice nel chiamante e inizializzarla o modificarla nel destinatario della chiamata, utilizza WriteOnlyArray
. Nell'esempio riportato di seguito viene illustrato come implementare una funzione di C++ che utilizza l'oggetto WriteOnlyArray
e lo chiama da 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] + " ";
}
}
Nel frammento riportato di seguito viene mostrato come implementare il metodo 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;
}
}
Conversioni di matrice
In questo esempio viene illustrato come usare un Platform::Array
oggetto per costruire altri tipi di raccolte:
#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);
}
}
Nell'esempio seguente viene illustrato come costruire un oggetto Platform::Array
da una matrice di tipo C e restituirlo da un metodo pubblico.
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);
}
Matrici di matrici
Il sistema di tipi di Windows Runtime non supporta il concetto di matrici di matrici, pertanto non puoi passare IVector<Platform::Array<T>>
come valore restituito o parametro di metodo in un metodo pubblico. Per passare una matrice di matrici o una sequenza di sequenze attraverso l'interfaccia applicativa binaria (ABI), usa IVector<IVector<T>^>
.
Utilizza ArrayReference per evitare di copiare i dati
In alcuni scenari in cui i dati vengono passati attraverso l'interfaccia ABI in un Platform::Array
oggetto e si vuole elaborare i dati in una matrice in stile C per ottenere efficienza, è possibile usare Platform::ArrayReference per evitare l'operazione di copia aggiuntiva. Quando si passa un oggetto Platform::ArrayReference
come argomento a un parametro che accetta un Platform::Array
oggetto , ArrayReference
i dati verranno archiviati direttamente in una matrice in stile C specificata. Tieni presente che ArrayReference
non ha alcun blocco sui dati di origine. Pertanto, se tali dati vengono modificati o eliminati in un altro thread prima del completamento della chiamata, i risultati saranno non definiti.
Il frammento di codice seguente illustra come copiare i risultati di un'operazione DataReader
in un Platform::Array
(modello consueto) e quindi come sostituire ArrayReference
per copiare i dati direttamente in una matrice in stile 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) );
}
};
Evitare di esporre una matrice come proprietà
In generale, evita di esporre un tipo Platform::Array
come proprietà in una classe di riferimento poiché l'intera matrice viene restituita anche quando il codice client tenta semplicemente di accedere a un singolo elemento. Quando è necessario esporre un contenitore di sequenza come proprietà in una classe di riferimento pubblica, Windows::Foundation::IVector
è una scelta migliore. Nelle API private o interne (che non vengono pubblicate nei metadati), prendere in considerazione l'uso di un contenitore C++ standard, ad std::vector
esempio .
Vedi anche
Sistema di tipi
Riferimenti al linguaggio C++/CX
Riferimenti a spazi dei nomi