Array 및 WriteOnlyArray(C++/CX)

일반 C 스타일 배열 또는 std::array C++/CX 프로그램에서 자유롭게 사용할 수 있지만( std::vector 종종 더 나은 선택임) 메타데이터에 게시된 모든 API에서는 C 스타일 배열 또는 벡터를 Platform::Array 사용 방법에 따라 C 스타일 배열 또는 Platform::WriteOnlyArray 형식으로 변환해야 합니다. 형식은 Platform::Array 효율적이고 강력 std::vector하지 않으므로 일반적인 지침에서는 배열 요소에 대해 많은 작업을 수행하는 내부 코드에서 사용하지 않아야 합니다.

다음 배열 형식은 ABI 너머로 전달될 수 있습니다.

  1. const Platform::Array^

  2. Platform::Array^*

  3. Platform::WriteOnlyArray

  4. 의 반환 값 Platform::Array^

이러한 배열 형식을 사용하여 Windows 런타임 정의된 세 가지 종류의 배열 패턴을 구현합니다.

PassArray
호출자가 메서드에 배열을 전달할 때 사용됩니다. C++ 입력 매개 변수 형식은 T>입니다constPlatform::Array<.

FillArray
호출자가 메서드에서 채울 배열을 전달할 때 사용됩니다. C++ 입력 매개 변수 형식은 T>입니다Platform::WriteOnlyArray<.

ReceiveArray
호출자가 메서드가 할당하는 배열을 받을 때 사용됩니다. C++/CX에서는 반환 값에서 배열을 Array^로 반환하거나 Array^* 형식의 out 매개 변수로 반환할 수 있습니다.

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에서 배열 개체를 선언한 다음, 메모리를 할당하고 요소를 초기화하여 JavaScript에 반환하는 C++ 함수에 이 개체를 전달하는 방법을 보여 줍니다. 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를 사용합니다. 다음 예제에서는 WriteOnlyArray 를 사용하는 C++ 함수를 구현하고 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;
    }   
}

배열 규칙

이 예제에서는 a 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);
    }   
}

다음 예제에서는 C 스타일 배열에서 생성 Platform::Array 하 고 공용 메서드에서 반환 하는 방법을 보여 있습니다.

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 런타임 형식 시스템에서는 가변 배열의 개념이 지원되지 않으므로 public 메서드에서 IVector<Platform::Array<T>> 를 반환 값 또는 메서드 매개 변수로 사용할 수 없습니다. ABI 전반에서 가변 배열 또는 시퀀스의 시퀀스를 전달하려면 IVector<IVector<T>^>를 사용합니다.

ArrayReference를 사용하여 데이터 복사 방지

데이터를 ABIPlatform::Array에 전달하고 궁극적으로 효율성을 위해 C 스타일 배열에서 해당 데이터를 처리하려는 일부 시나리오에서는 Platform::ArrayReference를 사용하여 추가 복사 작업을 방지할 수 있습니다. 인수를 Platform::ArrayReference 사용하는 Platform::ArrayArrayReference 매개 변수에 인수로 전달하면 지정한 C 스타일 배열에 데이터를 직접 저장합니다. ArrayReference 에는 소스 데이터에 대한 잠금이 없으므로 호출이 완료되기 전에 다른 스레드에서 해당 데이터가 수정되거나 삭제되는 경우 결과가 정의되지 않습니다.

다음 코드 조각은 작업 결과를 DataReader (일반적인 패턴)으로 Platform::Array 복사한 다음, 데이터를 C 스타일 배열로 직접 복사하는 ArrayReference 방법을 보여 줍니다.

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

속성으로 배열 노출 방지

일반적으로 ref 클래스에서는 Platform::Array 형식을 속성으로 노출하지 않아야 합니다. 클라이언트 코드가 단일 요소에만 액세스하려고 하는 경우에도 전체 배열이 반환되기 때문입니다. 시퀀스 컨테이너를 public ref 클래스 Windows::Foundation::IVector 의 속성으로 노출해야 하는 경우 더 나은 선택입니다. 프라이빗 또는 내부 API(메타데이터에 게시되지 않음)에서는 다음과 같은 std::vector표준 C++ 컨테이너를 사용하는 것이 좋습니다.

참고 항목

형식 시스템
C++/CX 언어 참조
네임스페이스 참조