.NET Framework SDKで始める.NETプログラミング(前編)
7.Hello World展覧会(4)
デジタルアドバンテージ 遠藤孝信 |
マネージドC++版Hello World
中間コード形式であるMSILのコードを生成するC++は、マネージド拡張されたC++(Managed Extensions for C++)、あるいはマネージドC++(Managed C++)と呼ばれ、これまでのC++と区別されるようになった。これに対し、特定のハードウェア・プラットフォームやOS向けのネイティブ・コードを出力する従来のC++は、アンマネージドC++(Unmanaged C++)と呼ばれる。マネージドC++では、CLRに対応するために言語仕様が若干拡張されている。
マネージドC++で記述したHello Worldプログラムは次のようになる。
|
|||||||||||||||
マネージドC++版Hello Worldのソースコード | |||||||||||||||
|
3行目の“#using”は、C#やVB.NETのコードになかった余分なコードだが、これはCLR対応のためにC++に追加されたキーワードの1つで、これによりC++コンパイラは、クラス・ライブラリやネームスペースについての情報を取得できるようになる。ここで指定されているmscorlib.dll(DLLファイル)には、.NET Frameworkの基本的なクラス・ライブラリのアセンブリが含まれており、Consoleクラスもここに含まれているため、この指定が必要になってくる。これはマネージドC++コードでのお約束の1つだ。
C++でマネージド・コードを出力する場合には、コンパイル・オプションとして“/CLR”を指定する。“/CLR”オプションなしでこのHello Worldプログラムをコンパイルしても、「マネージ ターゲット コードには '#using <mscorlib.dll>' と /CLR スイッチが必要です。」というコンパイル・エラーが出力されてしまう。
マネージドC++版Hello Worldをコンパイル、実行したところ |
C++のHello Worldプログラムでは、出力ストリームの“cout”を使用するのが一般的である。
|
|
coutストリームを使用する一般的なC++のHello World |
しかし.NET SDKでは、このように“cout”出力ストリームを使用するプログラムは記述できない。そもそも.NET SDKには、iostream.hファイルがない。
ただしVS.NETでは、C++用のヘッダーやライブラリが含まれており、このcout版Hello Worldをコンパイルすることができた。
マネージドC++版Hello World(Cバージョン)
C++はC言語のスーパーセットであるため、C言語で記述したプログラムもコンパイルすることができる。次のコードはC言語の仕様の範囲で記述した、少し懐かしいHello Worldである。
|
|
C言語で記述したHello Worldのソースコード |
このプログラムをコンパイルして実行すると次のようになる。
C言語版Hello Worldをコンパイル、実行したところ |
C++の場合と同じく、“/CLR”オプションを指定することによりマネージド・コードが出力される。ただし、文字出力に使用しているprintf関数は.NETのクラス・ライブラリに含まれるものではなく、C言語の標準ライブラリに含まれるものである(実体は\Program Files\Microsoft.Net\FrameworkSDK\Libにあるファイル)。このクラス・ライブラリはマネージド・コードではないため、生成された実行ファイル(exeファイル)では、PInvoke(Platform Invocation service)と呼ばれる機能を使用しているようだ。
PInvokeは、マネージド・コードからアンマネージド・コードのライブラリを呼び出すために用意されたサービスである。通常このPinvoke機能は、Win32 APIをC#やC++プログラムから呼び出すために使用される。例えば次のコードは、C#のプログラムから、メッセージ・ボックスを表示するためのWin32 APIであるMessageBoxAというAPIを呼び出した例である。
|
||||||||||||
メッセージ・ボックス版Hello World(C#からPInvokeを使用してWin32 APIを呼び出したもの) | ||||||||||||
PInvokeはマネージド・コードからアンマネージド・コードのライブラリを呼び出すために用意されたサービスである。PInvokeを使用してアンマネージド・コードのDLLを呼び出すには、呼び出す関数を[DllImport]属性を指定して宣言しておく。 | ||||||||||||
|
マネージド・コードからPInvokeを使用してアンマネージド・コードであるWin32 APIを呼び出すには、あらかじめ呼び出すAPIの型を[DllImport]属性を付けて宣言しておく必要がある(8〜10行目)。DllImport属性のパラメータに指定した“user32.dll”は、MessageBoxAが含まれるDLLファイルである(\WINNT\System32\user32.dll)。
プログラムをコンパイルし、実行すると、次のようなメッセージ・ボックスが表示される。
メッセージ・ボックス版Hello Worldを実行したところ |
プログラムをコンパイルし、生成されるEXEファイルを実行すると、このようなメッセージ・ボックスが表示される。 |
ちなみに、Windows Formsを使用して上記と同様のメッセージ・ボックスを表示するには
System.WinForms.MessageBox.Show("Hello
World!", "From C#"); |
とするだけでOKだ。これはstaticメソッドであるため、単体で使用することができる。Pinvokeを使用したメッセージ・ボックスは直接Win32 APIを呼び出しているのに対し、この呼び出しはWin32 APIを実装したクラス・ライブラリを呼び出している。プログラムでメッセージ・ボックスを使いたいのであれば当然こちら側を使用すべきだ。こうしておけば、将来的にWindowsが64bit化され、user32.dllがuser64.dllになったとしても、あるいはMessageBoxAというAPIを持たないLinuxに.NET Frameworkが移植されたとしても、プログラムを修正する必要はなくなる。最終的にどのような実装になるかは分からないが、Windows Formsを使用しておけば、少なくとも小さなウィンドウを表示してメッセージを出力するという動作は保証されている。
文献によっては、.NET SDKを利用して出力できるのはマネージド・コードのみという記述をしているものもあるようだが、/CLRオプションなしで、上のchello.cを以下のようにコンパイルすると、アンマネージドな、つまり通常のEXEファイルを作成することができた。
cl chello.c |
こうして生成されたchello.exeは、.NET SDKをインストールしていないPCでも実行することができた。
- 第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用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|