.NET Framework SDKで始める.NETプログラミング(前編)

7.Hello World展覧会(4)
- マネージド C++ -

デジタルアドバンテージ 遠藤孝信
2001/02/10

p.1 p.2 p.3 p.4 p.5 p.6 p.7 p.8 p.9 p.10 p.11 p.12

マネージド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ファイルを作成することができた。

cl chello.c

 こうして生成されたchello.exeは、.NET SDKをインストールしていないPCでも実行することができた。

関連記事(Insider.NET内)
特集
.NET Framework入門
Insider's Eye
Visual Studio.NETベータ1日本語版の入手法を総括する
関連リンク
マイクロソフトの.NET Framework SDKベータ1 日本語版のダウンロード・ページ
.NET Framework SDKベータ1(英語版)のダウンロード・ページ
IEのホームページ
Microsoft Data Access Components (MDAC) 2.6 RTM (2.60.6526.3) 日本語版 ダウンロード・ページ
最新障害情報ページ
 

 INDEX
  [特集] .NET Framework SDKで始める.NETプログラミング(前編)
    1..NET Framework SDKとは?
    2..NET Framework SDKをインストールする前に
    3..NET SDKのインストール
    4.Hello World展覧会(1)
    5.Hello World展覧会(2) - C# -
    6.Hello World展覧会(3) - VB.NET,JScript.NET -
  7.Hello World展覧会(4) - マネージド C++ -
    8.Hello World展覧会(5) - MSIL -
    9.Hello World展覧会(6) - Windows Forms -
   10.Hello World展覧会(7) - Webサービス -
   11.Hello World展覧会(8) - Webアプリケーション -
 
  [特集].NET Framework SDKで始める.NETプログラミング(後編)

 



Insider.NET フォーラム 新着記事
  • 第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用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間