【3/18〜】Amazon、VMwareが語る『クラウドの未来』 スラッシュドット    はてなブックマーク  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-
  TomcatやJBossなどAPサーバ環境に関する
情報を集約! “業務”用APサーバ大百科

New!
  一気に解説! 最新のクラスタストレージ
「RAIDを超えたストレージ基準」……など

New!
  クラウド的ユーザー体験の変化は脅威か?
仮想化技術を使いこなす運用管理術を紹介

New!

  上司や部下、部署内メンバーとの情報共有
を“ガラッ”と変えるコラボツールとは?

New!
  おばかアプリ選手権、第4弾開催中!!
ムダにカッコよくてくだらない作品求ム!

  社内ファイルサーバを“クラウド”に統合
VPN直結「クラウド型ストレージ」を紹介

  Twitterのアカウントはなぜ突破された?
メールによる新手の攻撃手法とその対策

  もう仮想化のお試しフェイズは終わりだ!
Hyper-V 2.0が基幹システムも仮想化

  美人!? まあまあ? 気になる いやし系!!
PV急増で「美人時計」がとった手段とは?

  クライアント企業から求められる人材
⇒IT技術と経営戦略を併せ持つ「戦略家」

  .NET編集長が実践する「技術情報検索術」
サンプル・コードを簡単に探す“技”は?

  業務効率と情報セキュリティ対策を両立!
手間なく確実に機密情報を守る方法とは?

  進化を続ける富士通ストレージETERNUS DX
製品開発者の自信を裏付けるものとは何か

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

  【CTC事例】約30の基幹システムを統合!
膨大なバッジジョブを制御した方法は?

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

  その数、なんと400台以上! グループ内
サーバの「統合管理」によるメリットは?