WisdomSoft - for your serial experiences.

最初のプログラム 

C++/CLI を用いて .NET Framework の System.Console.WriteLine() メソッドを呼び出して文字列を出力します。また .NET Framework アセンブリを参照する #using ディレクティブについて解説します。

テキストの出力

さっそく C++ 言語を使って .NET Framework アプリケーションを作成してみましょう。.NET Framework アプリケーションを開発するには Visual Studio の C++ プロジェクトを選択するか、Visual C++ を使います。もしくは、.NET Framework SDK の C++ コンパイラをコマンドラインから使用してもかまいません。「共通言語ランタイム サポート」を有効にして、以下のコードをコンパイルしてください。

コード1
#include <iostream>
#using <mscorlib.dll>

int main()
{
	//アンマネージ関数の呼び出し
	std::cout << "Stand by Ready!\n";

	//マネージ関数の呼び出し
	System::Console::WriteLine("Stand by Ready!");

	return 0;
}
実行結果
コード1 実行結果

コード1は、従来の C++ 言語で開発していたネイティブアプリケーション用の標準出力関数と、.NET アプリケーション用の標準出力関数を使って、それぞれで同じ文字列を表示させています。

最初の行の #include <iostream> に関しては、これまで C++ を使ってきた方には馴染みがあると思います。これは、入出力ストリームに関連するヘッダファイルを読み込むためのものですが、検証可能アセンブリ の場合はネイティブ型を処理できないので指定することはできません。

2行目の #using ディレクティブは C++/CLI の拡張構文のひとつです。.NET Framework は様々な言語で開発されるため、Visual Basic .NET や C# などの異なるプログラミング言語で開発されたコンポーネントを読み込まなければなりません。これらはソースコードによる静的なリンクではなく、コンパイルによって生成された中間言語を含むバイナリを動的にリンクして実現します。そのため、.NET Framework のコンポーネントを読み込むにはソーステキストのヘッダファイルではなく、#using で指定したコンパイル済みの中間言語を含むファイルから直接データの型情報を取得します。

#using ディレクティブ
#using < assembly-name >
#using " assembly-name "

assembly-name には中間言語を含んでいる .NET Framework モジュールを指定します。通常は .dll、.exe、.netmodule、.obj のいずれかになるでしょう。通常、システムが提供するビルドインのライブラリを参照するときに < > 記号で括り、ユーザーのライブラリを参照するときに "" で括ります。

#using ディレクティブはプリプロセッサによる事前のテキスト処理ではありません。前述したように事前にコンパイルされた中間言語を含むアセンブリと呼ばれるファイルを動的に参照します。アセンブリには、.NET Framework で利用される様々なデータ型の参照を解決する情報が含まれています。通常、アセンブリは exe や dll といった拡張子のバイナリに含まれ、アセンブリを含んでいるファイルから、アセンブリを解析して型を解決することができます。

#using ディレクティブに指定したファイル名は次の順番で検索されます。

  • #using ステートメントで指定されたパス
  • 現在のディレクトリ
  • .NET Framework システムディレクトリ
  • /AI コンパイラオプションで追加されたディレクトリ
  • LIBPATH 環境変数のディレクトリ

mscorlib.dll は、最も基本的な .NET Framework の API を使用するためのアセンブリです。.NET Framework のコア機能を利用するために、この dll ファイルを参照する必要があります。実は C++/CLI コンパイラは既定で mscorlib.dll を参照するため省略できます。この場では、.NET Framework のコードが mscorlib.dll を参照することを理解するために明示的に記述しています。

.NET Framework が共通して利用する基本的なデータ型や例外クラスなどは、すべて System 名前空間で定義されています。コード1の 10 行目で指定している System::Console::WriteLine() という文は、System 名前空間の Console クラスの WriteLine メソッドという静的なメソッドを呼び出しています。

名前空間の考え方や構文に関しては、従来の C++ から変更はありません。コード1のように名前空間を記述することが面倒であれば using ディレクティブを用いて名前空間を解決してもかまいません。

using namespace System;
Console::WriteLine("...");    //OK

上記のように記述すれば、それ以降のコードで System 名前空間を省略しても System 名前空間のメンバにアクセスすることができるようになります。

WriteLine() メソッドの詳細は割愛しますが、このメソッドは引数に様々なデータ型を受け取ることができるようにオーバーロードされています。WriteLine() メソッドに文字列や数値などのデータを渡すと、そのデータを文字列として標準出力に表示します。また、自動的に文字列の末尾に改行文字を追加します。改行が好ましくない場合は、同様の機能を持つ Write() メソッドを利用してください。