特集:WinRT登場で変わる開発技術と開発言語

Windows 8時代のアプリ開発とWinRT

岩永 信之
2012/06/01
Page1 Page2 Page3 Page4

Metro ― .NET

 先に結論だけいってしまえば、アプリ作成に関してはこれまでどおり、.NETが主力になるだろう。Metroスタイル・アプリはSilverlightの延長線上にある。

実行環境は同じ

 .NETにとって、デスクトップ・アプリとMetroスタイル・アプリの差は、単に参照可能なライブラリの差でしかない。図10に示すように、WinRTを参照する代わりに、.NETの標準ライブラリからWinRTとの重複部分を削った状態になっている。

図10: .NETにとってのデスクトップとMetro

WinRTはネイティブ

 WinRTが標準提供するコンポーネント自体はネイティブで作られている。しかし、言語プロジェクションによってWinRTコンポーネントが.NET型のように見えるということもあり、.NET側からWinRTがネイティブであることを意識することはない。

 実のところ、Silverlightの標準ライブラリも、中身を追っていけばすぐにInternalCallにたどり付く。つまり、かなりの部分が内部的にはネイティブで作られていて、見掛け(インターフェイスの部分)だけが.NETだった。ある意味、WinMDを介したネイティブとの連携強化は、このInternalCall相当のことを一般開発者にも開放したようなものと見なせる。

 また、OSのバージョン・アップによる機能追加も行われていくだろう。恐らく多くの機能はネイティブで作られることになるだろうが、WinRTコンポーネントとして提供され次第、タイムラグなしで(.NETラッパーの提供を待たずに)利用できることになる。.NET開発者にとっては大きな恩恵となるだろう。

.NET for Metro

 同じ.NETであっても、Metroスタイル・アプリとデスクトップ・アプリでは参照できるライブラリに差がある。差は大まかにいうと以下のとおりである。

  • WinRTとの重複削除
    • UI、ファイル操作、通信ソケットなど
  • レガシー削除
    • 非ジェネリック・コレクション(ジェネリック版で代替)
    • XmlSerializer(LINQ to XMLの利用で代替)

 結果として、デスクトップ版の.NETと比べてかなりコンパクトなライブラリに収まっている。また、クロス・プラットフォームにしづらい部分はWinRTに移っているため、残された部分はかなりポータブルになっている。

 デスクトップ版からの移行を考える場合、この辺りのライブラリの再整理を意識しておく必要がある(非ジェネリック・コレクションの使用を避けたり、ファイルは直接触らずStreamクラス(System.IO名前空間)など抽象度の高いクラスを介して操作したり)。

言語プロジェクション

 前述のとおり、WinRTを.NETらしい書き方で参照できるようにするため、いくつかの型に関しては規約ベースで置き換えを行っている(この置き換えは、.NET⇔WinRTの双方向で行われる)。表1に基礎的な型、表2にコレクション関連の型の一例を示す。

WinRTの型 .NETの型
Uri Uri
DateTime DateTimeOffset
TimeSpan TimeSpan
表1: System ⇔ Windows.Foundation間のプロジェクション
 Windows.Foundation名前空間
 System名前空間

 

WinRTの型 .NETの型
IIterable<T> IEnumerable<T>
IITerator<T> IEnumerator<T>
IVector<T> IList<T>
IVectorView<T> IReadOnlyList<T>
IMap<T> IDictionary<T>
IMapView<T> IReadOnlyCollection<T>
表2: System.Collections.Generic ⇔ Windows.Foundation.Collections間のプロジェクション
 Windows.Foundation.Collections名前空間
 System.Collections.Generic名前空間

 .NETを使ってWinRTコンポーネントを作りたい場合、図11に示すように、プロジェクト・タイプを「WinMD」に設定する必要がある(プロジェクトのプロパティを開いて、ビルドのページで設定)。

図11: WinMDプロジェクト

 .NETで作った任意の型をWinRT側に公開できるわけではなく、以下のいずれかである必要がある。

  • WinRTで決められた型
    • intなどのプリミティブ型
    • IList<T>やTimeSpanなどの言語プロジェクションが働く型
  • sealed(継承不可)なクラス
    • XAMLで使うUI要素は例外で、UIElementクラス(System.UI.Xaml名前空間)を継承
  • publicなフィールドだけを持つ構造体

Metro ― ネイティブ(C++)

 端的にいってしまうと、.NETでできることをわざわざネイティブでする必要はない。ネイティブの利用場面として想定されるのは、以下のような部分だろう。

  • アクション性の高いゲームなど、高性能なグラフィックが必要なものアプリ
  • CPU依存の最適化や、GPUを使った計算(大規模データ処理など)が必要なアプリ/ライブラリ

 ポイントは、全部をネイティブでやらないこと(つまり.NETなどと連携すること)と、GPUの活用である。そこで、図12に示すように、「C++/CX」と「C++ AMP」という言語拡張を提供している。

図12: Windows 8時代のC++拡張

 もちろん、標準C++だけでWinRTコンポーネントやMetroスタイル・アプリを作ることもできるが*1、大変になるだけなので、通常はC++/CXを使うことになるだろう。

*1 その場合は「WRL(Windows Runtime C++ Template Library)」というライブラリを利用する。

 また、C++ AMPは単に同時期に導入されるというだけで、デスクトップ・アプリでも利用できる。しかし、今の時代、ネイティブが何を期待されているかということの表れではある。Metroスタイル・アプリでも、ネイティブを使うからには性能を追求したい。

C++/CX

 WinRTは、内部的には単なるCOM(Component Object Model)である。ただ、前述のとおり、標準C++の文法の範囲内でCOMを使うのは少々面倒なため、「C++/CX(C++ with Component Extensions)」という言語拡張を提供している。

 C++/CXは、文法的にはC++/CLIを参考にして作られていて、リスト2に例を示すように、パッと見はC++/CLIにそっくりである(一部、差もある)。

public ref class ImageWithLabelControl sealed
  : public Windows::UI::Xaml::Controls::Control
{
public:
  property Platform::String^ Label
  {
    Platform::String^ get() { return
      (Platform::String^)GetValue(LabelProperty); }
    void set(Platform::String^ value) {
      SetValue(LabelProperty, value); }
  }
};
リスト2: C++/CXの記述例

 しかし、C++/CLIのように.NET向けの中間コードが生成されるわけではなく、あくまでネイティブにコンパイルされる。COMであり、メモリはガベージ・コレクションではなく、参照カウントによって管理される。

 より詳しくいうと、図13に示すように、WinMD形式のメタデータとネイティブ・コードが生成される。また、ネイティブ同士でメソッドを呼び出す場合には、COM呼び出しのオーバーヘッドすらなく、単なる仮想関数呼び出し程度のコストになるように作られている。

図13: C++/CXのコンパイル結果

C++ AMP

 GPUを活用して大規模データ並列処理を高速化するための「C++ AMP(C++ Accelerated Massive Parallelism)」というC++言語拡張が、Windows 8と同時期に(厳密にはVisual Studio 11の新機能として)提供される。

 リスト3に示すように、構文的な追加は少なく(リスト中にあるrestrict句と、tile_static修飾子の追加のみ)で、大部分の機能は関数やクラスとして提供されている。

int aCPP[] = {1, 2, 3, 4, 5};
int bCPP[] = {6, 7, 8, 9, 10};
int sumCPP[5] = {0, 0, 0, 0, 0};
array_view<int, 1> a(5, aCPP);
array_view<int, 1> b(5, bCPP);
array_view<int, 1> sum(5, sumCPP);
parallel_for_each(sum.extent,     
  [=](index<1> idx) restrict(amp)
  {
    sum[idx] = a[idx] + b[idx];
  });
リスト3: C++ AMPの利用例

 「restrict(amp)」という指定を行うとGPU上での実行になり、利用できるC++構文に少し制限がかかる。一方、「restrict(cpu)」を指定するとCPU上での実行になり、通常のC++が書ける。

Metro ― HTML5+JavaScript

 .NETやネイティブと比べると、JavaScriptの立ち位置は少し変わったものとなっている。

 .NETやネイティブがUI層の記述にXAMLを使い、UIまでWinRTに頼るのに対して、JavaScriptの場合、UIはHTML5を使って記述し、IE(Internet Explorer)と同じ描画エンジン(Trident)を使って描画する。JavaScriptの実行自体も、IEで使われているChakraエンジンを使う。

 ただし、.NETやネイティブのMetroスタイル・アプリと同様の方法でパッケージ化され、審査があり、Windows Store経由で配布されることになる。

 結局のところ要素技術としては、図14に示すように、標準のHTML5+JavaScriptに対して、WinRTを参照する機能と、「WinJS」というJavaScriptライブラリを追加しただけである。

図14: MetroスタイルのHTML5+JavaScriptアプリ

 基本的には標準のHTML5+JavaScriptであるため、(Webデザインの世界から)UIデザイナーを確保しやすいという利点がある。

WinRTの参照

 .NETやネイティブの場合とは異なり、JavaScriptの場合は、WinRTを参照する機能のみとなる(WinRTコンポーネントを作成して公開する機能はない)。ちなみに、JavaScriptからWinRTコンポーネントを参照する場合、言語プロジェクションによって、メソッド名などの大文字・小文字の置き換えが行われる(WinRTではメソッド名は大文字始まり、JavaScriptでは小文字始まりにする習慣があるため)。例えば、「CreateFileAsync」というメソッドであれば、JavaScriptから「createFileAsync」という名前で参照する。

 WinRTが必要になる機能は、あらためて書くと、セキュリティやプライバシー的に慎重な取り扱いが必要な機能である。

 標準提供されているWinRTコンポーネントだけでなく、WinMDを介して、.NETやネイティブで作ったコンポーネントも参照できる。HTML5+JavaScriptはあくまでUIの記述のみにとどめて、ロジックは.NETやネイティブで作るのも手だろう。

WinJS

 HTML5を使ってMetro風のUIを作るためのライブラリとして、「WinJS」というJavaScriptライブラリを提供している。WinJSを使う場合、リスト4に示すように、<div>タグ(あるいは<span>タグ)に「data-win-」から始まる属性を記述する。

<div data-win-control="WinJS.Binding.Template">
  <div data-win-bind="style.backgroundColor: backgroundColor"></div>
  <div data-win-bind="textContent: title"></div>
  <div data-win-bind="textContent: description"></div>
</div>
リスト4: WinJSの利用例

 あくまでHTML5の規格の範囲内ではあるが、UI作りの勘所としてはCSSなどを使った一般的なHTML記述よりもむしろ、XAMLに近い(XAMLでよく使うデータ・バインディングなどの概念を持っている)ため、注意が必要である。

 勘所が変わることを避けるために、WinJSを使わないという選択肢もあり得る。ただし、Metroスタイル・アプリは「UXガイドラインに沿っているかどうか」というのも審査基準になっていて、WinJSなしでこのガイドラインに沿ったUIを書くのはそれなりに大変な作業になるかもしれない。もっとも、この点は、もしかしたら、jQueryなどのライブラリがガイドライン対応のスタイルを提供してくれる可能性もある。また、ゲームの場合にはUXガイドラインに関してそれほど厳しく審査されないようなので、問題にならないだろう。

まとめ

 最後に簡単にまとめておこう。

  • WebとMetro
    • Metro固有の高機能が必要ならばMetro、そうでなければWeb
      • 高性能グラフィックスなど、ハードウェア依存の高い低レイヤ機能
      • セキュリティやプライバシー的に慎重な取り扱いが必要な機能
  • デスクトップとMetro
    • 同時開発や段階移行があり得る
    • WinRT = XAML UI、脱Win32
      • WPFやSilverlightとの同時開発/段階移行は楽
      • WindowsフォームやMFCからは大変
    • UI技術は陳腐化が激しいため、UIに依存した部分は極力小さく作るべき
  • Metro ― .NET
    • Silverlightの延長で、WPFやSilverlightの経験者であればすぐにでも開発可能
  • Metro ― ネイティブ
    • .NETでできることをネイティブでやる意味はなく、せっかくネイティブを使うのであれば性能を追求すべき
    • C++/CXとC++ AMP
  • Metro ― HTML5+JavaScript
    • 標準+α (WinRTの参照と、WinJSライブラリ)
    • とはいえ、“+α ”がある時点で勘所は変わる
    • ロジックは.NETやネイティブで作って、UIだけをHTML5+JavaScriptで作る方法もある

 これらの参考基準を判断材料に適切な技術を選択して、Windows 8時代に向けてアプリ開発を進めてほしい。end of article

 

 INDEX
  特集:WinRT登場で変わる開発技術と開発言語
  Windows 8時代のアプリ開発とWinRT
    1.Windows 8概要 - 多様化への対応
    2.新API「WinRT」
    3.Windows 8時代の多様な選択肢(1):MetroとWeb/デスクトップの対比
  4.Windows 8時代の多様な選択肢(2):選択可能な3つの言語/フレームワーク


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH