Программисты на C# располагают богатой средой разработки, в которой основной акцент делается на максимальной продуктивности труда, а не производительности приложений. Подозреваю, что это заявление может быть встречено разработчиками на C# с некоторым скептицизмом, поскольку производительность превосходна и превышает потребности большинства в достижении их задач. Таким образом, для разработчиков на C# современный C++ может не обеспечить отдачу от вложений, так как продуктивность труда может пострадать, несмотря на все недавние улучшения, предлагаемые новым C++. Однако изящество разработки приложений Windows Store заключается в том, что вы можете применять гибкий (agile) подход к созданию повторно используемых компонентов (что само по себе продуктивно), задействовав лучшие качества обоих языков для поэтапного введения компонентов на C++ там, где они наиболее полезны.
Эта статья адресована разработчикам на C#, желающим приобщиться к мощи и быстродействию современного C++, C++/CX (Component Extensions) и Windows Runtime C++ Template Library (WRL) (для краткости я буду в этой статье обобщенно называть все это как C++). Она также адресована разработчикам, которые подобно мне планируют задействовать мощь облака Windows Azure. Приложения, созданные с помощью C++, не только обладают потенциалом, продлевающим работу аккумуляторов планшетов и телефонов, но и приводят к снижению расходов из-за большей производительности на Ватт, на транзистор и на такт (см. «C++ and Beyond 2011: Herb Sutter — Why C++?» по ссылке bit.ly/1gtKQya).
Проблема, с которой сталкиваются разработчики на C# при попытке освоить C++, состоит в том, что большая часть документации, блогов и других доступных ресурсов отражают интересы опытных разработчиков на C++, а не на C# (которые, как правило, не хотят создавать консольное приложение на основе одного проекта). Ситуация еще больше осложняется тем, что C++ переживает период ренессанса, поэтому уйма текущих материалов может оказаться устаревшей, не применимой или отвлекающей от более новых и более эффективных техник кодирования. Чтобы отделить зерна от плевел, вы должны иметь базовое представление о предметной области, определяемой такими акронимами, как C++, C++/CLI, C++/CX, WRL, STL, ATL, WinRT и др. Без этого понимания вы можете попусту потратить уйму ценного времени на изучение материалов, не применимых к вашей задаче.
Мой интерес к C++ возник, когда я уткнулся в потолок производительности C# в одном сценарии применения, где приходилось обрабатывать более 200 000 записей по сложному алгоритму. Мои исследования привели меня к веб-трансляции «Taming GPU Compute with C++ AMP» (bit.ly/1dajKE6), в которой представлялось демонстрационное приложение, навсегда изменившее мое понимание того, что такое настоящая производительность. Если бы у меня был опыт работы с C++ AMP и я мог бы создать прототип для представления своей команде, то подозреваю, что они с радостью приняли бы C++-компонент, своими глазами увидев, как процесс длительностью в 11 секунд ускоряется до нескольких миллисекунд. Увы, огромный объем информации (и дезинформации) по C++ и отсутствие у меня предметного знания C++ вынудили меня погрузиться в эту огромную библиотеку в поисках полки с книгами, имеющими отношение к разработке приложений Windows Store на C++.
Программисты на C# располагают богатой средой разработки, в которой основной акцент делается на максимальной продуктивности труда, а не производительности приложений.
Цель этой статьи — не обучить вас C++, а указать на нужную полку. Это упростит ваше обучение, и вас не будет отвлекать уйма лишней информации. Прочитав эту статью, вы вооружитесь знаниями, которые позволят извлекать выгоду из доступных материалов по C++, например из недавних статей в журнале «MSDN Magazine», библиотек и блогов о разработке на C++.
Пакет исходного кода, сопутствующий этой статье, представляет собой решение Visual Studio, содержащее три приложения, которые основаны на разных платформах программирования: C#, C++ и JavaScript. Как вы увидите, в этом решении я сокращаю «Windows Store applications» до Wsa в именах проектов (это неофициальное сокращение). Приложение WsaJavaScript основано на учебных материалах MSDN «Walkthrough: Creating a Basic Windows Runtime Component Using WRL» (bit.ly/1n1gvV2). В это учебное приложение я просто добавил две кнопки с метками «Data Binding» и «Data Binding (Reused)» (как показано на рис. 1). Заметьте, что приложения WsaXamlCpp (C++/CX) и WsaXamlCs (C#) в этом решении используют одни и те же библиотеки и дают совершенно идентичные результаты.
{Для верстки: зеленый цвет – светло-серый оттенок, фиолетовый – серый, а серый – темно-серый}
Рис. 1. Схемы трех приложений (приложения обозначаются светло-серым, библиотеки — серым, а сценарии применения — темно-серым цветом)
Приложения на C# и C++/CX демонстрируют, насколько эффективна разработка приложений Windows Store: вы можете повторно использовать компоненты между платформами, как видно в правой секции рис. 1). Например, анализируя код, вы обнаружите, что эти приложения используют один и тот же XAML, который был скопирован и вставлен в соответствующее представление каждого приложения (DataBindingView). Аналогично вы заметите, что у них одинаковые презентатор (DataBindingPresenter), модель представления (MainViewModel), уровень доступа к данным (MockDataDal) и регистратор (DebugLogger). В случае приложений Windows Store вы можете создавать библиотеки на C# или C++, что позволяет поэтапно переходить на разработку на C++ по вашему усмотрению и заменять менее эффективные алгоритмы на C# высокопроизводительным кодом C++ AMP с минимальными потерями в продуктивности труда.
Продуктивность труда достаточно высока, потому что вы можете повторно использовать весь полезный код. Так, регистратор (logger) для обоих приложений (см. окно вывода внизу рис. 2) является C#-компонентом, который находится в C#-проекте WsaWrcCs. Я не стал тратить время на создание регистратора на C++, который оказал бы пренебрежимо малое влияние на производительность, и сосредоточился на более важных областях. Рис. 2 также демонстрирует небольшое различие между кодом на C# и C++/CX в классе DataBindingPresenter; этот класс содержит большую часть кода приложения, а остальная логика находится в общих компонентах (в обоих проектах вы не увидите много кода).
Рис. 2. Код на C++/CX и C# использует одни и те же ViewModel, уровень доступа к данным и регистратор
Помимо демонстрации мощи разработки, это решение предоставляет «песочницу» (изолированную среду), где вы можете приступить к разработке на C++. Если в большинстве учебных пособий и примеров предлагается код для какого-либо консольного приложения (от которого мало пользы в среде приложений Windows Store), то это решение дает пример кода в интересующем вас типе проектов — с использованием современного C++, WRL или C++/CX. Вы можете убедиться, насколько легко ваш C++-код доступен C#-приложению.
Хотя я намерен обсудить предметную тематику по C++, относящуюся к разработке приложений Windows Store, они не рассматриваются здесь во всей полноте. Однако в следующих разделах вы получите отправную точку, с которой сможете продолжить свое обучение; кроме того, я буду давать некоторые ссылки на более подробную информацию, если таковая есть. Смысл этого упражнения в том, чтобы вам было легче сосредоточиться на ключевых темах, которые вы должны понимать, и отфильтровать огромные залежи неприменимой к этой области информации. Хочу выразить благодарность группе разработки Microsoft C++, активно помогавшей мне в поисках нужной полки в колоссальной библиотеке информации, чтобы я быстрее стал разработчиком на Microsoft C++.
Windows Runtime (WinRT)
Система типов WinRT позволяет использовать самые разнообразные языки для доступа к Windows API (которые предоставляются как WinRT-типы) и писать приложения и компоненты по одной и той же технологии. Windows Runtime основана на Application Binary Interface (ABI) — стандарте соединения компонентов, а также на различных API.
То, что вы видели на рис. 1, — это результат интеграции различных платформ разработки: C#, C++ и C++/CX, прозрачно используемых приложениями Windows Store на JavaScript, C# и C++. Чтобы это было возможно, нужен некий стандартный интерфейс во всех языках для использования скомпилированного кода. Для этого в каждом проекте WRL- и WinRT-компонентов генерируется файл .winmd, который служит кросс-языковым заголовочным файлом. Заметьте, что файл .winmd, по сути, является файлом метаданных CLI (поэтому его можно просматривать с помощью ILSpy).
Вы создаете и используете ABI с помощью C++/CX, WRL, C# и JavaScript (или любого другого языка, который поддерживает WinRT ABI). Вашим первым порывом как разработчика на C#, возможно, будет попытка писать весь код на C++/CX, поскольку такой стиль ближе всего к тому, к чему вы привыкли, но вы должны по возможности свести к минимуму использование WinRT и строго ограничиться уровнем ABI. Например, ваш код должен задействовать мощь C++, используя C++/CX, только когда возникает необходимость в пересечении границ ABI. В соответствии с предназначением C++/CX содержит лишь малое подмножество функций для своих компонентов, т. е. в String будет отсутствовать большая часть функций, к которым вы привыкли и которые могут понадобиться, так как C++/CX не является автономным языком разработки. Понимание ABI и его ограничений поможет вам в разработках на C++/CX. Советую просмотреть видеоролики на Channel 9 по этой тематике, например «Under the Covers with C++ for Metro-Style Apps» (bit.ly/1k7CWLq).
Библиотеки
Standard Template Library (STL) — самая важная библиотека для программистов на C++. Шаблоны и обобщения отвечают на вопрос: «Как создавать безопасные по типам обобщенные контейнеры?». В C++ это шаблоны, а в C# — обобщения, и, хотя их синтаксис слегка похож, эти концепции весьма разные. Шаблоны специализируются при компиляции, а обобщения — в период выполнения. Что касается C++/CLI, они различаются в том плане, что используют разные ключевые слова и синтаксисы. С точки зрения C#, если вы подходите к шаблонам как к обобщениям, вы найдите некоторые сходства.
Как указывается в документации MSDN Library (bit.ly/1bZzkTB), STL устанавливает единые стандарты для применения итераторов к STL-контейнерам или другим последовательностям, определяемым вами, с помощью алгоритмов STL или других функций, также определяемых вами. Это общее определение STL, которое, конечно же, подразумевает, что вам нужно разобраться в том, что такое алгоритмы, итераторы и контейнеры. Я не стану здесь вдаваться в детали, так как все это очень хорошо документировано в MSDN Library.
Учтите, что C++ STL вовсе не идентична C++ Standard Library. Согласно документации MSDN Library, C++ Standard Library в Visual Studio 2013 — отвечающая стандартам реализации, из которой программы на C++ могут вызывать большое количество функций. Эти функции обеспечивают важные сервисы вроде ввода-вывода и предоставляют эффективные реализации часто используемых операций (bit.ly/1eQkPlS).
Active Template Library (ATL) — набор C++-классов на основе шаблонов, позволяющих создавать небольшие быстрые COM-объекты. В ней есть специальная поддержка ключевых COM-средств, в том числе дуальных интерфейсов, стандартных COM-интерфейсов перечислителей, точек соединения (connection points), интерфейсов с механизмом вызова по требованию (tear-off interfaces) и ActiveX-элементов управления (bit.ly/1engnjy). Важно понимать, что в WinRT-приложениях поддерживается лишь малое подмножество COM и WINAPI. Для таких приложений лучше подходит WRL.
WRL — нечто вроде упрощенной ATL для Windows Runtime. Она состоит из набора заголовочных файлов и шаблонов, помогающих создавать WinRT-классы, используя средства стандартного C++. Она избавляет от огромного объема стереотипного кода, который иначе вам пришлось бы добавлять самостоятельно, и уменьшает количество строк примерно так же, как и C++/CX. C++/CX — тот способ, которым большинство разработчиков должно создавать и использовать WinRT-компоненты, если только вам не нужно делать это в кодовой базе, где запрещены исключения или есть специфические требования, или если вы просто предпочитаете избегать закрытых языковых расширений, пока в них нет абсолютной необходимости. WRL — самый низкий уровень разработки на C++ для взаимодействия с приложениями Windows Store. В ней отсутствуют некоторые средства для создания XAML-компонентов, поэтому для их разработки вы должны использовать C++/CX или C#.
C++
Современный C++ (версии 11 или выше) значительно отличается от предыдущих версий, что обесценивает многие имеющиеся на данный момент книги, блоги и статьи, так что будьте внимательны. Если где-то используется new или delete, это старый C++. Это не значит, что он устарел или стал бесполезным, — вам не придется переписывать существующий код, поскольку C++11 хорошо совместим с существующим кодом. Вы просто лишитесь простоты и эффективности современного C++.
C++/CX — сравнительно дружелюбный к разработчикам на C# способ создания WinRT-типов. Это языковое расширение предназначено для того, чтобы упростить создание и использование WinRT-типов, но оно не обязательно. По сути, в тех же целях можно задействовать WRL — только это уже не будет так легко. Заметьте, что C++/CX заимствует синтаксис C++/CLI, но ориентирован на другую исполняющую среду.
C++/CLI, как правило, не применяется в разработке настольных Windows-приложений. Обычно он используется только для управляемого кода в крайне ограниченных случаях. Например, некоторый существующий неуправляемый код хорошо выполняет свою работу и вы хотите, чтобы его можно было легко задействовать из управляемого кода, но интерфейс, который нужно предоставить управляемому коду, не столь идеально работает через COM или P/Invoke. Так что аудитория C++/CLI очень-очень мала. Я отметил его здесь только из-за сходства нотации ^ (шляпы) и потенциальной путаницы, так как некоторые примеры CLI-кода не будут совместимы с C++/CX.
Как C++/CLI, так и приложения Windows Store, написанные на C++/CX, используют нотацию «шляпы». С помощью C++/CX можно использовать WinRT-компоненты в настольных Windows-приложениях (не Windows Store), и тогда нотация «шляпы» применяется обязательно. Используя C++, вы также можете задействовать WinRT-компоненты как в настольных приложениях, так и в приложениях Windows Store; в этом случае нотация «шляпы» не применяется.
При поиске по Интернету советую предварять искомые слова сочетанием «modern C++» или «C++/CX», чтобы получить ссылки именно на нужную документацию.
Урок истории
В прошлом возможность повторного использования программного обеспечения подразумевала доступ к компонентам без обязательного доступа к их коду. Это можно было делать, предоставляя статически связанную библиотеку (файл .lib) в сочетании с заголовочным файлом (.h), и тогда другие разработчики могли связывать этот файл .lib с другими приложениями — заголовочный файл обеспечивал интерфейс к библиотеке со скомпилированным исходным кодом.
Одна из проблем с такой практикой в том, какие объемы памяти и дискового пространства это могло отнимать. Например, библиотека размером 2 Мб, скомпилированная с программным пакетом из шести приложений, занимала 12 Мб дискового пространства. Конечно, средняя емкость жесткого диска в те времена на компьютерах PC XT была порядка 20 Мб. С появлением DLL программисты получили возможность разделять один набор код между несколькими приложениями. Благодаря этому шесть приложений при использовании той же библиотеки теперь дополнительно занимали только 2 Мб.
Подробности, аргументы за и против статических библиотек и DLL выходят за рамки этой статьи. Вы можете найти исчерпывающую информацию по ссылкам в документации MSDN Library.
Статические библиотеки и DLL занимают свои места в создании современных библиотек на C++. Однако, если вы пытаетесь создавать повторно используемые компоненты, легко доступные из приложений Windows Store на JavaScript, C++ и C#, вам нельзя поддаваться подсознательному искушению выбрать проект Windows Store Application DLL (как привыкли разработчики на C#). Как вы вскоре увидите, это не те DLL, о которых вы знаете. Вместо этого вы должны выбрать шаблон проекта для WinRT-компонента (который я предпочитаю сокращенно называть WRC). Это то, что рекомендует Microsoft и что позволит вести разработку максимально близко к тому, к чему вы привыкли.
Шаблоны проектов
Для разработчиков на C# добавить новую библиотеку несложно: достаточно включить проект библиотеки классов и использовать его для создания своих интерфейсов, классов и т. д. Так же легко ссылаться на библиотеки классов: вы просто добавляете ссылки на проект библиотеки классов в ваши приложения или другие библиотеки классов — очень наглядная демонстрация высокой продуктивности труда.
К сожалению, создание C++-библиотек куда менее прямолинейно, и на момент написания этой статьи вы не найдете особо много документации или примеров, помогающих настроить Visual Studio на разработку повторно используемых компонентов, в частности как сконфигурировать различные доступные типы шаблонов проектов. В следующем разделе я помогу вам подготовить Visual Studio к использованию шаблонов проектов для приложений Windows Store на C++.
WinRT-компонент
В документации MSDN Library для «DLLs (C++/CX)» предлагается при необходимости создать DLL для приложения Windows Store создать ее как WinRT-компонент, используя одноименный шаблон проекта (bit.ly/1iwL1Wg). Как отмечалось, это обеспечивает наиболее привычный вариант для добавления и ссылок на библиотеки.
Как показано на рис. 2, между C++/CX и C# есть много схожего, поэтому разработчики на C# смогут достаточно быстро освоить C++. Интересно, что WinRT-компонент прозрачен для приложений Windows Store на C# и C++, что позволяет разработчикам на C# сделать упор как на продуктивность труда, так и на производительность приложения в зависимости от того, что диктует конкретная ситуация. Таким образом, как я указывал ранее, если вы хотите повторно использовать существующий компонент C# Logger в приложении Windows Store на C++ и XAML, вам нужно просто перенести этот код в проект C# WRC — и это все. После этого вы сможете ссылаться на него из приложений, написанных как на C++, так и на C# (как это делаю я в решении-примере).
Учтите: из-за того, что ABI накладывает некоторые ограничения, например классы должны быть запечатанными (sealed), вам придется посмотреть на разработку под новым углом, где композиция преобладает над абстракцией, а это изящно подводит нас к возможности создавать составные приложения.
Шаблон проекта WRL Class Library
Этот шаблон является набором пользовательских классов, созданных с применением WRL. К сожалению, учебные материалы и разъяснения по WRL могут оказаться весьма устрашающими. В качестве введения в WRL и шаблон проекта WRL Class Library советую прочитать учебное пособие «Walkthrough: Creating a Basic Windows Runtime Component Using WRL» (bit.ly/1n1gvV2). Вас наверняка впечатлит, как с помощью всего нескольких строк кода вы сможете обращаться к своему коду на C++ из JavaScript-приложения, просто добавив ссылку на библиотеку. Это учебное пособие стало основой для моего решения-примера.
Это пособие очень важно для новичков в WRL, так как в нем также дается ссылка для генерации WRL-проекта с помощью шаблона WRL Class Library. Этот шаблон включает необходимую информацию для запуска MIDL-компилятора, который обрабатывает IDL-файл (подробнее см. по ссылке bit.ly/1fLMurc). «За кулисами» MIDL-компилятор генерирует требуемые (скрытые) файлы для WRL-проекта Contoso и тем самым берет на себя все издержки, связанные с разработкой под WRL: contoso_h.h, contoso_i.c и contoso_p.c. Как вы увидите из учебного пособия, вам нужно лишь создать файлы contoso.idl и contoso.cpp, которые показаны соответственно на рис. 3 и 4. Заметьте, что я добавил функциональность AddStr(string, string); ее не было в этом учебном пособии.
Рис. 3. Contoso.idl
import "inspectable.idl";
import "Windows.Foundation.idl";
import "ocidl.idl";
#define COMPONENT_VERSION 1.0
namespace Contoso {
interface ICalculator;
runtimeclass Calculator;
[uuid(0be9429f-2c7a-40e8-bb0a-85bcb1749367),
version(COMPONENT_VERSION),
exclusiveto(Calculator)]
interface ICalculator : IInspectable
{
// "Walkthrough: Creating a Basic Windows Runtime Component
// Using WRL" (msdn.microsoft.com/library/jj155856)
HRESULT Add([in] int a, [in] int b, [out, retval] int* value);
HRESULT AddStr([in] HSTRING a, [in]
HSTRING b, [out, retval] int* value);
}
[version(COMPONENT_VERSION), activatable(COMPONENT_VERSION)]
runtimeclass Calculator
{
[default] interface ICalculator;
}
}
Рис. 4. Contoso.cpp
#include "pch.h"
#include "Contoso_h.h"
#include <wrl.h>
#include <string>
#include <memory>
#include "Calculator.h"
using namespace std;
using namespace Microsoft::WRL;
using namespace Windows::Foundation;
namespace ABI {
namespace Contoso {
class Calculator : public RuntimeClass<ICalculator> {
InspectableClass(RuntimeClass_Contoso_Calculator, BaseTrust)
public:
// Используем для обработки строк в приложении
// Windows Store App на C++ внешнюю DLL. Заметьте:
// WRL запрещает перегрузку функций.
HRESULT __stdcall AddStr(_In_ HSTRING a, _In_ HSTRING b, _Out_ int* value)
{
// Преобразуем HSTRING-значения в const wchar_t*,
// чтобы их можно было передать в C++ DLL
const wchar_t* buffera = WindowsGetStringRawBuffer(a, nullptr);
const wchar_t* bufferb = WindowsGetStringRawBuffer(b, nullptr);
// Создаем экземпляр калькулятора,
// используя современные методы
// (msdn.microsoft.com/library/hh279669)
auto calc = make_shared<WsaDllCpp::Calculator>();
// Добавляем строковые значения
auto val = calc->Add(buffera, bufferb);
// Присваиваем значение
*value = val;
return S_OK;
}
// "Walkthrough: Creating a Basic Windows Runtime
// Component Using WRL" (msdn.microsoft.com/library/ jj155856)
HRESULT __stdcall Add(_In_ int a, _In_ int b, _Out_ int* value) {
if (value == nullptr)
{
return E_POINTER;
}
*value = a + b;
return S_OK;
}
};
ActivatableClass(Calculator);
}
}
Как и в случае C#-библиотек классов, для использования WRL-компонента из внешнего компонента или приложения достаточно добавить ссылку на этот проект.
Статические библиотеки
Статические библиотеки годятся, когда вы заново компилируете код, используя текущие средства для каждого проекта, и хотите добиться минимальных издержек, связанных с вызовами этого кода. Этот вариант стоит выбрать, если вы не предполагаете применять один и тот же двоичный файл для нескольких проектов, скомпилированных в разное время.
Компилятору нужно знать расположение статической библиотеки (.lib) и связанного с ней заголовочного файла (.h), чтобы успешно подключить скомпилированный код к приложению. Для этого можно щелкнуть правой кнопкой мыши Solution, выбрать Common Properties | Project Dependencies, затем указать проект (WsaWrcCpp) в списке проектов и отметить файл .lib (WsaLibCpp) как зависимость. Далее щелкните правой кнопкой мыши Project (WsaWrcCpp), выберите Properties | Common Properties | References | Add New Reference | Solution| Projects, а потом укажите свой файл .lib (WsaLibCpp).
Теперь вы должны дать знать проекту, где искать заголовочный файл для проектов .lib. Если вы используете решение-пример, щелкните правой кнопкой мыши проект WsaWrcCpp (WRC), выберите Properties | Configuration Properties | C/C++ | General и укажите в Additional Include Directories местонахождение заголовочного файла, в данном случае это $(SolutionDir)WsaLibCpp;<existing paths>.
DLL
В сопутствующем этой статье коде вы найдете DLL приложения Windows Store для C++-проекта WsaDllCpp (показан на рис. 2). В качестве справочника я использовал статью MSDN Library «Walkthrough: Creating and Using a Dynamic Link Library (C++)» (bit.ly/1enxzWc). Заметьте, что этот проект предназначен только для демонстрации, поскольку применение этой DLL на практике не рекомендуется (об этом мне рассказали разработчики Microsoft C++ и рецензенты моей статьи). Я включил ее, так как вам, возможно, потребуется использовать существующие DLL в приложении Windows Store.
WsaDllCpp DLL позволяет решению Contoso WRL (шаблону WRL Class Library, рассмотренному ранее) складывать две строки, например WsaDllCpp::Calculator::Add(“1000”,“2000”) дает 3000. Следующий интерфейсный код подчеркивает разницу между C++ DLL и C# DLL:
#pragma once
#include <string>
#define WSADLLCPP_API __declspec(dllexport)
namespace WsaDllCpp
{
class Calculator
{
public:
WSADLLCPP_API int Add(const wchar_t* numberOne,
const wchar_t* numberTwo);
WSADLLCPP_API int Add(int numberOne, int numberTwo);
};
}
Как видите, есть некоторые издержки, связанные с необходимостью сделать функции видимыми внешним библиотекам и приложениям (__declspec). Аналогично настройки, требуемые для успешной компиляции WsaDllCpp в приложение, выходят за рамки простого добавления ссылки на проект. Мне пришлось щелкнуть правой кнопкой мыши WRL-проект Contoso, выбрать Properties | Configuration Properties | C/C++ | General и указать в Additional Include Directories местонахождение заголовочного файла.
Разработчики на C# могут счесть такое добавление ссылки на DLL не понятным на интуитивном уровне или, как минимум, непривычным. Как и в случае файла .lib, чтобы добавить ссылку, вы должны щелкнуть проект правой кнопкой мыши, выбрать Add | Reference, а затем щелкнуть кнопку Add New Reference.
В отличие от разработки на C# выбранные вами пути не будут преобразованы в относительные. Лучше всего привыкать к использованию макросов Visual Studio для задания своих путей. В предыдущем примере я указал в Additional Include Directories значение $(SolutionDir)WsaDllCpp; <existing paths>.
Заключение
Как только вы полностью сосредоточитесь на той самой правильной полке, вы обнаружите массу полезной информации (особенно в MSDN Library), что сделает ваш процесс обучения эффективнее. Этот первый шаг к базовому пониманию предметной области C++ поможет вам в ваших исследованиях и разработке приложений Windows Store на C++. Также советую прочитать статьи Кенни Керра (Kenny Kerr) в «MSDN Magazine» (bit.ly/1iv7mUQ) и посмотреть видеоролики на Channel 9 (bit.ly/1dFqYjV), а также изучить статьи Майкла Маклафлина (Michael B. Mclaughlin) по ссылке bit.ly/1b5CDhs. (Ценный ресурс, не указанный на этом сайте, — его «C# to C++ — A Somewhat Short Guide», доступный по ссылке bit.ly/MvdZv4.)
Если вы сконцентрируетесь на C++/CX, современном C++ и на использовании WinRT-компонентов, то достаточно быстро добьетесь своих целей в разработке приложений Windows Store.