- 題名: C#でDLLを使う時の引数の型
- 日時: 2005/04/09 16:53:50
- ID: 10330
- この記事の返信元:
- (なし)
- この記事への返信:
- [10335] Re[1]: C#でDLLを使う時の引数の型2005/04/10 20:06:56
- ツリーを表示
■No10335に返信(antさんの記事) > StringBuilderで行うのがいいと思いますが、以下のように > してみてはどうでしょうか。 > bool mp3infp_GetValue(string Tag, ref System.Text.StringBuilder Buf); 関数のシグネチャからすると、この関数は自身で用意したアンマネージメモリ のアドレスを第二引数に返すのですよね。 アンマネージメモリの内容から StringBuilder クラスのインスタンスを作成 した後、相互運用マーシャラはアンマネージメモリを解放しますが、解放には CoTaskMemFree 関数が使われることになっています。mp3infp_GetValue 関数 のソースを読んでいないのですが、この関数は CoTaskMemAlloc 関数を使って メモリを割り当てるのでしょうか? 仮に割り当てるとして、呼び出し元がそれ を解放する仕様なんでしょうか? CoTaskMemFree 関数での解放が不適切なアンマネージメモリのアドレスは、一 旦 IntPtr 型の出力パラメータで受け取った後、明示的にマーシャリングする ことになります。 それから、bool 型の戻り値のアンマネージ型は既定で 16 bit 幅じゃないで す? 明示的に属性を指定する必要がある気がするのですが、どうでしょうか?
■No10346に返信(show_landさんの記事) > ソースには CoTaskMemAlloc を使っていないようですが、これは、いわゆる > 「メモリリーク」ってやつですか。良く分からないので、それらしい現象が > 出たら考えることにします。 ソースを読みましたが、返ってくるアドレスは static な CString オブジェ クトを LPCSTR 型に型変換して得たものですよね。CString クラスが管理する メモリですから、メモリリークは発生しません。反対に、勝手に解放してはい けないメモリです。 ただ、CoTaskMemFree 関数による解放は失敗するでしょうから、実害はないは ずです。あとはプログラマの良識や美的センスの問題でしょうね。:-) > 戻り値をshortにしてもOKでしたが、この際、C#の顔を立てて、boolで行く > ことにします。 これはこちらの書き方が下手すぎました。BOOL 型は 32 bit 幅だが、bool 型 へ変換する際、既定では相互運用マーシャラは BOOL 型の値を 16 bit 分しか 見てくれないのではないか? という疑問だったんです。 指摘ではなく疑問なのは、bool 型の戻り値に属性を指定している例を見た記 憶がないからなのですが、 http://www.microsoft.com/japan/msdn/library/ja/cpguide/html/cpcondefaultmarshalingforbooleans.asp には、 | UnmanagedType.VariantBool : 2 バイトの整数値。値 -1 は TRUE を表し、 | 0 は FALSE を表します。これは Boolean パラメータの既定の形式です。 とあります。よくあるドキュメントの不備なのか、これまたよくある意味の取 り違えなのか、レジスタで返される戻り値ではそれほど問題にならないだけな のか、「戻り値はパラメータじゃないよ」「じゃあ、何なのさ?」ということ なのか。まぁ、余談でした。
分類:[.NET]
C#でDLLを使おうと思っています。**の引数の型が違うらしく、 うまくデータを取り込めません。 http://www.atmarkit.co.jp/fdotnet/dotnettips/024w32api/w32api.html というリンクから有益な知識を得まして、使えるようになった のですが、うまく行かない関数が出まして、皆様のお知恵を拝 借いたしたく、お願いします。 そのDLLにはソースも付いていまして、問題の関数は以下のよう になっています。 BOOL __stdcall mp3infp_GetValue(const char *szValueName, char **buf); C#では以下のようにしました。 [DllImport("mp3infp.dll")] static extern bool mp3infp_GetValue(string Tag, [Parame2]); 第一引数は、別の関数で確認しているので、これで問題ありません。 問題は第二引数で、「バッファのポインタを受け取るポインタ」と いうのですから、 (1) bool mp3infp_GetValue(string Tag, ref string Buf); とやったのですが、「stringはrefに変換できない」のでダメ。 string型ではなく、StringBuilder かな、と思ったので (2) bool mp3infp_GetValue(string Tag, System.Text.StringBuilder Buf); と宣言し、呼び出しは buf = new System.Text.StringBuilder(256); res = mp3infp_GetValue("SIZK",buf); のようにしました。エラーは出ませんが、予想もできない文字列 が入っています。(数字のはずですが、キャラクタ画素でした) Cの文字列はCharの配列だったと思い出し、 (3) bool mp3infp_GetValue(string Tag, ref char[] Buf); とやったのですが、「変換できない」のでダメ。 もう手詰まりで、他にやる方法が思い浮かびません。 VB6では Declare Function mp3infp_GetValue Lib "mp3infp.dll" (ByVal Tag As String, ByRef buf As String) As Boolean できちんと動いています。 ちなみに、mp3infp.dll は以下のURLで配布されています。 C++のソースもあります。 http://www.win32lab.com/fsw/mp3infp/index.html