step5:薄皮を被せる
前回こしらえたC++によるCounterLibに、C++/CXの皮を被せてWindows Runtime Componentを作ってみます。"プロジェクトの追加"で選択するのはもちろん"Windowsランタイムコンポーネント"です。名前はCounterComponentとしましょう。
ひな型ができたら、プロジェクトプロパティでCounterLibのヘッダ/ライブラリの在り処とライブラリ名(CounterLib.lib)を設定します。
ひな型のClass1.h/Class1.cppをそれぞれCounter.h/Counter.cppに改名し、ぺらっぺらの薄皮を作ります。
#pragma once
#include "CounterLib/CounterLib.h"
namespace CounterComponent {
// [Windows::Foundation::Metadata::WebHostHidden]
public ref class Counter sealed {
public:
Counter();
void Increment();
void Decrement();
int Get();
private:
CounterLib::Counter counter_;
};
}
Windows Runtime Componentが従うべきお作法(ルール)がいくつかあります。
-
ヨソ様に使ってもらうつもりならpublicでなくてはならない。
これはまぁ当然のこととして。 -
publicなものは直接/間接的に(プロジェクト名と同じ)名前空間に置かなければならない。
おっと、プロジェクト名がそのまま名前空間になりますか。これは要注意。 -
public ref classはsealed、すなわち継承不可でなくてはならない。
ふむ...コンポーネントから導出することを許しちゃならん、と。 -
public部にC/C++由来のものがあってはならない。
例えばポインタとか、ヘッダの必要なstd::stringとかをpublic部つまりヨソ様がお使いになるインターフェースに置いてはならん。
そりゃそうです。継承できないんだからprotected部は無意味になりますね。private部はヨソ様には見えない/触れないのでポインタだろがstd::stringだろがなんでも置いておけます(現にCounterLib::Counterがprivate部にあります)。
主要なお作法はざっとこんなもんでしょうか。これらを満足していないとコンパイル時にエラーです。
実装部はまさに薄皮。各メソッドが呼ばれたら内包するCounterLib::Counterに横流ししているだけ。
#include "pch.h"
#include "Counter.h"
using namespace Platform;
namespace CounterComponent {
Counter::Counter() : counter_() {}
void Counter::Increment() { counter_.increment(); }
void Counter::Decrement() { counter_.decrement(); }
int Counter::Get() { return counter_.get(); }
}
ビルドするとCounterComponent.dllとCounterComponent.winmdが作られます。.dllがコンポーネント本体。.winmdはメタデータと呼ばれ、.dllの使い方(インターフェース)が記された"トリセツ"的役割を担います(C/C++でいうところのヘッダみたいなものです)。各国語で書かれたトリセツあるじゃないですか、あんなカンジ。このトリセツはC#やVB.NETなど、さまざまな言語から読むことができるわけです。




