.NET Framework SDKで始める.NETプログラミング(前編)
7.Hello World展覧会(4)
- マネージド C++ -
デジタルアドバンテージ 遠藤孝信
2001/02/10 |

|
マネージドC++版Hello World
中間コード形式であるMSILのコードを生成するC++は、マネージド拡張されたC++(Managed Extensions for C++)、あるいはマネージドC++(Managed
C++)と呼ばれ、これまでのC++と区別されるようになった。これに対し、特定のハードウェア・プラットフォームやOS向けのネイティブ・コードを出力する従来のC++は、アンマネージドC++(Unmanaged
C++)と呼ばれる。マネージドC++では、CLRに対応するために言語仕様が若干拡張されている。
マネージドC++で記述したHello Worldプログラムは次のようになる。
1: // cpphello.cpp
2:
3: #using <mscorlib.dll>
4:
5: using namespace System;
6:
7: void main()
8: {
9: Console::WriteLine("Hello Managed C++ World!");
10: } |
|
マネージドC++版Hello Worldのソースコード |
|
1: |
コメント行。 |
|
2: |
#usingはCLR対応のために追加されたキーワード。これによりC++コンパイラは、クラス・ライブラリやネームスペースに関する情報を取得する。 |
|
5: |
Systemネームスペースを使用するという宣言。C++ではこのように“namespace”を明記する。 |
|
7: |
プログラムが起動されると最初に実行されるmain関数。 |
|
9: |
他の言語と同じく、出力したい文字列を指定して、ConsoleクラスのWriteLineメソッドを呼び出す。 |
|
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”を使用するのが一般的である。
1: #include <iostsream.h>
2:
3: main() {
4: cout << "Hello World";
5: } |
|
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である。
1: /* chello.c */
2:
3: #include <stdio.h>
4:
5: void main()
6: {
7: printf("Hello Managed C World!\n");
8: } |
|
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を呼び出した例である。
1: // pinvoke.cs
2:
3: using System;
4: using System.Runtime.InteropServices;
5:
6: class PInvokeClass
7: {
8: [DllImport("user32.dll")]
9: public static extern int
10: MessageBoxA(int h, string m, string c, int type);
11: static void Main()
12: {
13: MessageBoxA(0, "Hello PInvoke World!", "From
C#", 0);
14: }
15: } |
|
メッセージ・ボックス版Hello World(C#からPInvokeを使用してWin32
APIを呼び出したもの) |
PInvokeはマネージド・コードからアンマネージド・コードのライブラリを呼び出すために用意されたサービスである。PInvokeを使用してアンマネージド・コードのDLLを呼び出すには、呼び出す関数を[DllImport]属性を指定して宣言しておく。
|
|
4: |
8行目のDllImportを使用するために必要なネームスペース。 |
|
6: |
ここでは“PinvokeClass”というクラス名をつけた。 |
|
8〜10: |
PInvokeを使用してアンマネージド・コードのDLLを呼び出す場合には、このように呼び出す関数を[DllImport]属性を指定して宣言しておく必要がある。 |
|
13: |
Win32 APIであるMessageBoxAの呼び出し。 |
|
マネージド・コードから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ファイルを作成することができた。
こうして生成されたchello.exeは、.NET SDKをインストールしていないPCでも実行することができた。