C++/WinRT 시작Get started with C++/WinRT

C++/WinRT를 빠르게 사용할 수 있도록, 이 항목에서는 새 Windows 콘솔 애플리케이션(C++/WinRT) 프로젝트를 기반으로 하는 간단한 코드 예제를 살펴보겠습니다.To get you up to speed with using C++/WinRT, this topic walks through a simple code example based on a new Windows Console Application (C++/WinRT) project. 이 항목에서는 Windows 데스크톱 애플리케이션 프로젝트에 C++/WinRT 지원을 추가하는 방법도 보여 줍니다.This topic also shows how to add C++/WinRT support to a Windows Desktop application project.

참고

Visual Studio 및 Windows SDK의 최신 버전을 사용하여 개발하는 것이 좋지만, Visual Studio 2017(버전 15.8.0 이상)을 사용 중이고 Windows SDK 버전 10.0.17134.0(Windows 10 버전, 1803)을 대상으로 하는 경우 새로 만든 C++/WinRT 프로젝트가 컴파일되지 않고 “오류 C3861: ‘from_abi’: 식별자를 찾을 수 없음” 오류와 base.h에서 발생하는 기타 오류가 표시될 수 있습니다.While we recommend that you develop with the latest versions of Visual Studio and the Windows SDK, if you're using Visual Studio 2017 (version 15.8.0 or higher), and targeting the Windows SDK version 10.0.17134.0 (Windows 10, version 1803), then a newly created C++/WinRT project may fail to compile with the error "error C3861: 'from_abi': identifier not found", and with other errors originating in base.h. 해결 방법으로, 보다 규칙에 맞는 Windows SDK 최신 버전을 대상으로 지정하거나, 프로젝트 속성 C/C++ > 언어 > 적합성 모드: 아니요를 설정합니다. 또는 추가 옵션 아래의 프로젝트 속성 C/C++ > 언어 > 명령줄/permissive- 가 표시되는 경우 삭제합니다.The solution is to either target a later (more conformant) version of the Windows SDK, or set project property C/C++ > Language > Conformance mode: No (also, if /permissive- appears in project property C/C++ > Language > Command Line under Additional Options, then delete it).

C++/WinRT 빠른 시작A C++/WinRT quick-start

참고

—프로젝트 템플릿 및 빌드 지원을 함께 제공하는 C++/WinRT Visual Studio 확장(VSIX) 및 NuGet 패키지를 설치하고 사용하는 방법을 포함—하는 C++/WinRT용 Visual Studio 개발 설정에 대한 자세한 내용은 Visual Studio의 C++/WinRT 지원을 참조하세요.For info about setting up Visual Studio for C++/WinRT development—including installing and using the C++/WinRT Visual Studio Extension (VSIX) and the NuGet package (which together provide project template and build support)—see Visual Studio support for C++/WinRT.

Windows 콘솔 애플리케이션(C++/WinRT) 프로젝트를 만듭니다.Create a new Windows Console Application (C++/WinRT) project.

pch.hmain.cpp를 다음과 같이 편집합니다.Edit pch.h and main.cpp to look like this.

// pch.h
#pragma once
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Web.Syndication.h>
#include <iostream>
// main.cpp
#include "pch.h"

using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Web::Syndication;

int main()
{
    winrt::init_apartment();

    Uri rssFeedUri{ L"https://blogs.windows.com/feed" };
    SyndicationClient syndicationClient;
    SyndicationFeed syndicationFeed = syndicationClient.RetrieveFeedAsync(rssFeedUri).get();
    for (const SyndicationItem syndicationItem : syndicationFeed.Items())
    {
        winrt::hstring titleAsHstring = syndicationItem.Title().Text();
        std::wcout << titleAsHstring.c_str() << std::endl;
    }
}

위의 간단한 코드 예제를 하나씩 살펴보고 각 파트에서 수행되는 작업을 설명하겠습니다.Let's take the short code example above piece by piece, and explain what's going on in each part.

#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Web.Syndication.h>

기본 프로젝트 설정을 사용하면 Windows SDK의 %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt 폴더에 있는 헤더가 포함됩니다.With the default project settings, the included headers come from the Windows SDK, inside the folder%WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt. Visual Studio는 IncludePath 매크로에 해당 경로를 포함합니다.Visual Studio includes that path in its IncludePath macro. 그러나 cppwinrt.exe 도구를 통해 프로젝트의 $(GeneratedFilesDir) 폴더에 동일한 헤더가 생성되기 때문에 Windows SDK에 대한 엄격한 종속성은 없습니다.But there's no strict dependency on the Windows SDK, because your project (via the cppwinrt.exe tool) generates those same headers into your project's $(GeneratedFilesDir) folder. 다른 곳에서 찾을 수 없거나 프로젝트 설정을 변경하는 경우 해당 폴더에서 헤더가 로드됩니다.They'll be loaded from that folder if they can't be found elsewhere, or if you change your project settings.

헤더에는 C++/WinRT에 프로젝션된 Windows API가 포함됩니다.The headers contain Windows APIs projected into C++/WinRT. 즉, C++/WinRT는 각 Windows 형식에 해당하는 C++에 편리한 형식(‘프로젝션된 형식’이라고 함)을 정의합니다.In other words, for each Windows type, C++/WinRT defines a C++-friendly equivalent (called the projected type). 프로젝션된 형식은 Windows 형식과 동일한 정규화된 이름을 갖지만 C++ winrt 네임스페이스에 배치됩니다.A projected type has the same fully-qualified name as the Windows type, but it's placed in the C++ winrt namespace. 이러한 형식을 미리 컴파일된 헤더에 포함하면 증분 빌드 시간을 줄일 수 있습니다.Putting these includes in your precompiled header reduces incremental build times.

중요

Windows 네임스페이스의 형식을 사용하려는 경우에는 항상 해당하는 C++/WinRT Windows 네임스페이스 헤더 파일을 위와 같이 #include해야 합니다.Whenever you want to use a type from a Windows namespaces, you must #include the corresponding C++/WinRT Windows namespace header file, as shown above. ‘해당’ 헤더는 형식의 네임스페이스와 동일한 이름을 가진 헤더입니다.The corresponding header is the one with the same name as the type's namespace. 예를 들어 Windows::Foundation::Collections::PropertySet 런타임 클래스에 C++/WinRT 프로젝션을 사용하려면 winrt/Windows.Foundation.Collections.h 헤더를 포함합니다.For example, to use the C++/WinRT projection for the Windows::Foundation::Collections::PropertySet runtime class, include the winrt/Windows.Foundation.Collections.h header.

일반적으로 C++/WinRT 프로젝션 헤더가 부모 네임스페이스 헤더 파일을 자동으로 포함합니다.It's usual for a C++/WinRT projection header to automatically include its parent namespace header file. 예를 들어 winrt/Windows.Foundation.Collections.hwinrt/Windows.Foundation.h를 포함합니다.So, for example, winrt/Windows.Foundation.Collections.h includes winrt/Windows.Foundation.h. 하지만 이 구현 세부 정보는 시간이 지나면 변경되므로 이 동작을 사용하면 안 됩니다.But you shouldn't rely on this behavior, since it's an implementation detail that changes over time. 필요한 헤더를 명시적으로 포함해야 합니다.You must explicitly include any headers that you need.

using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Web::Syndication;

using namespace 지시문은 선택 사항이지만 편리합니다.The using namespace directives are optional, but convenient. 이러한 지시문에 위와 같은 패턴을 사용하면 winrt 네임스페이스에 있는 모든 항목에 대해 한정되지 않은 이름 조회가 가능하므로, 새 프로젝트를 시작 중이며 C++/WinRT가 해당 프로젝트 내에서 사용하는 유일한 언어 프로젝션인 경우에 적합합니다.The pattern shown above for such directives (allowing unqualified name lookup for anything in the winrt namespace) is suitable for when you're beginning a new project and C++/WinRT is the only language projection you're using inside of that project. 반면에 C++/WinRT 코드와 C++/CX 및/또는 SDK ABI(애플리케이션 이진 인터페이스) 코드를 함께 사용하는 경우(두 모델 중 하나 또는 둘 다에서 포팅하거나 상호 운용), C++/WinRT와 C++/CX 간의 상호 운용성, C++/CX에서 C++/WinRT로 이동, C++/WinRT와 ABI 간의 상호 운용성 항목을 참조하세요.If, on the other hand, you're mixing C++/WinRT code with C++/CX and/or SDK application binary interface (ABI) code (you're either porting from, or interoperating with, one or both of those models), then see the topics Interop between C++/WinRT and C++/CX, Move to C++/WinRT from C++/CX, and Interop between C++/WinRT and the ABI.

winrt::init_apartment();

winrt::init_apartment 호출은 기본적으로 다중 스레드 아파트에서 Windows 런타임의 스레드를 초기화합니다.The call to winrt::init_apartment initializes the thread in the Windows Runtime; by default, in a multithreaded apartment. 이 호출에서 COM도 초기화합니다.The call also initializes COM.

Uri rssFeedUri{ L"https://blogs.windows.com/feed" };
SyndicationClient syndicationClient;

두 개의 개체를 스택 할당합니다. 두 개체는 Windows 블로그의 URI와 배포 클라이언트를 나타냅니다.Stack-allocate two objects: they represent the uri of the Windows blog, and a syndication client. 간단한 와이드 문자열 리터럴로 URI를 생성합니다(문자열로 작업할 수 있는 더 많은 방법은 C++/WinRT의 문자열 처리 참조).We construct the uri with a simple wide string literal (see String handling in C++/WinRT for more ways you can work with strings).

SyndicationFeed syndicationFeed = syndicationClient.RetrieveFeedAsync(rssFeedUri).get();

SyndicationClient::RetrieveFeedAsync는 비동기 Windows 런타임 함수의 예입니다.SyndicationClient::RetrieveFeedAsync is an example of an asynchronous Windows Runtime function. 이 코드 예제는 RetrieveFeedAsync에서 비동기 작업 개체를 받은 후 해당 개체에서 get을 호출하여 호출 스레드를 차단하고 결과(이 경우 배포 피드)를 기다립니다.The code example receives an asynchronous operation object from RetrieveFeedAsync, and it calls get on that object to block the calling thread and wait for the result (which is a syndication feed, in this case). 동시성에 대한 자세한 내용과 비차단 기술에 대해서는 C++/WinRT를 통한 동시성 및 비동기 작업을 참조하세요.For more about concurrency, and for non-blocking techniques, see Concurrency and asynchronous operations with C++/WinRT.

for (const SyndicationItem syndicationItem : syndicationFeed.Items()) { ... }

SyndicationFeed.Itemsbeginend 함수에서 반환된 반복기(또는 해당 상수, 역방향, 상수-역방향 변형)로 정의된 범위입니다.SyndicationFeed.Items is a range, defined by the iterators returned from begin and end functions (or their constant, reverse, and constant-reverse variants). 따라서 범위 기반 for 문 또는 std::for_each 템플릿 함수를 사용하여 Items를 열거할 수 있습니다.Because of this, you can enumerate Items with either a range-based for statement, or with the std::for_each template function. 이처럼 Windows 런타임 컬렉션을 반복할 때마다 #include <winrt/Windows.Foundation.Collections.h>가 필요합니다.Whenever you iterate over a Windows Runtime collection like this, you'll need to #include <winrt/Windows.Foundation.Collections.h>.

winrt::hstring titleAsHstring = syndicationItem.Title().Text();
std::wcout << titleAsHstring.c_str() << std::endl;

피드의 제목 텍스트를 winrt::hstring 개체로 가져옵니다(자세한 내용은 C++/WinRT의 문자열 처리 참조).Gets the feed's title text, as a winrt::hstring object (more details in String handling in C++/WinRT). 그러면 C++ 표준 라이브러리 문자열과 함께 사용된 패턴을 반영하는 hstringc_str 함수를 통해 출력됩니다.The hstring is then output, via the c_str function, which reflects the pattern used with C++ Standard Library strings.

이와 같이 C++/WinRT는 클래스와 유사한 최신 C++ 식(예: syndicationItem.Title().Text())의 사용을 장려합니다.As you can see, C++/WinRT encourages modern, and class-like, C++ expressions such as syndicationItem.Title().Text(). 이 기술은 기존 COM 프로그래밍과 확연히 다를 뿐만 아니라 보다 명확한 프로그래밍 스타일입니다.This is a different, and cleaner, programming style from traditional COM programming. COM을 직접 초기화하거나 COM 포인터를 사용할 필요가 없습니다.You don't need to directly initialize COM, nor work with COM pointers.

HRESULT 반환 코드를 처리할 필요도 없습니다.Nor do you need to handle HRESULT return codes. C++/WinRT는 자연스러운 최신 프로그래밍 스타일을 위해 winrt::hresult-error 등의 오류 HRESULT를 예외로 변환합니다.C++/WinRT converts error HRESULTs to exceptions such as winrt::hresult-error for a natural and modern programming style. 오류 처리와 코드 예제에 대한 자세한 내용은 C++/WinRT를 통한 오류 처리를 참조하세요.For more info about error-handling, and code examples, see Error handling with C++/WinRT.

Windows 데스크톱 애플리케이션 프로젝트를 수정하여 C++/WinRT 지원 추가Modify a Windows Desktop application project to add C++/WinRT support

이 섹션에서는 기존의 Windows 데스크톱 애플리케이션 프로젝트에 C++/WinRT 지원을 추가하는 방법을 보여 줍니다.This section shows you how you can add C++/WinRT support to a Windows Desktop application project that you might have. 기존의 Windows 데스크톱 애플리케이션 프로젝트가 없는 경우 먼저 프로젝트를 만든 후 이러한 단계를 수행할 수 있습니다.If you don't have an existing Windows Desktop application project, then you can follow along with these steps by first creating one. 예를 들어 Visual Studio를 열고, Visual C++ > Windows 데스크톱 > Windows 데스크톱 애플리케이션 프로젝트를 만듭니다.For example, open Visual Studio and create a Visual C++ > Windows Desktop > Windows Desktop Application project.

선택적으로 C++/WinRT VSIX(Visual Studio Extension) 및 NuGet 패키지를 설치할 수 있습니다.You can optionally install the C++/WinRT Visual Studio Extension (VSIX) and the NuGet package. 자세한 내용은 Visual Studio의 C++/WinRT 지원을 참조하세요.For details, see Visual Studio support for C++/WinRT.

프로젝트 속성 설정Set project properties

일반 > Windows SDK 버전 프로젝트 속성으로 차례로 이동한 다음, 모든 구성모든 플랫폼을 선택합니다.Go to project property General > Windows SDK Version, and select All Configurations and All Platforms. Windows SDK 버전이 10.0.17134.0(Windows 10, 버전 1803) 이상으로 설정되어 있는지 확인합니다.Ensure that Windows SDK Version is set to 10.0.17134.0 (Windows 10, version 1803) or greater.

새 프로젝트가 컴파일되지 않는 이유는 무엇인가요?의 영향을 받지 않는지 확인합니다.Confirm that you're not affected by Why won't my new project compile?.

C++/WinRT는 C++17 표준의 기능을 사용하기 때문에 프로젝트 속성 C/C++ > 언어 > C++ 언어 표준을 ‘ISO C++17 표준(/std:c++17)’으로 설정합니다.Because C++/WinRT uses features from the C++17 standard, set project property C/C++ > Language > C++ Language Standard to ISO C++17 Standard (/std:c++17).

미리 컴파일된 헤더The precompiled header

기본 프로젝트 템플릿은 framework.h 또는 stdafx.h라는 미리 컴파일된 헤더를 자동으로 만듭니다.The default project template creates a precompiled header for you, named either framework.h, or stdafx.h. 헤더 이름을 pch.h로 바꿉니다.Rename that to pch.h. stdafx.cpp 파일이 있는 경우 파일 이름도 pch.cpp로 바꿉니다.If you have a stdafx.cpp file, then rename that to pch.cpp. 프로젝트 속성 C/C++ > 미리 컴파일된 헤더 > 미리 컴파일된 헤더만들기(/Yc) 로 설정하고 미리 컴파일된 헤더 파일pch.h로 설정합니다.Set project property C/C++ > Precompiled Headers > Precompiled Header to Create (/Yc), and Precompiled Header File to pch.h.

모든 #include "framework.h"(또는 #include "stdafx.h")를 찾아서 #include "pch.h"로 바꿉니다.Find and replace all #include "framework.h" (or #include "stdafx.h") with #include "pch.h".

pch.hwinrt/base.h를 포함합니다.In pch.h, include winrt/base.h.

// pch.h
...
#include <winrt/base.h>

연결Linking

C++/WinRT 언어 프로젝션은 WindowsApp.lib 상위 라이브러리에 대한 연결이 필요한 특정 Windows 런타임 프리(비멤버) 함수 및 진입점에 따라 달라집니다.The C++/WinRT language projection depends on certain Windows Runtime free (non-member) functions, and entry points, that require linking to the WindowsApp.lib umbrella library. 이 섹션에서는 링커를 충족하는 세 가지 방법을 설명합니다.This section describes three ways of satisfying the linker.

첫 번째 옵션은 Visual Studio 프로젝트에 C++/WinRT MSBuild 속성과 대상을 모두 추가하는 것입니다.The first option is to add to your Visual Studio project all of the C++/WinRT MSBuild properties and targets. 이 작업을 수행하려면 Microsoft.Windows.CppWinRT NuGet 패키지를 프로젝트에 설치합니다.To do this, install the Microsoft.Windows.CppWinRT NuGet package into your project. Visual Studio에서 프로젝트를 열고, 프로젝트 > NuGet 패키지 관리... > 찾아보기를 차례로 클릭하고, 검색 상자에서 Microsoft.Windows.CppWinRT를 입력하거나 붙여넣고, 검색 결과에서 해당 항목을 선택한 다음, 설치를 클릭하여 해당 프로젝트에 대한 패키지를 설치합니다.Open the project in Visual Studio, click Project > Manage NuGet Packages... > Browse, type or paste Microsoft.Windows.CppWinRT in the search box, select the item in search results, and then click Install to install the package for that project.

프로젝트 연결 설정을 사용하여 WindowsApp.lib를 명시적으로 연결할 수도 있습니다.You can also use project link settings to explicitly link WindowsApp.lib. 또는 다음과 같이 소스 코드(예: pch.h)에서 이 작업을 수행할 수 있습니다.Or, you can do it in source code (in pch.h, for example) like this.

#pragma comment(lib, "windowsapp")

이제 컴파일하고 연결한 다음, 프로젝트에 C++/WinRT 코드(예: 위의 C++/WinRT 빠른 시작 섹션의 코드와 유사한 코드)를 추가할 수 있습니다.You can now compile and link, and add C++/WinRT code to your project (for example, code similar to that shown in the A C++/WinRT quick-start section, above).

C++/WinRT에 대한 세 가지 주요 시나리오The three main scenarios for C++/WinRT

C++/WinRT를 사용하여 익숙해지고 이 설명서의 나머지 부분을 살펴보면 다음 섹션에서 설명하는 세 가지 주요 시나리오가 있음을 알 수 있습니다.As you use and become familiar with C++/WinRT, and work through the rest of the documentation here, you'll likely notice that there are three main scenarios, as described in the following sections.

Windows 런타임 API 및 형식 사용Consuming Windows Runtime APIs and types

즉 API를 사용하거나 호출합니다.In other words, using, or calling APIs. 예를 들어 Bluetooth를 통한 통신, 비디오 스트리밍 및 표시, Windows 셸과의 통합 등을 수행하는 API를 호출합니다.For example, making API calls to communicate using Bluetooth; to stream and present video; to integrate with the Windows shell; and so on. C++/WinRT는 이 시나리오 범주를 완벽하고 단호하게 지원합니다.C++/WinRT fully and uncompromisingly supports this category of scenario. 자세한 내용은 C++/WinRT를 통한 API 사용을 참조하세요.For more info, see Consume APIs with C++/WinRT.

Windows 런타임 API 및 형식 작성Authoring Windows Runtime APIs and types

즉 API 및 형식을 생성합니다.In other words, producing APIs and types. 예를 들어 위의 섹션에서 설명하는 종류의 API, 그래픽 API, 스토리지 및 파일 시스템 API, 네트워킹 API 등을 생성합니다.For example, producing the kinds of APIs described in the section above; or the graphics APIs; the storage and file system APIs; the networking APIs, and so on. 자세한 내용은 C++/WinRT를 통한 API 작성을 참조하세요.For more info, see Author APIs with C++/WinRT.

API를 구현하려면 먼저 IDL을 사용하여 해당 API의 모양을 정의해야 하므로 C++/WinRT를 사용하여 API를 작성하는 것이 이러한 API를 사용하는 것보다 더 중요합니다.Authoring APIs with C++/WinRT is a little more involved than consuming them, because you must use IDL to define the shape of the API before you can implement it. 이러한 작업은 XAML 컨트롤, C++/WinRT 속성에 바인딩에서 연습할 수 있습니다.There's a walkthrough of doing that in XAML controls; bind to a C++/WinRT property.

XAML 애플리케이션XAML applications

이 시나리오는 애플리케이션 및 컨트롤을 XAML UI 프레임워크에 구축하는 것입니다.This scenario is about building applications and controls on the XAML UI framework. XAML 애플리케이션에서 작업하는 것은 사용과 작성의 조합에 해당합니다.Working in a XAML application amounts to a combination of consuming and authoring. 그러나 XAML은 현재 Windows에서 가장 많이 사용되는 UI 프레임워크이며 Windows 런타임에 대한 영향력은 이에 비례하므로 고유한 시나리오 범주가 있습니다.But since XAML is the dominant UI framework on Windows today, and its influence over the Windows Runtime is proportionate to that, it deserves its own category of scenario.

XAML은 리플렉션을 제공하는 프로그래밍 언어에서 가장 효율적으로 작동합니다.Be aware that XAML works best with programming languages that offer reflection. C++/WinRT에서는 XAML 프레임워크와 상호 운용하기 위해 약간의 추가 작업을 수행해야 하는 경우도 있습니다.In C++/WinRT, you sometimes have to do a little extra work in order to interoperate with the XAML framework. 이러한 모든 사례는 설명서에서 다룹니다.All of those cases are covered in the documentation. 적절한 시작 지점은 XAML 컨트롤, C++/WinRT 속성에 바인딩C++/WinRT를 통한 XAML 사용자 지정(템플릿 기반) 컨트롤입니다.Good places to start are XAML controls; bind to a C++/WinRT property and XAML custom (templated) controls with C++/WinRT.

C++/WinRT로 작성된 샘플 앱Sample apps written in C++/WinRT

C++/WinRT 샘플 앱은 어디서 찾을 수 있나요?를 참조하세요.See Where can I find C++/WinRT sample apps?.

중요 APIImportant APIs