【2/17】今年は「濃厚」技術トーク!@ITメールセミナー スラッシュドット    はてなブックマーク  Yahoo!ブックマークに登録  印刷
 

.NET TIPS

Win32 APIやDLL関数に文字列や文字列バッファを渡すには?

泉 祐介
2003/05/09

 TIPS:Win32 APIやDLL関数を呼び出すには? では、.NETのプログラムからWin32 APIやDLLファイルにある関数を呼び出すための基本的な手順を解説している。ここではそれらDLL関数のパラメータが、文字列や文字列バッファの場合について解説する。

DLL関数に文字列を渡す場合

 .NET FrameworkからWin32 APIやDLL関数を呼び出す場合に、パラメータとして文字列を渡す場合は、そのパラメータや戻り値の型としてstring型を指定する。ただし一口に文字列といっても、この場合にはANSI文字セット(日本語の場合はシフトJIS)で表現された文字列と、Unicodeで表現された文字列の2種類があるので注意が必要だ。ちなみに、.NET Frameworkの内部では文字列をUnicodeで処理しているが、Win32 APIやDLL関数に文字列を渡す場合は、デフォルトでANSI文字セットによる表現に変換される。

 Win32 APIについては、ほとんどの場合ANSI文字セットの文字列を扱うもの(ANSI版)とUnicode文字列を扱うもの(Unicode版)の2種類のAPIが用意されている。例えば、現在のコンソール・ウィンドウのタイトル文字列を設定するSetConsoleTitleというWin32 APIがある。このAPIのANSI版、およびUnicode版の書式はそれぞれ次のようになっている。

BOOL SetConsoleTitleA(LPCSTR lpConsoleTitle);
BOOL SetConsoleTitleW(LPCWSTR lpConsoleTitle);

 関数名の後ろに、ANSI版であることを表す接尾辞「A」、あるいはUnicode版であることを表す接尾辞「W」が付されている点に注意してほしい。冒頭で述べたとおり、デフォルトではANSI文字セットで表現された文字列が渡されるので、SetConsoleTitleA関数(ANSI版)をC#で宣言するには、以下のように、LPCSTRに対してstring型を指定するだけでよい。

[DllImport("kernel32.dll")]
extern static bool SetConsoleTitleA(string lpConsoleTitle);

 DllImport属性(System.Runtime.InteropServices名前空間)と、externおよびstaticを付けた関数宣言については、TIPS:Win32 APIやDLL関数を呼び出すには? で解説しているので参照していただきたい。

 なお、接尾辞のAは省略可能である。従って、以下のように宣言しても構わない。

[DllImport("kernel32.dll")]
extern static bool SetConsoleTitle(string lpConsoleTitle);

 一方、Unicode版を使用する場合は、以下のようにDllImport属性のCharSetフィールドに、CharSet列挙型(System.Runtime.InteropServices名前空間)のメンバであるCharSet.Unicodeを指定する。

[DllImport("kernel32.dll", CharSet=CharSet.Unicode)]
extern static bool SetConsoleTitleW(string lpConsoleTitle);

 ANSI版と同様、接尾辞のWは省略しても構わない。

 ところで、MSDNドキュメント(英語)では、SetConsoleTitleの書式が以下のように表記されている。

BOOL SetConsoleTitle(LPCTSTR lpConsoleTitle);

 LPCTSTRは、Windows 9xの場合はANSI文字セットによる文字列、Windows NTの場合はUnicodeによる文字列を表す。つまり、文字列をANSI文字セットで内部処理しているWindows 9x上ではANSI版のSetConsoleTitleA関数を、文字列をUnicodeで内部処理しているWindows NT上ではUnicode版のSetConsoleTitleW関数をそれぞれ呼び出すことを意味している。

 ただし、実際にはSetConsoleTitleという名前の関数のエントリがDLLに存在するわけではない。プラットフォームSDKでは、ヘッダ・ファイルにSetConsoleTitleという名前のマクロが定義されており、プラットフォームに応じてANSI版(SetConsoleTitleA関数)、あるいはUnicode版(SetConsoleTitleW関数)の呼び出しに置き換えられるようになっている。

 このようなプラットフォームに応じた呼び出し関数の変更は、.NET Frameworkで実現することも可能である。具体的には、DllImport属性のCharSetフィールドにCharSet.Autoを設定すればよい。

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
extern static bool SetConsoleTitle(string lpConsoleTitle);

 いささか説明が長くなってしまったが、この関数の具体的な使用例として、コマンド・プロンプトのタイトル文字列を変更するサンプル・プログラムを以下に示しておく。ここではANSI版のSetConsoleTitleを利用した。

// settitle.cs

using System;
using System.Runtime.InteropServices;

class SetTitle {
  [DllImport("kernel32.dll")]
  private static extern bool SetConsoleTitle(string lpConsoleTitle);

  static void Main() {
    SetConsoleTitle("タイトル文字列を変更しました。");
    Console.ReadLine();
  }
}

// コンパイル方法: csc settitle.cs
現在のコンソール・ウィンドウのタイトル文字列を変更するプログラム(settitle.cs)

 なお、プログラムが終了するとタイトル文字列がもとに戻ってしまうため、すぐに終了しないように最後にConsole.ReadLineメソッドを呼んでいる。

DLL関数に文字列バッファを渡す場合

 Win32 APIやDLL関数の中には、戻り値となる文字列を格納するためのバッファを呼び出し元で用意し、そのバッファへの参照(ポインタ)をパラメータに指定しなければならない場合がある。GetConsoleTitleというWin32 APIもそのような関数の1つである。このWin32 APIは現在のコンソール・ウィンドウのタイトル文字列を取得する関数であり、書式は次のとおりである。

DWORD GetConsoleTitleA(LPSTR lpConsoleTitle, DWORD nSize);
DWORD GetConsoleTitleW(LPWSTR lpConsoleTitle, DWORD nSize);

 lpConsoleTitleが取得したタイトル文字列を格納するバッファを指定するパラメータである。もう1つのパラメータであるnSizeには、そのバッファの大きさ(格納できる文字数)を指定する。

 このようなDLL関数を.NET Frameworkから呼び出して利用する場合は、StringBuilderクラス(System.Text名前空間)を利用すればよい。例えば、GetConsoleTitleA関数(ANSI版)をC#で宣言すると次のようになる(接尾辞は省略している)。

[DllImport("kernel32.dll")]
extern static uint GetConsoleTitle(System.Text.StringBuilder lpConsoleTitle, uint nSize);

 Unicode版を使用する場合、あるいはプラットフォームに応じて呼び出す関数を変更する場合は、通常の文字列を渡す場合と同様にCharSetフィールドを指定する。

 以下に、GetConsoleTitleの具体的な使用例を示しておく。

// gettitle.cs

using System;
using System.Text;
using System.Runtime.InteropServices;

class GetTitle {
  [DllImport("kernel32.dll")]
  private static extern uint GetConsoleTitle
    (StringBuilder lpConsoleTitle, uint nSize);

  static void Main() {
    StringBuilder buf = new StringBuilder(256);
    GetConsoleTitle(buf, (uint)(buf.Capacity));
    Console.WriteLine(buf.ToString());
    // 出力例: コマンド プロンプト - gettitle
  }
}

// コンパイル方法: csc gettitle.cs
プロセッサのSSE命令セットのサポートの有無を調べるプログラム(ssechk1.cs)

 このサンプル・プログラムでは、そのプログラムを実行しているコマンド・プロンプトのタイトルバーの文字列を取得し、画面に表示している。End of Article

カテゴリ:クラス・ライブラリ 処理対象:Win32 API
使用ライブラリ:DllImport属性(System.Runtime.InteropServices名前空間)
使用ライブラリ:StringBuilderクラス(System.Text名前空間)
関連TIPS:Win32 APIやDLL関数を呼び出すには?
 
この記事と関連性の高い別の.NET TIPS
Win32 APIやDLL関数を呼び出すには?
INIファイルを読み書きするには?
文字列中の1文字を取得するには?
Win32 APIのWin32エラー・コードを取得するには?
Win32 APIやDLL関数に構造体を渡すには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」

ホワイトペーパーTechTargetジャパン

Insider.NET フォーラム 新着記事

@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

RSSフィード

スキルアップ/キャリアアップ(JOB@IT)

- PR -
- PR -

お勧め求人情報

キャリアアップ 〜JOB@IT
@IT Special -PR-
  企業の仮想化に足りない“発想”とは?
仮想化運用管理のキモは意外なところに!

New!
  操作もマニュアルも分かりやすい!
ユーザー視点で開発されたPC管理ツール

New!
  仮想化すればコストは削減できるか?
仮想化に必要な「3つの視点」を解説する

  セキュリティを知り尽くす上野氏が登壇!
@ITメールソリューションLive! in Tokyo

  運用管理の課題を“2つの観点”から分析
ユーザー満足度の高い「仮想環境」とは?

  世界に通用するストレージの作り方とは?
製品に込めた思いを富士通の開発者に聞く

  OSSで手間も時間も、障害も減った――
「マピオンの事例」オープンソース活用法

  「ノートPCの持ち出し禁止」で大丈夫?
情報漏えいを防ぐ管理手法とインフラは?

  1日の処理を1秒に――MySQLの達人が語る
「コスト削減」できるチューニング

  ドキュメント作成を自動化して、SEの作業
効率を大幅アップ! Visio 2007の魅力

  急速に広がるHyper-Vでのサーバ仮想化
そのベストプラクティスをデルが解説

  @IT主催セミナーで語られた、「担当者に
求められるセキュリティ対策」をレポート

  @IT「Windows 7」 特設サイトオープン!
最新情報・移行ノウハウを公開しています