C++/CX가 포함된 Windows 런타임 구성 요소Windows Runtime components with C++/CX

참고

이 항목은 C++/CX 응용 프로그램 유지에 도움을 주기 위해 작성되었습니다.This topic exists to help you maintain your C++/CX application. 하지만 새로운 응용 프로그램에 대해 C++/WinRT를 사용하는 것이 좋습니다.But we recommend that you use C++/WinRT for new applications. C++/WinRT는 Windows 런타임(WinRT) API용 최신 표준 C++17 언어 프로젝션으로서 헤더 파일 기반 라이브러리로 구현되며, 오늘날 Windows API에 대해 최고 수준의 액세스를 제공하도록 설계되었습니다.C++/WinRT is an entirely standard modern C++17 language projection for Windows Runtime (WinRT) APIs, implemented as a header-file-based library, and designed to provide you with first-class access to the modern Windows API. /Winrt를 사용 하 여 C++Windows 런타임 구성 요소를 만드는 방법에 대 한 자세한 내용은 /Winrt의 C++Author 이벤트를 참조 하세요.To learn how to create a Windows Runtime component using C++/WinRT, see Author events in C++/WinRT.

이 항목에서는/cx를 사용 C++하 여 Windows 런타임 언어 (—C#, Visual Basic, C++또는 Javascript)를 사용 하 여 빌드된 유니버설 Windows 앱에서 호출할 수 있는 구성 요소 Windows 런타임 구성 요소를 만드는 방법을 보여 줍니다.This topic shows how to use C++/CX to create a Windows Runtime component—a component that's callable from a Universal Windows app built using any Windows Runtime language (C#, Visual Basic, C++, or Javascript).

Windows 런타임 구성 요소를 작성 하는 데는 여러 가지 이유가 있습니다.There are several reasons for building a Windows Runtime component.

  • 복잡하거나 많은 계산이 필요한 작업에서 C++의 성능 이점을 얻을 수 있습니다.To get the performance advantage of C++ in complex or computationally intensive operations.
  • 이미 작성되고 테스트된 코드를 다시 사용할 수 있습니다.To reuse code that's already written and tested.

JavaScript 또는 .NET 프로젝트와 Windows 런타임 구성 요소 프로젝트가 포함된 솔루션을 빌드할 때, JavaScript 프로젝트 파일 및 컴파일된 DLL이 하나의 패키지로 병합되어 시뮬레이터에서 로컬로 또는 테더링된 디바이스에서 원격으로 디버그할 수 있습니다.When you build a solution that contains a JavaScript or .NET project, and a Windows Runtime component project, the JavaScript project files and the compiled DLL are merged into one package, which you can debug locally in the simulator or remotely on a tethered device. 또한 구성 요소 프로젝트만 확장 SDK로 배포할 수 있습니다.You can also distribute just the component project as an Extension SDK. 자세한 내용은 소프트웨어 개발자 키트 만들기를 참조하세요.For more information, see Creating a Software Development Kit.

일반적으로 C++/cx 구성 요소를 코딩할 때 다른 winmd 패키지의 코드 C++ 에서 데이터를 전달 하는 ABI (추상 이진 인터페이스) 경계를 제외 하 고 일반 라이브러리 및 기본 제공 형식을 사용 합니다.In general, when you code your C++/CX component, use the regular C++ library and built-in types, except at the abstract binary interface (ABI) boundary where you are passing data to and from code in another .winmd package. 여기에서 이러한 형식을 만들고 조작 하는 데 지원 C++되는 Windows 런타임 형식 및 특수 구문이 사용 됩니다.There, use Windows Runtime types and the special syntax that C++/CX supports for creating and manipulating those types. 또한 C++/cx 코드에서 대리자 및 이벤트와 같은 형식을 사용 하 여 구성 요소에서 발생 하 고 JavaScript에서 처리 될 수 있는 이벤트를 구현 하거나, Visual Basic C++, 또는 C#를 사용 합니다.In addition, in your C++/CX code, use types such as delegate and event to implement events that can be raised from your component and handled in JavaScript, Visual Basic, C++, or C#. /Cx 구문에 대 한 자세한 내용은 /cx (C++시각적 C++ 언어 참조)를 참조 하세요. C++For more information about the C++/CX syntax, see Visual C++ Language Reference (C++/CX).

대/소문자 표기 및 명명 규칙Casing and naming rules

JavaScriptJavaScript

JavaScript는 대/소문자를 구분합니다.JavaScript is case-sensitive. 따라서 이러한 대/소문자 표기 규칙을 따라야 합니다.Therefore, you must follow these casing conventions:

  • C++ 네임스페이스와 클래스를 참조하는 경우 C++ 쪽에서 사용한 동일한 대/소문자 표기를 사용합니다.When you reference C++ namespaces and classes, use the same casing that's used on the C++ side.
  • 메서드를 호출할 때, 메서드 이름이 C++ 쪽에서 대문자로 표시되는 경우에도 카멜식 대/소문자 표기법을 사용합니다.When you call methods, use camel casing even if the method name is capitalized on the C++ side. 예를 들어 C++ 메서드 GetDate()는 JavaScript에서 getDate()로 호출해야 합니다.For example, a C++ method GetDate() must be called from JavaScript as getDate().
  • 활성화 가능한 클래스 이름 및 네임스페이스 이름에는 유니코드 문자를 포함할 수 없습니다.An activatable class name and namespace name can't contain UNICODE characters.

.NET.NET

.NET 언어는 일반 대/소문자 표기 규칙을 따릅니다.The .NET languages follow their normal casing rules.

개체 인스턴스화Instantiating the object

Windows 런타임 형식만 ABI 경계를 통해 전달할 수 있습니다.Only Windows Runtime types can be passed across the ABI boundary. 구성 요소에 공용 메서드의 매개 변수나 반환 형식으로 std::wstring과 같은 형식이 있으면 컴파일러가 오류를 발생시킵니다.The compiler will raise an error if the component has a type like std::wstring as a return type or parameter in a public method. Visual C++ 구성 요소 확장(C++/CX) 제공 형식에는 int 및 double과 같은 일반적인 스칼라와 해당 typedef인 int32, float64 등이 포함됩니다.The Visual C++ component extensions (C++/CX) built-in types include the usual scalars such as int and double, and also their typedef equivalents int32, float64, and so on. 자세한 내용은 형식 시스템(C++/CX)을 참조하세요.For more information, see Type System (C++/CX).

// ref class definition in C++
public ref class SampleRefClass sealed
{
    // Class members...

    // #include <valarray>
public:
    double LogCalc(double input)
    {
        // Use C++ standard library as usual.
        return std::log(input);
    }

};
//Instantiation in JavaScript (requires "Add reference > Project reference")
var nativeObject = new CppComponent.SampleRefClass();
//Call a method and display result in a XAML TextBlock
var num = nativeObject.LogCalc(21.5);
ResultText.Text = num.ToString();

C++/CX 기본 제공 형식, 라이브러리 형식 및 Windows 런타임 형식C++/CX built-in types, library types, and Windows Runtime types

활성화 가능한 클래스(ref 클래스라고도 함)는 JavaScript, C# 또는 Visual Basic과 같은 다른 언어에서 인스턴스화할 수 있습니다.An activatable class (also known as a ref class) is one that can be instantiated from another language such as JavaScript, C# or Visual Basic. 다른 언어에서 사용할 수 있으려면 구성 요소에 하나 이상의 활성화 가능한 클래스가 포함되어야 합니다.To be consumable from another language, a component must contain at least one activatable class.

Windows 런타임 구성 요소에는 여러 활성화 가능한 공용 클래스와 구성 요소에 내부적으로만 알려진 추가 클래스가 포함될 수 있습니다.A Windows Runtime component can contain multiple public activatable classes as well as additional classes that are known only internally to the component. JavaScript에 표시 되지 않는 C++/cx 형식에 WebHostHidden 특성을 적용합니다.Apply the WebHostHidden attribute to C++/CX types that are not intended to be visible to JavaScript.

모든 공용 클래스는 구성 요소 메타데이터 파일과 같은 이름을 가진 같은 루트 네임스페이스에 있어야 합니다.All public classes must reside in the same root namespace which has the same name as the component metadata file. 예를 들어 A.B.C.MyClass라는 클래스는 A.winmd 또는 A.B.winmd 또는 A.B.C.winmd라는 메타데이터 파일에서 정의된 경우에만 인스턴스화할 수 있습니다.For example, a class that's named A.B.C.MyClass can be instantiated only if it's defined in a metadata file that's named A.winmd or A.B.winmd or A.B.C.winmd. .winmd 파일 이름과 일치시키기 위해 DLL의 이름은 필요하지 않습니다.The name of the DLL is not required to match the .winmd file name.

클라이언트 코드는 모든 클래스에 대해서와 마찬가지로 new(Visual Basic에서는 New) 키워드를 사용하여 구성 요소의 인스턴스를 만듭니다.Client code creates an instance of the component by using the new (New in Visual Basic) keyword just as for any class.

활성화 가능한 클래스는 public ref class sealed로 선언해야 합니다.An activatable class must be declared as public ref class sealed. ref class 키워드가 컴파일러에게 Windows 런타임 호환 형식으로 클래스를 만들도록 지시하면 봉인된 키워드는 클래스가 상속될 수 없다고 지정합니다.The ref class keyword tells the compiler to create the class as a Windows Runtime compatible type, and the sealed keyword specifies that the class cannot be inherited. Windows 런타임은 현재 유니버설 상속 모델을 지원하지 않고, 제한된 상속 모델이 사용자 지정 XAML 컨트롤의 생성을 지원합니다.The Windows Runtime does not currently support a generalized inheritance model; a limited inheritance model supports creation of custom XAML controls. 자세한 내용은 Ref 클래스 및 구조(C++/CX)를 참조하세요.For more information, see Ref classes and structs (C++/CX).

/Cx C++의 경우 모든 숫자 기본 형식은 기본 네임 스페이스에 정의 됩니다.For C++/CX, all the numeric primitives are defined in the default namespace. Platform 네임 스페이스는 C++Windows 런타임 형식 시스템과 관련 된/cx 클래스를 포함 합니다.The Platform namespace contains C++/CX classes that are specific to the Windows Runtime type system. 여기에는 Platform::String 클래스 및 Platform::Object 클래스가 포함됩니다.These include Platform::String class and Platform::Object class. Platform::Collections::Map 클래스 및 Platform::Collections::Vector 클래스와 같은 구체적인 컬렉션 형식은 Platform::Collections 네임스페이스에서 정의됩니다.The concrete collection types such as Platform::Collections::Map class and Platform::Collections::Vector class are defined in the Platform::Collections namespace. 이러한 형식이 구현하는 공용 인터페이스는 Windows::Foundation::Collections 네임스페이스(C++/CX)에서 정의됩니다.The public interfaces that these types implement are defined in Windows::Foundation::Collections Namespace (C++/CX). 이러한 인터페이스 형식이 JavaScript, C# 및 Visual Basic에서 사용하는 형식입니다.It is these interface types that are consumed by JavaScript, C# and Visual Basic. 자세한 내용은 형식 시스템(C++/CX)을 참조하세요.For more information, see Type System (C++/CX).

기본 제공 형식의 값을 반환하는 메서드Method that returns a value of built-in type

    // #include <valarray>
public:
    double LogCalc(double input)
    {
        // Use C++ standard library as usual.
        return std::log(input);
    }
//Call a method
var nativeObject = new CppComponent.SampleRefClass;
var num = nativeObject.logCalc(21.5);
document.getElementById('P2').innerHTML = num;

사용자 지정 값 구조를 반환하는 메서드Method that returns a custom value struct

namespace CppComponent
{
    // Custom struct
    public value struct PlayerData
    {
        Platform::String^ Name;
        int Number;
        double ScoringAverage;
    };

    public ref class Player sealed
    {
    private:
        PlayerData m_player;
    public:
        property PlayerData PlayerStats
        {
            PlayerData get(){ return m_player; }
            void set(PlayerData data) {m_player = data;}
        }
    };
}

ABI를 통해 사용자 정의 값 구조체를 전달 하려면/Cx에 C++정의 된 값 struct와 동일한 멤버를 포함 하는 JavaScript 개체를 정의 합니다.To pass user-defined value structs across the ABI, define a JavaScript object that has the same members as the value struct that's defined in C++/CX. 그런 다음 해당 개체를 C++/cx 메서드에 인수로 전달 하 여 개체를 C++/cx 형식으로 암시적으로 변환할 수 있습니다.You can then pass that object as an argument to a C++/CX method so that the object is implicitly converted to the C++/CX type.

// Get and set the value struct
function GetAndSetPlayerData() {
    // Create an object to pass to C++
    var myData =
        { name: "Bob Homer", number: 12, scoringAverage: .357 };
    var nativeObject = new CppComponent.Player();
    nativeObject.playerStats = myData;

    // Retrieve C++ value struct into new JavaScript object
    var myData2 = nativeObject.playerStats;
    document.getElementById('P3').innerHTML = myData.name + " , " + myData.number + " , " + myData.scoringAverage.toPrecision(3);
}

다른 접근 방식은 IPropertySet(표시되지 않음)를 구현하는 클래스를 정의하는 것입니다.Another approach is to define a class that implements IPropertySet (not shown).

.NET 언어에서는 C++/cx 구성 요소에 정의 된 형식의 변수를 만듭니다.In the .NET languages, you just create a variable of the type that's defined in the C++/CX component.

private void GetAndSetPlayerData()
{
    // Create a ref class
    var player = new CppComponent.Player();

    // Create a variable of a value struct
    // type that is defined in C++
    CppComponent.PlayerData myPlayer;
    myPlayer.Name = "Babe Ruth";
    myPlayer.Number = 12;
    myPlayer.ScoringAverage = .398;

    // Set the property
    player.PlayerStats = myPlayer;

    // Get the property and store it in a new variable
    CppComponent.PlayerData myPlayer2 = player.PlayerStats;
    ResultText.Text += myPlayer.Name + " , " + myPlayer.Number.ToString() +
        " , " + myPlayer.ScoringAverage.ToString();
}

오버로드된 메서드Overloaded Methods

/Cx C++public ref 클래스는 오버 로드 된 메서드를 포함할 수 있지만 JavaScript는 오버 로드 된 메서드를 구분 하는 기능을 제한 합니다.A C++/CX public ref class can contain overloaded methods, but JavaScript has limited ability to differentiate overloaded methods. 예를 들어 다음 서명 간의 차이는 구분할 수 있습니다.For example, it can tell the difference between these signatures:

public ref class NumberClass sealed
{
public:
    int GetNumber(int i);
    int GetNumber(int i, Platform::String^ str);
    double GetNumber(int i, MyData^ d);
};

그러나 다음의 차이는 구분할 수 없습니다.But it can’t tell the difference between these:

int GetNumber(int i);
double GetNumber(double d);

모호한 경우에는 JavaScript가 Windows::Foundation::Metadata::DefaultOverload 특성을 헤더 파일의 메서드 서명에 적용하여 항상 특정 오버로드를 호출합니다.In ambiguous cases, you can ensure that JavaScript always calls a specific overload by applying the Windows::Foundation::Metadata::DefaultOverload attribute to the method signature in the header file.

이 JavaScript는 항상 특성이 지정된 오버로드를 호출합니다.This JavaScript always calls the attributed overload:

var nativeObject = new CppComponent.NumberClass();
var num = nativeObject.getNumber(9);
document.getElementById('P4').innerHTML = num;

.NET.NET

.NET 언어는 모든 .NET 클래스에서 C++와 마찬가지로/cx ref 클래스의 오버 로드를 인식 합니다.The .NET languages recognize overloads in a C++/CX ref class just as in any .NET class.

DateTimeDateTime

Windows 런타임에서 Windows::Foundation::DateTime 개체는 단지 1601년 1월 1일 전 또는 후의 100나노초 간격 수를 나타내는 64비트의 부호 있는 정수입니다.In the Windows Runtime, a Windows::Foundation::DateTime object is just a 64-bit signed integer that represents the number of 100-nanosecond intervals either before or after January 1, 1601. Windows:Foundation::DateTime 개체에는 메서드가 없습니다.There are no methods on a Windows:Foundation::DateTime object. 대신 각 언어는 해당 언어에 대 한 기본 형식으로 DateTime을 프로젝션 합니다. JavaScript의 Date 개체와 .NET의 system.string 및 system.string 형식입니다.Instead, each language projects the DateTime in the way that is native to that language: the Date object in JavaScript and the System.DateTime and System.DateTimeOffset types in .NET.

public  ref class MyDateClass sealed
{
public:
    property Windows::Foundation::DateTime TimeStamp;
    void SetTime(Windows::Foundation::DateTime dt)
    {
        auto cal = ref new Windows::Globalization::Calendar();
        cal->SetDateTime(dt);
        TimeStamp = cal->GetDateTime(); // or TimeStamp = dt;
    }
};

/Cx에서 C++Javascript로 DateTime 값을 전달 하면 javascript는 해당 값을 날짜 개체로 받아들이고 기본적으로 긴 날짜 문자열로 표시 합니다.When you pass a DateTime value from C++/CX to JavaScript, JavaScript accepts it as a Date object and displays it by default as a long-form date string.

function SetAndGetDate() {
    var nativeObject = new CppComponent.MyDateClass();

    var myDate = new Date(1956, 4, 21);
    nativeObject.setTime(myDate);

    var myDate2 = nativeObject.timeStamp;

    //prints long form date string
    document.getElementById('P5').innerHTML = myDate2;

}

.NET 언어가 시스템. DateTime을 C++/cx 구성 요소에 전달 하는 경우 메서드는이를 Windows:: Foundation::D atetime으로 받아들입니다.When a .NET language passes a System.DateTime to a C++/CX component, the method accepts it as a Windows::Foundation::DateTime. 구성 요소가 Windows:: Foundation::D ateTime을 .NET 메서드에 전달할 때 프레임 워크 메서드는이를 DateTimeOffset으로 받아들입니다.When the component passes a Windows::Foundation::DateTime to a .NET method, the Framework method accepts it as a DateTimeOffset.

private void DateTimeExample()
{
    // Pass a System.DateTime to a C++ method
    // that takes a Windows::Foundation::DateTime
    DateTime dt = DateTime.Now;
    var nativeObject = new CppComponent.MyDateClass();
    nativeObject.SetTime(dt);

    // Retrieve a Windows::Foundation::DateTime as a
    // System.DateTimeOffset
    DateTimeOffset myDate = nativeObject.TimeStamp;

    // Print the long-form date string
    ResultText.Text += myDate.ToString();
}

컬렉션 및 배열Collections and arrays

컬렉션은 항상 ABI 경계 전반에서 Windows::Foundation::Collections::IVector^ 및 Windows::Foundation::Collections::IMap^과 같은 Windows 런타임 형식에 핸들로 전달됩니다.Collections are always passed across the ABI boundary as handles to Windows Runtime types such as Windows::Foundation::Collections::IVector^ and Windows::Foundation::Collections::IMap^. 예를 들어 핸들을 Platform::Collections::Map으로 반환하는 경우 이것이 Windows::Foundation::Collections::IMap^으로 암시적으로 변환됩니다.For example, if you return a handle to a Platform::Collections::Map, it implicitly converts to a Windows::Foundation::Collections::IMap^. 컬렉션 인터페이스는 구체적 구현을 제공 하는 C++/cx 클래스와는 별개의 네임 스페이스에서 정의 됩니다.The collection interfaces are defined in a namespace that's separate from the C++/CX classes that provide the concrete implementations. JavaScript와 .NET 언어는 인터페이스를 사용합니다.JavaScript and .NET languages consume the interfaces. 자세한 내용은 컬렉션(C++/CX)배열과 WriteOnlyArray(C++/CX)를 참조하세요.For more information, see Collections (C++/CX) and Array and WriteOnlyArray (C++/CX).

IVector 전달Passing IVector

// Windows::Foundation::Collections::IVector across the ABI.
//#include <algorithm>
//#include <collection.h>
Windows::Foundation::Collections::IVector<int>^ SortVector(Windows::Foundation::Collections::IVector<int>^ vec)
{
    std::sort(begin(vec), end(vec));
    return vec;
}
var nativeObject = new CppComponent.CollectionExample();
// Call the method to sort an integer array
var inVector = [14, 12, 45, 89, 23];
var outVector = nativeObject.sortVector(inVector);
var result = "Sorted vector to array:";
for (var i = 0; i < outVector.length; i++)
{
    outVector[i];
    result += outVector[i].toString() + ",";
}
document.getElementById('P6').innerHTML = result;

.NET 언어는 IVector<T>를 IList<T>로 표시합니다.The .NET languages see IVector<T> as IList<T>.

private void SortListItems()
{
    IList<int> myList = new List<int>();
    myList.Add(5);
    myList.Add(9);
    myList.Add(17);
    myList.Add(2);

    var nativeObject = new CppComponent.CollectionExample();
    IList<int> mySortedList = nativeObject.SortVector(myList);

    foreach (var item in mySortedList)
    {
        ResultText.Text += " " + item.ToString();
    }
}

IMap 전달Passing IMap

// #include <map>
//#include <collection.h>
Windows::Foundation::Collections::IMap<int, Platform::String^> ^GetMap(void)
{    
    Windows::Foundation::Collections::IMap<int, Platform::String^> ^ret =
        ref new Platform::Collections::Map<int, Platform::String^>;
    ret->Insert(1, "One ");
    ret->Insert(2, "Two ");
    ret->Insert(3, "Three ");
    ret->Insert(4, "Four ");
    ret->Insert(5, "Five ");
    return ret;
}
// Call the method to get the map
var outputMap = nativeObject.getMap();
var mStr = "Map result:" + outputMap.lookup(1) + outputMap.lookup(2)
    + outputMap.lookup(3) + outputMap.lookup(4) + outputMap.lookup(5);
document.getElementById('P7').innerHTML = mStr;

.NET 언어는 IMap 및 IDictionary<K, V>를 표시합니다.The .NET languages see IMap and IDictionary<K, V>.

private void GetDictionary()
{
    var nativeObject = new CppComponent.CollectionExample();
    IDictionary<int, string> d = nativeObject.GetMap();
    ResultText.Text += d[2].ToString();
}

속성Properties

/Cx 구성 요소 확장의 C++public ref 클래스는 property 키워드를 사용 하 여 public 데이터 멤버를 속성으로 노출 합니다.A public ref class in C++/CX component extensions exposes public data members as properties, by using the property keyword. 개념은 .NET 속성과 동일 합니다.The concept is identical to .NET properties. Trivial 속성은 그 기능이 암시적이므로 데이터 멤버와 비슷합니다.A trivial property resembles a data member because its functionality is implicit. NSEOTrivial이 아닌 속성은 명시적인 get 및 set 접근자와 해당 값에 대한 "백업 저장소"인 명명된 프라이빗 변수가 있습니다.A non-trivial property has explicit get and set accessors and a named private variable that's the "backing store" for the value. 이 예제에서 private 멤버 변수 _propertyavalue는 propertya에 대 한 백업 저장소입니다.In this example, the private member variable _propertyAValue is the backing store for PropertyA. 속성은 값이 변경될 때 이벤트를 발생시킬 수 있으며 클라이언트 앱은 해당 이벤트를 받도록 등록할 수 있습니다.A property can fire an event when its value changes, and a client app can register to receive that event.

//Properties
public delegate void PropertyChangedHandler(Platform::Object^ sender, int arg);
public ref class PropertyExample  sealed
{
public:
    PropertyExample(){}

    // Event that is fired when PropertyA changes
    event PropertyChangedHandler^ PropertyChangedEvent;

    // Property that has custom setter/getter
    property int PropertyA
    {
        int get() { return m_propertyAValue; }
        void set(int propertyAValue)
        {
            if (propertyAValue != m_propertyAValue)
            {
                m_propertyAValue = propertyAValue;
                // Fire event. (See event example below.)
                PropertyChangedEvent(this, propertyAValue);
            }
        }
    }

    // Trivial get/set property that has a compiler-generated backing store.
    property Platform::String^ PropertyB;

private:
    // Backing store for propertyA.
    int m_propertyAValue;
};
var nativeObject = new CppComponent.PropertyExample();
var propValue = nativeObject.propertyA;
document.getElementById('P8').innerHTML = propValue;

//Set the string property
nativeObject.propertyB = "What is the meaning of the universe?";
document.getElementById('P9').innerHTML += nativeObject.propertyB;

.Net 언어는 .NET 개체의 경우와 C++마찬가지로 네이티브/cx 개체의 속성에 액세스 합니다.The .NET languages access properties on a native C++/CX object just as they would on a .NET object.

private void GetAProperty()
{
    // Get the value of the integer property
    // Instantiate the C++ object
    var obj = new CppComponent.PropertyExample();

    // Get an integer property
    var propValue = obj.PropertyA;
    ResultText.Text += propValue.ToString();

    // Set a string property
    obj.PropertyB = " What is the meaning of the universe?";
    ResultText.Text += obj.PropertyB;

}

대리자 및 이벤트Delegates and events

대리자는 함수 개체를 나타내는 Windows 런타임 형식입니다.A delegate is a Windows Runtime type that represents a function object. 이벤트, 콜백 및 비동기 메서드 호출과 관련된 대리자를 사용하여 나중에 수행할 작업을 지정할 수 있습니다.You can use delegates in connection with events, callbacks, and asynchronous method calls to specify an action to be performed later. 함수 개체와 마찬가지로 대리자는 컴파일러에서 함수의 매개 변수 형식 및 반환 형식을 확인할 수 있도록 함으로써 형식의 안전성을 제공합니다.Like a function object, the delegate provides type-safety by enabling the compiler to verify the return type and parameter types of the function. 대리자의 선언은 함수 서명과 비슷하고 구현은 클래스 정의와 비슷하며 호출은 함수 호출과 비슷합니다.The declaration of a delegate resembles a function signature, the implementation resembles a class definition, and the invocation resembles a function invocation.

이벤트 수신기 추가Adding an event listener

이벤트 키워드를 사용하여 지정된 대리자 형식의 공용 멤버를 선언할 수 있습니다.You can use the event keyword to declare a public member of a specified delegate type. 클라이언트 코드는 특정 언어로 제공되는 표준 메커니즘을 사용하여 이벤트를 구독합니다.Client code subscribes to the event by using the standard mechanisms that are provided in the particular language.

public:
    event SomeHandler^ someEvent;

이 예제에서는 이전 속성 섹션과 동일한 C++ 코드를 사용합니다.This example uses the same C++ code as for the previous properties section.

function Button_Click() {
    var nativeObj = new CppComponent.PropertyExample();
    // Define an event handler method
    var singlecasthandler = function (ev) {
        document.getElementById('P10').innerHTML = "The button was clicked and the value is " + ev;
    };

    // Subscribe to the event
    nativeObj.onpropertychangedevent = singlecasthandler;

    // Set the value of the property and fire the event
    var propValue = 21;
    nativeObj.propertyA = 2 * propValue;

}

.NET 언어에서 C++ 구성 요소의 이벤트를 구독 하는 것은 .net 클래스에서 이벤트를 구독 하는 것과 같습니다.In the .NET languages, subscribing to an event in a C++ component is the same as subscribing to an event in a .NET class:

//Subscribe to event and call method that causes it to be fired.
private void TestMethod()
{
    var objWithEvent = new CppComponent.PropertyExample();
    objWithEvent.PropertyChangedEvent += objWithEvent_PropertyChangedEvent;

    objWithEvent.PropertyA = 42;
}

//Event handler method
private void objWithEvent_PropertyChangedEvent(object __param0, int __param1)
{
    ResultText.Text = "the event was fired and the result is " +
         __param1.ToString();
}

하나의 이벤트에 여러 이벤트 수신기 추가Adding multiple event listeners for one event

JavaScript에는 여러 처리기가 단일 이벤트를 구독할 수 있는 addEventListener 메서드가 있습니다.JavaScript has an addEventListener method that enables multiple handlers to subscribe to a single event.

public delegate void SomeHandler(Platform::String^ str);

public ref class LangSample sealed
{
public:
    event SomeHandler^ someEvent;
    property Platform::String^ PropertyA;

    // Method that fires an event
    void FireEvent(Platform::String^ str)
    {
        someEvent(Platform::String::Concat(str, PropertyA->ToString()));
    }
    //...
};
// Add two event handlers
var multicast1 = function (ev) {
    document.getElementById('P11').innerHTML = "Handler 1: " + ev.target;
};
var multicast2 = function (ev) {
    document.getElementById('P12').innerHTML = "Handler 2: " + ev.target;
};

var nativeObject = new CppComponent.LangSample();
//Subscribe to the same event
nativeObject.addEventListener("someevent", multicast1);
nativeObject.addEventListener("someevent", multicast2);

nativeObject.propertyA = "42";

// This method should fire an event
nativeObject.fireEvent("The answer is ");

C#에서는 이전 예제에 표시된 대로 += 연산자를 사용하여 임의 개수의 이벤트 처리기가 이벤트를 구독할 수 있습니다.In C#, any number of event handlers can subscribe to the event by using the += operator as shown in the previous example.

열거형Enums

/Cx의 C++Windows 런타임 열거형은 public 클래스 열거를 사용 하 여 선언 됩니다. 표준 C++의 범위가 지정 된 열거형과 유사 합니다.A Windows Runtime enum in C++/CX is declared by using public class enum; it resembles a scoped enum in standard C++.

public enum class Direction {North, South, East, West};

public ref class EnumExampleClass sealed
{
public:
    property Direction CurrentDirection
    {
        Direction  get(){return m_direction; }
    }

private:
    Direction m_direction;
};

열거형 값은/Cx와 C++JavaScript 간에 정수로 전달 됩니다.Enum values are passed between C++/CX and JavaScript as integers. 선택적으로 같은 명명 된 값을 포함 하는 JavaScript 개체를 C++/cx 열거형으로 선언 하 고 다음과 같이 사용할 수 있습니다.You can optionally declare a JavaScript object that contains the same named values as the C++/CX enum and use it as follows.

var Direction = { 0: "North", 1: "South", 2: "East", 3: "West" };
//. . .

var nativeObject = new CppComponent.EnumExampleClass();
var curDirection = nativeObject.currentDirection;
document.getElementById('P13').innerHTML =
Direction[curDirection];

C# 및 Visual Basic 둘 다 열거에 대해 언어를 지원합니다.Both C# and Visual Basic have language support for enums. 이러한 언어는 .NET C++ 열거형이 표시 되는 것 처럼 public enum 클래스를 참조 합니다.These languages see a C++ public enum class just as they would see a .NET enum.

비동기 메서드Asynchronous methods

다른 Windows 런타임 개체에서 제공하는 비동기 메서드를 사용하려면 작업 클래스(동시성 런타임)를 사용합니다.To consume asynchronous methods that are exposed by other Windows Runtime objects, use the task Class (Concurrency Runtime). 자세한 내용은 작업 병렬 처리(동시성 런타임)를 참조하세요.For more information, see and Task Parallelism (Concurrency Runtime).

/Cx에서 C++비동기 메서드를 구현 하려면 ppltasks.h에 정의 된 create_async 함수를 사용 합니다.To implement asynchronous methods in C++/CX, use the create_async function that's defined in ppltasks.h. 자세한 내용은 UWP 앱 용/cx에서 C++비동기 작업 만들기를 참조 하세요.For more information, see Creating Asynchronous Operations in C++/CX for UWP apps. 예제는 C++/cx Windows 런타임 구성 요소를 만들고 JavaScript 또는 C#에서 호출 하는 연습을 참조 하세요.For an example, see Walkthrough of creating a C++/CX Windows Runtime component, and calling it from JavaScript or C#. .Net 언어는 .NET C++에 정의 된 비동기 메서드와 마찬가지로/cx 비동기 메서드를 사용 합니다.The .NET languages consume C++/CX asynchronous methods just as they would any asynchronous method that's defined in .NET.

예외Exceptions

Windows 런타임에서 정의된 모든 예외 형식을 throw할 수 있습니다.You can throw any exception type that's defined by the Windows Runtime. 일부 Windows 런타임 예외 형식에서는 사용자 지정 형식을 파생시킬 수 없습니다.You cannot derive custom types from any Windows Runtime exception type. 그러나 COMException을 throw하고 예외를 catch하는 코드에서 액세스할 수 있는 사용자 지정 HRESULT를 제공할 수 있습니다.However, you can throw COMException and provide a custom HRESULT that can be accessed by the code that catches the exception. COMException에서 사용자 지정 메시지를 지정할 수 있는 방법이 없습니다.There's no way to specify a custom Message in a COMException.

디버깅 팁Debugging tips

구성 요소 DLL이 있는 JavaScript 솔루션을 디버그할 때, 디버거가 스크립트를 단계별로 또는 구성 요소의 네이티브 코드를 단계별로 실행하도록 설정할 수 있지만 동시에 둘 다 실행하도록 할 수 없습니다.When you debug a JavaScript solution that has a component DLL, you can set the debugger to enable either stepping through script, or stepping through native code in the component, but not both at the same time. 설정을 변경하려면 솔루션 탐색기에서 JavaScript 프로젝트 노드를 선택한 다음 속성, 디버깅, 디버거 형식을 선택합니다.To change the setting, select the JavaScript project node in Solution Explorer and then choose Properties, Debugging, Debugger Type.

패키지 디자이너에서 적절한 기능을 선택해야 합니다.Be sure to select appropriate capabilities in the package designer. 예를 들어 Windows 런타임 API를 사용하여 사용자의 사진 라이브러리에서 이미지 파일을 열려고 하는 경우 매니페스트 디자이너의 기능 창에서 사진 라이브러리 확인란을 선택해야 합니다.For example, if you are attempting to open an image file in the user's Pictures library by using the Windows Runtime APIs, be sure to select the Pictures Library check box in the Capabilities pane of the manifest designer.

JavaScript 코드가 구성 요소의 public 속성 또는 메서드를 인식하지 못하는 경우 JavaScript에서 카멜식 대/소문자 표기를 사용하고 있는지 확인합니다.If your JavaScript code doesn't seem to be recognizing the public properties or methods in the component, make sure that in JavaScript you are using camel casing. 예를 들어 LogCalc C++/cx 메서드는 JavaScript에서 logcalc로 참조 되어야 합니다.For example, the LogCalc C++/CX method must be referenced as logCalc in JavaScript.

솔루션에서 C++/cx Windows 런타임 구성 요소 프로젝트를 제거 하는 경우에는 JavaScript 프로젝트 에서도 프로젝트 참조를 수동으로 제거 해야 합니다.If you remove a C++/CX Windows Runtime component project from a solution, you must also manually remove the project reference from the JavaScript project. 이렇게 하지 않으면 이후 디버그 또는 빌드 작업을 수행할 수 없습니다.Failure to do so prevents subsequent debug or build operations. 필요한 경우 DLL에 대한 어셈블리 참조를 추가할 수 있습니다.If necessary, you can then add an assembly reference to the DLL.