C#によるWinRTコンポーネント作成時の要点を説明。そしてmrubyを例に既存コード(C言語)の再利用を解説する。
powered by Insider.NET
前回は、Windowsランタイム・コンポーネントの概要、Windowsストア・アプリの開発言語と実行環境、Windowsストア・アプリで既存のコードを再利用するための基本方針について話をした。
今回は、最初にC#でWindowsランタイム・コンポーネントを作成する場合の要点について説明する。この説明で、WindowsランタイムがどのようにABI(アプリケーション・バイナリ・インターフェイス)を実現するか理解できると思う。ここではVisual Studio 2012の利用にまでは踏み込まないが、いずれにしても、Windowsストア・アプリ用.NETを利用するWindowsランタイム・コンポーネントの作成は比較的容易なため、ここでの説明で十分に用をなすだろう。
本連載では、C言語で記述されている既存コードをWindowsランタイム・コンポーネントとして再利用する例として、mrubyを実際にWindowsランタイム・コンポーネント化する過程を見ていく。そこで、C#によるWindowsランタイム・コンポーネント作成について話をした後は、mrubyをWindowsランタイム・コンポーネントとするための準備として、これをコンポーネントに組み込めるようにコンパイルしてみよう。
最初に、Windowsストア・アプリ用.NET(.NET for Windows Store App)を利用してWindowsランタイム・コンポーネントを作成する場合の注意点について、C#を例として説明する。
Windowsランタイム・コンポーネントが持つ制約
この場合に気を付けなければならないのは次の点だ。
このうち1.については説明不要だろう。あらかじめ用意されたテンプレートを使うことで、適切な参照設定やビルド設定が行われる。また、これによりWindowsストア・アプリで利用不可能な.NET FrameworkのAPIがIntelliSenseから隠されるため、不用意に利用できない型やメソッド呼び出しを記述することを防げる。
なお、プロジェクト・テンプレートから[Windows ストア]−[クラス ライブラリ (Windows ストア アプリ)]を選択しクラスライブラリ・プロジェクトを作成した場合でも、プロジェクトのプロパティ設定画面の[アプリケーション]タブにある[出力の種類]から[Windows ランタイム コンポーネント]を選べば、Windowsランタイム・コンポーネントとしてプロジェクトをビルドすることは可能だ。だが、あらかじめWindowsランタイム・コンポーネントを開発することが分かっているのであれば、専用のプロジェクト・テンプレートを使うのが適切だろう。例えばクラス・ライブラリ・プロジェクトを選択した場合、既定のクラスのひな型コードはsealedとなっていないため、そのままではビルド時にエラーとなる。
2.以降をひと言で示せば「Windowsランタイム・コンポーネントに定義された全てのpublicな型はWindowsランタイム型としてビルドされる」ということだ。当然、これらの型が持つpublicなメソッドやフィールドにも同じ制限が付される。
2.の「クラスにsealed修飾子が必須」というのは、利用者側はこのクラスを定義されたままの状態でのみ利用できるということだ。3.と4.の「publicクラスはpublicフィールドやpublicなネスト型を持てない」という制限は、クラスの公開情報はメソッドに限定されるということを意味している。もちろんプロパティは公開できるが、これはメソッドの特殊な記述方法にすぎない。
これらのクラス定義に関する制限について、COMやRPCでIDL(インターフェイス定義言語)を利用したインターフェイス定義を行ったことがある方ならピンとくるように、Windowsランタイム・コンポーネントが公開するクラスとは、コンポーネントのインターフェイスに他ならない。C#の文法ではクラスに直接メソッドを定義できるし、internalやprivateなメソッドやフィールドの定義は自由だ。しかし、ここで示した制限により、ビルド時にクラスの情報からpublicな要素が自動的にインターフェイスとして抽出される*1。このとき、インターフェイスが示す実体が複数の実装を持たないようにsealedで制限し、publicであれば自動的に抽出することができるように、型の制限が付く。
*1 インターフェイス情報は拡張子「winmd」のPE形式バイナリとして生成される。なおPE形式のバイナリではあるが、拡張子を「.EXE」に変更して実行すると「お使いのコンピュータでは実行できません」というエラーとなる。ただし、ILDasmやDumpbinなどのバイナリ参照ツールを利用して生成されたインターフェイス情報を参照することが可能である。
以上を踏まえれば、5.で構造体が公開フィールドのみを持てるのということも当然のことだ。これも同様にIDLで記述可能なUDT(ユーザー定義型)にマッピングされるからだ。UDTはメンバの型で区切られたメモリ・レイアウトにすぎないので、可視性を持たないフィールドやメソッド定義を含めることはできない。
なお、これらの型定義に関する制限はWindowsランタイム・コンポーネントとしてビルドする時点で初めて検証される。コードの編集時点ではC#の文法としては正しいためにIntelliSenseなどではエラーとはならないのだ。このため大量にコードを記述した後にビルドして間違いに気付くことがないように、あらかじめ制限については押さえておきたい。
Copyright© Digital Advantage Corp. All Rights Reserved.