Классы Array и WriteOnlyArray (C++/CX)

Вы можете свободно использовать обычные массивы стилей C или std::array в программе C++/CX (хотя std::vector это часто лучший выбор), но в любом API, опубликованном в метаданных, необходимо преобразовать массив стилей C или Platform::WriteOnlyArray вектор в тип Platform::Array в зависимости от того, как он используется. Platform::Array Тип не является столь эффективным или std::vectorмощным, как и общий руководящий принцип, поэтому следует избежать его использования в внутреннем коде, который выполняет множество операций с элементами массива.

Следующие типы массивов могут передаваться через ABI:

  1. const Platform::Array^

  2. Platform::Array^*

  3. Platform::WriteOnlyArray

  4. возвращаемое значение Platform::Array^

Эти типы массивов используются для реализации трех типов шаблонов массивов, определенных среда выполнения Windows.

PassArray
Используется, когда вызывающий объект передает массив методу. Тип входного параметра C++ — constPlatform::Array<T>.

FillArray
Используется, когда вызывающий объект передает массив методу для заполнения. Тип входного параметра C++ — Platform::WriteOnlyArray<T>.

ReceiveArray
Используется, когда вызывающий объект получает массив, выделяемый методом. В C++/CX массив можно вернуть в возвращаемом значении в виде Array^ или в качестве выходного параметра типа Array^*.

Шаблон PassArray

Когда клиентский код передает массив методу C++ и метод не изменяет его, метод принимает массив в виде const Array^. На уровне двоичного интерфейса приложения среда выполнения Windows (ABI) это называется PassArray. В следующем примере показано, как передать массив, выделенный в JavaScript функции C++, которая считывает из него.

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

В следующем фрагменте кода показан метод 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;
}

Шаблон ReceiveArray

В шаблоне ReceiveArray клиентский код объявляет массив и передает его методу, который выделяет память для него и инициализирует его. Тип входного параметра C++ — это указатель на шляпу: Array<T>^* В следующем примере показано, как объявить объект массива в JavaScript и передать его функции C++, которая выделяет память, инициализирует элементы и возвращает массив в JavaScript. JavaScript обрабатывает выделенный массив в качестве возвращаемого значения, но функция C++ обрабатывает его как выходной параметр.

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

В следующем фрагменте кода показаны два способа реализации метода 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;
}

Заполнение массивов

Если необходимо выделить массив в вызывающем объекте, а затем инициализировать или изменить его в вызываемом объекте, используйте массив WriteOnlyArray. В следующем примере показано, как реализовать функцию C++, которая использует WriteOnlyArray и вызывает его из 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] + " ";
    }
}

В следующем фрагменте кода показано, как реализовать метод 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;
    }   
}

Преобразования массивов

В этом примере показано, как использовать Platform::Array для создания других типов коллекций:

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

В следующем примере показано, как создать Platform::Array массив стилей C и вернуть его из общедоступного метода.

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

Массивы массивов

Система типов среды выполнения Windows не поддерживает концепцию массивов массивов и, таким образом, невозможно использовать IVector<Platform::Array<T>> в качестве возвращаемого значения или параметра метода в открытом методе. Для передачи массива массивов или последовательности массивов в ABI используйте IVector<IVector<T>^>.

Используйте ArrayReference, чтобы избежать копирования данных

В некоторых сценариях, когда данные передаются через ABI в ABI Platform::Array, и в конечном счете вы хотите обработать эти данные в массиве стиле C для повышения эффективности, можно использовать Platform::ArrayReference , чтобы избежать дополнительной операции копирования. При передаче Platform::ArrayReference в качестве аргумента параметру, который принимает значение Platform::Array, ArrayReference данные будут храниться непосредственно в заданном массиве стилей C. Просто учтите, что ArrayReference не блокирует исходные данные, и если данные изменяются или удаляются в другом потоке до завершения вызова, результаты будут неопределенными.

В следующем фрагменте кода показано, как скопировать результаты DataReader операции в Platform::Array (обычный шаблон), а затем заменить ArrayReference данные непосредственно в массив стилей 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) );
    }
};

Избегайте использования типа Array в качестве свойства

Как правило, следует избегать предоставления доступа к типу Platform::Array как к свойству в ссылочном классе, потому что массив возвращается целиком, даже если код клиента пытается получить доступ только к одному элементу. Если необходимо предоставить контейнер последовательности в качестве свойства в общедоступном классе ссылок, Windows::Foundation::IVector лучше выбрать. В частных или внутренних API (которые не публикуются в метаданных), рассмотрите возможность использования стандартного контейнера C++, std::vectorнапример.

См. также

Система типов
Справочник по языку C++/CX
Справочник по пространствам имен