2007年05月02日

[C#]DLLから文字列(char*)を取得する際のゴタゴタ

C#のアプリで、昔ながらのstdcallなDLLから文字列を取得する際、
char*をStringBuilder型として取得してました。

これはこれで実績があったのですが、
つい最近期待した動きになっていないことが
発覚しました。

 ⇒と前フリしてみましたが、実は文末にあるように
  単なるミスだった説が浮上していたり・・・(^-^;)
  まぁ色んな方法があるぞ、ということで(汗


●現象
 例えば、TestAPI.dllのTESTFUNCという関数が以下のような
 プロトタイプ宣言だとします。

 void __stdcall TESTFUNC( int* buf_max_size, char* buf, int* buf_len );

 上記をC#で使う際、今までは以下のように宣言してました。

 using System;
 using System.Runtime.InteropServices;
 using System.Text;
 
 (略)
 
 // bufはStringBuilder型で取得する
 [DllImport("TestAPI.dll", CharSet = CharSet.Auto)]
 private static extern void TESTFUNC(
  ref int buf_max_size,
  [MarshalAs(UnmanagedType.LPStr)] StringBuilder buf,
  ref int buf_len
 );

 TESTFUNCは文字列の末尾をスペースで埋めてから返しています。
 
 buf_max_size=10で"abc"という文字列を返す場合、
 buf="abc "と末尾にスペースが入って返ってきます。
 
 VisualStudio.NET 2005でしか試していませんが、
 上記のソースだとDebugビルド時のみ期待どおり動作しました。
 
 Releaseビルドで実行した場合は、bufの末尾のスペースが
 一部化けてしまい、Trimでのブランクカットが期待どおりに
 動いていませんでした。
 
●対応
 原因は深く追っていませんが、文字のバイト数の違いとか
 そのあたりが怪しい気がしてます。
 
 で、そもそも悩む必要はなくて、C言語っぽく扱えば良いのでは?
 という当たり前の結論に達しました。
 
 C言語のcharは1バイト・・・すなわちC#言語のbyte型です。
 そこで、以下のようにbyte型の配列で受け取るように
 ソースを修正しました。

 using System;
 using System.Runtime.InteropServices;
 
 (略)
 
 // bufはbyte[]型で取得する
 [DllImport("TestAPI.dll", CharSet = CharSet.Auto)]
 private static extern void TESTFUNC(
  ref int buf_max_size,
  [MarshalAs(UnmanagedType.LPArray)] byte[] buf,
  ref int buf_len
 );

 当たり前ではありますが、この対応でばっちりでした。
 もしbyte[]を文字列で見たいのであれば、以下のような
 ソースで簡単に確認できます。

 using System.Text;
 (略)
 Console.WriteLine(Encoding.ASCII.GetString(buf));

まだまだ最後に頼るのはバイト列・・・なことを実感
した一件なのでした。


と、ここまで書いて、念のためネットで調べてみました。
http://www.atmarkit.co.jp/fdotnet/dotnettips/025w32string/w32string.html

確かにStringBuilder型で受け取っているようです。
ふと、DllImport時にMarshalAsしてないことに気づきました。

自分、[MarshalAs(UnmanagedType.LPStr)] StringBuilderとしてたけど、
もしかして余計なお世話だった・・・?
ってかオイラの宣言ミスなだけ??

でも、もういいや。byte[]最強の方向で。
posted by てるとみ at 16:27| Comment(0) | TrackBack(0) | プログラミング/.NET関係 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

この記事へのトラックバックURL
http://blog.seesaa.jp/tb/40601169

この記事へのトラックバック