.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ファイルを読み書きするには?
文字列中の指定された位置の文字列を取得するには?
長いパスを8.3形式の短いパスに変換するには?
文字列をシフトJISとしてバイト列に変換するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


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 記事ランキング

本日 月間