- PR -

VC++6.0で作成したDLL内でVB.NETのStringBuilderを編集したい

投稿者投稿内容
トモ
会議室デビュー日: 2004/05/06
投稿数: 4
投稿日時: 2004-05-06 18:18
初めて投稿します。トモと申します…

VC++6.0で作成したDLLをVB.NETで利用したいと考えています。
具体的には、
VB側からDLLへバッファを渡し、DLL内で値を詰める、という作業です。
(VC側のDLLですが、MFCを使用していません…;;
過去ログを調べたのですが、MFCを使用しているパターンしか探せなかったので…

コードは以下のようになっています。

---- VC DLL -----
void WINAPI GetStr( BSTR argStr )
{
SysFreeString(argStr);
argStr = SysAllocStringByteLen( "TEST", 4 );
}
---- VB ----
Declare Sub GetStr Lib "TestDLL" (ByVal argStr As StringBuilder)
----呼び出し部----
Private Sub GetChar()
Dim tmpStr As New StringBuilder(256)
GetStr(tmpStr)
MsgBox(tmpStr.ToString)
End Sub

結果は、空文字列になってしまいます…
SysFreeStringで解放をしてから…?などと思い、やってみましたが、ネイティブ例外が発生してしまったり…(TT
DLL側の引数を BSTR以外にもLPSTR等試してみたのですが、うまく行きませんでした…
この手の質問を多く見かけ、参考にはしているのですがいまいちうまくいきません。
よろしければご指導の程お願いしますm(_ _)m
PPN
会議室デビュー日: 2003/07/23
投稿数: 2
お住まい・勤務地: 横浜
投稿日時: 2004-05-06 18:34
はじめまして

引数の値渡しを参照渡しにする必要があると思います。

>---- VC DLL -----
>void WINAPI GetStr( BSTR argStr )
>{
>SysFreeString(argStr);
>argStr = SysAllocStringByteLen( "TEST", 4 );
>}

---- VC DLL -----
void WINAPI GetStr( BSTR *argStr )        /* ポインタ渡し */
{
SysFreeString(*argStr);
*argStr = SysAllocStringByteLen( "TEST", 4 );
}

>---- VB ----
>Declare Sub GetStr Lib "TestDLL" (ByVal argStr As StringBuilder)
>----呼び出し部----
>Private Sub GetChar()
>Dim tmpStr As New StringBuilder(256)
>GetStr(tmpStr)
>MsgBox(tmpStr.ToString)
>End Sub

---- VB ----
Declare Sub GetStr Lib "TestDLL" (ByRef argStr As StringBuilder) 'ByValをByRefにする
----呼び出し部----
Private Sub GetChar()
Dim tmpStr As New StringBuilder(256)
GetStr(tmpStr)
MsgBox(tmpStr.ToString)
End Sub

VB.NETではやったことはありませんがVC++とVB6.0では動作しました。(無責任ですいません)
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-05-06 18:41
 「SysFreeStringってなに?」と思ってMSDNを見たのですが・・・これ、メモリリークを起こしません?っつうか、StringBuilderで確保したところをSysFreeStringで解放していいのか???
トモ
会議室デビュー日: 2004/05/06
投稿数: 4
投稿日時: 2004-05-06 18:58
トモです。早速のご返答有難うございます。

>PPNさん
有難うございます。早速試してみたいと思います(^^

>Jittaさん
確かに…言われてみると、解放してしまっていいのでしょうか…。
BSTR型なので=FreeStringと考え付いてしまった次第です。
この辺はもう少し試しながら調べてみます。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-05-06 19:07
なんか根本的な疑問ですけど、このDLL変じゃないです?
PRNさんのように修正したらいけるように思いますけど、そもそもこれ、バッファを渡す意味ないですよね?

# SysFreeString とか見つけられなかったのでちょっと誤解してるかもしれませんが。
トモ
会議室デビュー日: 2004/05/06
投稿数: 4
投稿日時: 2004-05-06 19:15
トモです。

>なちゃさん
確かに…バッファを渡さずに、戻り値で、という形で十分な気もします(^^;
以下の用にDLL側にメソッドを追加し、テストしてみたのですが…
BSTR WINAPI GetStr2( void )
{
return SysAllocString( _T("TEST")) ;
}
予期せぬエラー…
もう少し、文字列のマーシャリングについて調べて(理解して)見ようと思います(TT
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-05-06 19:18
引用:

Jittaさんの書き込み (2004-05-06 18:41) より:
 「SysFreeStringってなに?」と思ってMSDNを見たのですが・・・これ、メモリリークを起こしません?っつうか、StringBuilderで確保したところをSysFreeStringで解放していいのか???


いいわけないですよね…
というか、そもそもマーシャリングの関係で、StringBuilderが確保したのとは違うとこが渡されているような気がします。
※WIN32関連は素人なので例によって誤解してるかもしれませんが。

--追記--
SysFreeStringとかについて書いてあるのみつけました。私が単純に思ってたのと全然違いました。
というわけで、上記辺りはどうなるのかやっぱり分かりません…失礼。

[ メッセージ編集済み 編集者: なちゃ 編集日時 2004-05-06 19:26 ]
トモ
会議室デビュー日: 2004/05/06
投稿数: 4
投稿日時: 2004-05-06 19:58
トモです。

やはり、メモリリークは起こしていますね…
しかもかなり膨大に(TT

GetStr呼び出し前にtmpStrに初期値を設定し、
DLL内でその値を取得しようとしましたが、それもうまく行きませんでした。
(文字列、文字ともに取得できていない)

---- BSTRの内容をファイルへ出力
int lenStr = SysStringByteLen( argStr);
char* strTemp ;
strTemp = new char[ lenStr + 1 ] ;
wcstombs( strTemp, argStr, lenStr ) ;
FILE* fpTemp = fopen( FILEPATH , "a+" ) ;
fprintf( fpTemp, "%s\nLen=%d\n", strTemp, lenStr ) ;
fclose(fpTemp);

普通のStringに対してなら上記のコードは正常に機能したのですが…
やはり、StringBuilderが確保した領域はDLL側に渡ってきてないのでしょうか。
となると、引数の編集は出来ない…?

スキルアップ/キャリアアップ(JOB@IT)