tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルdllから文字列を取得する
記事No7021
投稿日: 2008/02/14(Thu) 18:21
投稿者すん
失礼致します。
どうか皆様のお力をお貸し下さい。

「dllファイルの関数を呼び出し、戻り値を画面に表示する」
という単純なツールをVB.NETで作成しています。
dllファイルはVC++で作成しています。

戻り値がlong型、double型の関数に関しましては、問題なく動作しています。
=====OK=====
・dllファイル内
__declspec(dllexport) double __stdcall [関数名]( [引数] );

・VB.NET製ツール内
Declare Ansi Function [関数名] Lib [dllファイル名] Alias [該当する値] ( [引数] ) As Double
===========

今回、皆様のお力をお借りしたいのは、戻り値が「char*」の関数です。
=====NG=====
・dllファイル内
__declspec(dllexport) char* __stdcall [関数名]( [引数] );

・VB.NET製ツール内
Declare ■■ Function [関数名] Lib [dllファイル名] Alias [該当する値] ( [引数] ) As ●●
===========
上記“■■”および“●●”の部分の記述はどのようにすればよいのでしょうか?

“■■”の部分は“Ansi/Auto/Unicode”、
“●●”の部分は“String/Char”のいずれかであると思い、
試してみたのですが、上手くいきませんでした。
文字化けしたような値が表示(取得)されます。

アドバイスをお願いいたします。

[ツリー表示へ]
タイトルRe: dllから文字列を取得する
記事No7022
投稿日: 2008/02/14(Thu) 18:48
投稿者Hongliang
その DLL 内関数が返す文字列が char* なら Ansi でいいでしょう(Declare 宣言の文字セットのデフォルトは Ansi)。
返値は IntPtr で受けてください。で、Marshal.PtrToStringAnsi 辺りで文字列に変換してください。

問題はその char* の素性と解放手段ですが。
// 返値がポインタって扱いづらくてやだなぁ。

[ツリー表示へ]
タイトルRe^2: dllから文字列を取得する
記事No7024
投稿日: 2008/02/14(Thu) 19:44
投稿者すん
Hongliang 様、早急なレスをありがとうございました。

お教えいただいた通り、
==========
Declare ansi Function [関数名] Lib [dllファイル名] Alias [該当する値] ( [引数] ) As Intptr
==========
で受け取り、Marshal.PtrToStringAnsiで変換したところ
正常に動作しているようです。

ただ、戻り値がnull(期待値ではない)だったため、
dllから無理やり“KARI”という値を返すようにしてみました。
その結果“KARI”が取得できました。
今度はdllファイル内の処理を見直す必要がありそうです。

// 私も「char*」という仕様が嫌です・・・

[ツリー表示へ]
タイトルRe^2: dllから文字列を取得する
記事No7025
投稿日: 2008/02/14(Thu) 21:19
投稿者すん
解決したかのように思えたのですが・・・まだダメだったようです。

dllをデバッグ(ステップ実行)してみたのですが、
正常な値をリターンしていました。
やはりVB側の宣言・呼出・変換の部分でまだ間違いがあるのでしょうか・・・。
引き続き調査を行います。

他に何か可能性がありましたら、教えていただきたく思います。

[ツリー表示へ]
タイトルRe^3: dllから文字列を取得する
記事No7026
投稿日: 2008/02/14(Thu) 21:57
投稿者Hongliang
むしろ char* の出所が気になります。
ローカル変数を return してたりしませんか?

[ツリー表示へ]
タイトルRe^4: dllから文字列を取得する
記事No7027
投稿日: 2008/02/14(Thu) 23:01
投稿者すん
度々恐れ入ります。

dll側からはxmlファイルから取得した要素を返しています。
==========
typedef struct{
 〜略〜
    char      AAA[100 + 1];
    long      BBB;
    double    CCC;
 〜略〜
}名前;
==========
といった形になっており、“名前.BBB”と“名前.CCC”はVB側で取得可能です。
“名前.AAA”を取得できないというのが、今回の件です。
dll内で“名前.AAA”に期待通りの値が取得できていることは確認できました。

・・・これで何か分かりますでしょうか。

[ツリー表示へ]
タイトルRe^5: dllから文字列を取得する
記事No7030
投稿日: 2008/02/15(Fri) 10:09
投稿者Hongliang
XML ファイルとかはどうでもいいです。返値がただの値ならコピーされるだけなんで正しく返されるのは当然です。
スタックに確保した静的配列をポインタとして返してるんじゃないか、と聞いています。スタックに「静的配列を持った構造体」を置いてその静的配列をポインタとして返すのも同じことですよ。
関数を越えてポインタを扱うなら、malloc なり new なり HeapAlloc なりでヒープに領域を確保しなければなりません。もちろん DLL はその領域の解放手段も用意する必要があるでしょう。

[ツリー表示へ]