- ベストアンサー
DLL VBとC++での関数呼び出しについて
- VBAからVC++2005のDLLを呼び出すプログラムを書いています。DLLのreturnの直前にMessageBoxで表示させるとVB側で作成したcpp_proc関数を呼ぶとVBアプリが落ちる現象が発生しました。
- VB側の引数の値が原因なのか、DLLの戻り値に問題があるのか確認したいです。また、DEFの@1が無くても動くのか、意味が知りたいです。
- C++側で定義されているcpp_proc関数は、inpとoutという2つの引数を取り、MessageBoxでデバッグ表示を行った後に0を返します。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
こんにちは。補足頂きました。確かに可笑しいです。 SysAllocStringByteLen()を使用してVBに送り返すそうです。此れでは駄目でしょうか。 // //VC側 // #include"exsample.h" #include<string.h> #include<comutil.h> #pragma comment(lib, "comsupp.lib") #pragma comment(lib, "comsuppw.lib") int __stdcall cpp_proc(LPSTR inp, BSTR* out) { CHAR buf[1024]; strcpy(buf, inp); MessageBoxA(0, buf, "化け文字??", MB_OK); // 文字化け? わかりません? // ついでに、outに "結果はゼロです" という日本語文字を返したいです。 // どう書けばよいか、わかりません。 SysFreeString(*out); LPCSTR psz = "結果はゼロです"; *out = SysAllocStringByteLen(psz, ::strlen(psz)); // 戻り値 return 2; } // //VB側 // Public Declare Function cpp_proc Lib "tovba.dll" (ByVal inp As String, ByRef out As String) As Integer Public Sub Test() Dim ret As Integer Dim inp As String Dim out As String inp = "abcdefg" 'out = Space(1024) 必要なし ret = cpp_proc(inp, out) MsgBox ("ret=[" & CStr(ret) & "]") '2が返ります。 MsgBox ("inp=[" & inp & "]") '送った内容 abcdefg MsgBox ("out=[" & out & "]") '「結果はゼロです」という文字を表示させたい。 MsgBox ("outLength=[" & CStr(Len(out)) & "]") '文字数の計測 End Sub
その他の回答 (3)
- machongola
- ベストアンサー率60% (434/720)
こんばんは。補足頂きました。 此れに関しては当方も疑問です。他のQandAでもリークではないのだろうか?と言う話が上がっていますが、其の一方でVisualBasic側によって消去されると言う人も居ます。 ただし、MSDNに書いてあった文章ではないので、真偽の程は定かではありません。 VisualBasicに文字を送り返す為にSysAllocStringByteLen()を使用するのは大方間違いないようです。 http://www.google.co.jp/search?hl=ja&q=sysallocstringbytelen+vb&lr= VisualBasic側で解放されている・・・らしい。 http://www2.big.or.jp/~osamu/Delphi/Tips/key.cgi?key=11 VisualBasic側で解放されない・・・らしい。 http://oshiete1.goo.ne.jp/qa137598.html http://202.218.219.160/bbs/phpBB/viewtopic.php?topic=11384&forum=7&8 此処は一つ、新たな質問を立てて、VisualBasic系やCOM/OLE系に深い知識を持つ方に御意見賜るのも一つの手かもしれません。 当方の知識では、此処が限界であります。
- machongola
- ベストアンサー率60% (434/720)
こんにちは。補足頂きました。 此れでは駄目でしょうか。ExcelVBA2003で表示確認しました。 http://support.microsoft.com/default.aspx?scid=kb;ja;410837 // //VC側 // #include"exsample.h" #include<string.h> #include<comutil.h> #pragma comment(lib, "comsupp.lib") #pragma comment(lib, "comsuppw.lib") int __stdcall cpp_proc(LPSTR inp, LPSTR* out) { CHAR buf[1024]; strcpy(buf, inp); MessageBoxA(0, buf, "化け文字??", MB_OK); // 文字化け? わかりません? // ついでに、outに "結果はゼロです" という日本語文字を返したいです。 // どう書けばよいか、わかりません。 ::strcpy(*out, "結果はゼロです"); // 戻り値 return 2; } // //VB側 // Public Declare Function cpp_proc Lib "tovba.dll" _ (ByVal inp As String, ByRef out As String) As Integer Public Sub Test() Dim ret As Integer Dim inp As String Dim out As String inp = "abcdefg" out = Space(1024) '受け取りに必要 ret = cpp_proc(inp, out) MsgBox ("ret=[" & CStr(ret) & "]") '2が返ります。 MsgBox ("inp=[" & inp & "]") '送った内容 abcdefg MsgBox ("out=[" & out & "]") '「結果はゼロです」という文字を表示させたい。 'DLLで何もしていないので、空白ですが End Sub
補足
動作確認、ありがとうございます。 こちらでも提示して頂いたサンプルの動作は確認できました。 疑問な点が2点あります。 【1】 VB側で out = Space(1024)して送った場合、 C側で「結果はゼロです」と7文字書き込んだ後、VB側で len(out)とすると、書き込んだ文字数分マイナスになり、 1014となります。 1024文字確保したのに戻ってきた場合は 書き込んだ分だけ減ります。 「結果はゼロですよ」と1文字増やすと、戻ってきた場合は1013となります。 何か気持ち悪いですね。 仕組みがわからず、これで良いものか、何か対策が必要?なのか心配しています。 ----------------------------------------- 【2】 あと、VB側で表示させた場合、「結果はゼロです となり、C側でヌル文字がセットしているためか表示が欠落します。 どのような方法が一般的でしょうか? 他の方法もありましたら教えて下さい。 (1)VB側で0までの文字を別のStringにコピーする。 betu_out = left(out, InStr(out, chr(0))-1) (2)C側で代入文字数も含めて返す。 (LPSTR inp, int* size, LPSTR *out) betu_out = left(out, size) よろしくお願いします。
- machongola
- ベストアンサー率60% (434/720)
こんにちは。 BSTR型の場合はString型だった様な気がします。 LPSTR/LPCSTR型の場合はAs Byteの配列で引くのではないでしょうか。 Public Declare Function cpp_proc Lib "example.dll" _ (ByRef inp() As Byte, ByRef out() As Byte) As Integer では駄目でしょうか。
補足
ありがとうございます。 VB側から文字列を送り、DLLから変更した文字列を受け取るというものが作りたくて悪戦苦闘しています。 BSTR型で試しました。 コンパイルはとおり、C++(DLL)側にパラメータが渡ったのですが、 表示してみると、VBからASCII文字を送っているのにも関わらず、 bufで化け文字??や漢字が表示されました。 何が悪いのでしょうか? //=========== C (DLL) 側 #include <comutil.h> #pragma comment(lib, "comsupp.lib") #pragma comment(lib, "comsuppw.lib") int __stdcall cpp_proc(BSTR inp, BSTR* out) { char buf[1024]; char* p = _com_util::ConvertBSTRToString( inp ); strcpy(buf, p); MessageBox(0, buf, "化け文字??", MB_OK); // 文字化け? わかりません? delete [] p; // ついでに、outに "結果はゼロです" という日本語文字を返したいです。 // どう書けばよいか、わかりません。 // 戻り値 return 2; } //=========== VB側 Public Declare Function cpp_proc Lib "example.dll" _ (ByVal inp As String, ByRef out as String) As Integer Public Sub Test() Dim ret As Integer Dim inp as String Dim out as String inp = "abcdefg" out = space(1024) // 不要でしょうか? ret = cpp_proc(inp, out) MsgBox ("ret=[" & CStr(ret) & "]") // 2が返ります。 MsgBox ("inp=[" & inp & "]") // 送った内容 abcdefg MsgBox ("out=[" & out & "]") // 「結果はゼロです」という文字を表示させたい。 // DLLで何もしていないので、空白ですが End Sub -------- こちらの方法は、ByRefで躓いています。 LPCSTR / LPSTR ByVal inp() as Byte / ByRef out() Byte
補足
何度もお手数おかけします。 SysAllocStringByteLen()を使用してVBに送り返す方法は、うまくいきました。 また、疑問な点がでてきたのですが SysFreeString(*out); で最初、解放するのは納得できましたが、 *out = SysAllocStringByteLen(psz, ::strlen(psz)); として、VBに返された領域は、VB側で解放されるのでしょうか? 知識が少なくて申し訳ありませんが、メモリリークなどは 大丈夫でしょうか? http://mzs184.blogspot.com/2008/03/bstr.html