Matriz e WriteOnlyArray (C++/CX)
Você pode usar livremente matrizes regulares de estilo C ou std::array
em um programa em C++/CX (embora std::vector
muitas vezes seja uma opção melhor), mas em qualquer API publicada nos metadados, você deverá converter uma matriz ou um vetor C-style em um tipo Platform::Array
ou Platform::WriteOnlyArray
, dependendo de como ele estiver sendo usado. O tipo Platform::Array
não é tão eficiente nem tão poderoso quanto std::vector
, assim, como uma diretriz geral, você deve evitar seu uso no código interno que executa muitas operações nos elementos da matriz.
Os seguintes tipos de matriz podem ser passados pela ABI:
const Platform::Array^
Platform::Array^*
Platform::WriteOnlyArray
valor de retorno de
Platform::Array^
Use esses tipos de matrizes para implementar os três tipos de padrões de matrizes que são definidos pelo Windows Runtime.
PassArray
Usada quando o chamador passa uma matriz a um método. O tipo de parâmetro de entrada de dados em C++ é const
Platform::Array
<T>.
FillArray
Usada quando o chamador passa uma matriz ao método para preenchimento. O tipo de parâmetro de entrada em C++ é Platform::WriteOnlyArray
<T>.
ReceiveArray
Usada quando o chamador recebe uma matriz que o método aloca. No C++/CX, é possível retornar a matriz no valor de retorno como um Array^ ou retorná-la o como um parâmetro de saída como o tipo Array^*.
Padrão de PassArray
Quando o código do cliente passa uma matriz para um método do C++ e o método não a modifica, o método aceita a matriz como const Array^
. No nível da ABI (interface binária de aplicativo) do Windows Runtime, isso é conhecido como PassArray. O exemplo a seguir mostra como passar uma matriz alocada em JavaScript a uma função C++ que lê dela.
//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;
}
O snippet a seguir mostra o método do 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;
}
Padrão ReceiveArray
No padrão ReceiveArray, o código do cliente declara uma matriz e a passa a um método que aloca a memória para ela e a inicializa. O tipo de parâmetro de entrada C++ é um ponteiro para hat: Array<T>^*
. O exemplo a seguir mostra como declarar um objeto de matriz em JavaScript e passá-lo a uma função C++ que aloca a memória, inicializa os elementos e o retorna ao JavaScript. O JavaScript trata a matriz alocada como um valor de retorno, mas a função C++ a trata como um parâmetro de saída.
//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] + " ";
}
}
O snippet a seguir mostra duas maneiras de implementar o método do 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;
}
Matrizes de preenchimento
Quando você deseja alocar uma matriz no chamador e inicializá-la ou modificá-la no chamado, use WriteOnlyArray
. O exemplo a seguir mostra como implementar uma função C++ que usa WriteOnlyArray
e a chama do 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] + " ";
}
}
O snippet a seguir mostra como implementar o método do 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;
}
}
Conversões de matriz
Este exemplo mostra como usar um Platform::Array
para construir outros tipos de coleções:
#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);
}
}
O exemplo a seguir mostra como construir um Platform::Array
a partir de uma matriz C-style e retorná-lo de um método público.
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);
}
Matrizes denteadas
O sistema de tipos do Windows Runtime não oferece suporte ao conceito de matrizes denteadas e, portanto, você não pode usar IVector<Platform::Array<T>>
como um valor de retorno ou parâmetro de método em um método público. Para passar uma matriz denteada ou uma sequência de sequências através da ABI, use IVector<IVector<T>^>
.
Usar ArrayReference para evitar a cópia de dados
Em alguns cenários onde os dados estiverem sendo passados pela ABI para um Platform::Array
e você, por fim, desejar processar esses dados em uma matriz C-style para obter eficiência, poderá usar Platform::ArrayReference para evitar a operação de cópia extra. Quando você passar um Platform::ArrayReference
como um argumento para um parâmetro que usa um Platform::Array
, o ArrayReference
armazenará os dados diretamente em uma matriz C-style especificada por você. Apenas esteja ciente de que ArrayReference
não tem nenhum bloqueio nos dados de origem, portanto, se esses dados forem modificados ou excluídos em outro thread antes de a chamada ser concluída, os resultados serão indefinidos.
O seguinte snippet de código mostra como copiar os resultados de uma operação DataReader
em um Platform::Array
(o padrão comum) e como substituir ArrayReference
para copiar os dados diretamente em uma matriz C-style:
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) );
}
};
Evitar a exposição de uma matriz como uma propriedade
Em geral, você deve evitar expor um tipo Platform::Array
como uma propriedade em uma classe ref, pois a matriz inteira será retornada mesmo quando o código do cliente estiver apenas tentando acessar um único elemento. Quando você precisar expor um contêiner de sequências como uma propriedade em uma classe ref pública, Windows::Foundation::IVector
será uma opção melhor. Em APIs privadas ou internas (que não são publicadas nos metadados), pense na possibilidade de usar um contêiner padrão do C++, como std::vector
.
Confira também
Sistema de tipos
Referência da linguagem C++/CX
Referência de namespaces