• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:VBからMFC-DLL呼び出し)

VC++6.0でDLLを作成してVBから呼び出す方法

このQ&Aのポイント
  • VC++6.0のDLLを作成し、VBから呼び出す方法について説明します。
  • VC++6.0で作成したDLLをVBから呼び出す際、一部の文字が正しく表示されない現象が発生する場合があります。
  • 文字化けの原因や対処法についても解説します。

質問者が選んだベストアンサー

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.3

>回答していただいたコードを見ますと、VB側で >文字列サイズを決めてDLLに渡しているんですが、 >僕が意図していることも可能でしょうか。 >方法などがご存知でしたら教えてください。 VB、VC++間の受け渡しに限りませんが、 1.VC++側に、文字数を取得する関数を作り、それを事前に 呼び出すことで領域を確保する ・・・DLLでグローバル変数を使用しますが。 2.領域の確保、解放はすべてVC++側で行う ・・・VC++に、領域解放用の関数を作成する。 ただし、すべてアドレス操作になるため、 Longでアドレス値の受け渡しが必要 3.領域の確保はVC++、解放はVB側で行う となるでしょう。 で、簡単に済ますなら1になると思いますが、折角なので今回は3を お勧めします。 で、jaekukさんの作成されたものからの変更は、BSTRを返すのではなく、 VARIANTを返すようにしてください。 これで、正しくVBで扱える文字列を返せるようになり、 VB側では特に意識することなく領域の解放が行われます。 #DLLをCOMにしたり、タイプライブラリを作成すればString型(BSTR)でも 特に問題はなくなります。 VC++6.0 __declspec(dllexport) VARIANT WINAPI FunA() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); //別にこうする必要は無いですよ。API直接でもかまいません COleVariant vntA = L"This is the テストです。.愛する</CsvData>"; return vntA.Detach(); } VB6.0 Private Declare Function FunA _ Lib "Communication.dll" () As Variant Dim strRet As String strRet = FunA() こんなかな?

jaekuk
質問者

補足

ご回答本当に有難うございます。助かっています。 テストしてみましたが大丈夫でした。 これでまず解決できそうです。 >領域の確保はVC++、解放はVB側で行う ここで上のソースコード上は確保と開放のところが見当たらないですが、VB側で何もしなくても開放されるのでしょうか。 そしてもしよろしければ2番目のやり方も具体的に教えて頂けませんか。

すると、全ての回答が全文表示されます。

その他の回答 (3)

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.4

>>領域の確保はVC++、解放はVB側で行う >ここで上のソースコード上は確保と開放のところが見当た>らないですが、VB側で何もしなくても開放されるのでしょうか。 確保は、COleVariantのコンストラクタで文字列を渡している時点で行われています。 解放は、DLLの関数を呼び出したときの関数が終了した時点、この場合はstrRetが無効になった時点で行われています。 ちなみに、VBの可変長文字列って特に意識しないでも VBが領域の確保、解放ってやってくれてますよね。 今回は、VBが領域の確保、解放を自動的に行うことができる、Variantに格納できる値をDLLから返すことによって VBの内部動作に領域の解放を任せています。 もちろん、VBでは解放の処理を自動的にやってくれますが、このDLLの関数をCやC++から呼んだときは、正しく解放処理を行わないとメモリリークが発生します。 >そしてもしよろしければ2番目のやり方も具体的に教えて頂けませんか。 あくまでも例ですが。 __declspec(dllexport) LONG WINAPI FunA(LPSTR * lplp) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); LPSTR lpStr = new char[42]; lstrcpy(lpStr, "This is the テストです。.愛する</CsvData>"); *lplp = lpStr //結局VB側で長さが必要になっちゃいますけどね return 42; } __declspec(dllexport) LONG WINAPI Free(LPSTR lpStr) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); delete lpstr[]; return 0; } VB6.0 Private Declare Function FunA _ Lib "Communication.dll" (lpStrPtr As Long) As Long Private Declare Function Free _ Lib "Communication.dll" (ByVal lpStrPtr As Long) As Long Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (ByVal lpString1 As String, ByVal lpString2 As Long) As Long Dim lngLen As Long Dim lngStrPtr As Long lngLen = FunA(lngStrPtr) '取得した内容をString型にするために必要な領域を準備 Dim strString As String strString = Space(lngLen) 'lpStrPtrから文字列を取り出す '第二引数がByVal Longになってるところがミソ Call lstrcpy(strString, lngStrPtr) 'DLLで確保した領域を解放 Call Free(lngStrPtr) こんな感じにすれば一応はできますが。 似たようなことをやってるところを見つけたのでどうぞ。 http://www.bekkoame.ne.jp/~ilgg/VBMain/VB/C/Pointer.html

参考URL:
http://www.bekkoame.ne.jp/~ilgg/VBMain/VB/C/Pointer.html
jaekuk
質問者

お礼

ご回答有難うございます。 おかげさまで解決できました。 今後ともよろしくお願いします。

すると、全ての回答が全文表示されます。
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

>テストしてみたんですが,うまく行きません。 >もっと具体的なコードが欲しいですが, BSTRで返す理由も聞いてみたかったですけど(^^;; というわけで、サンプル。 __declspec(dllexport) LONG WINAPI FunA(LPSTR lpString) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); lstrcpy(lpString, "This is the テストです。.愛する</CsvData>"); return(0); } VB6.0 Private Declare Function FunA _ Lib "Communication.dll" (ByVal lpString As String) As Long Dim strRet As String strRet = Space(256) Call FunA(strRet)

jaekuk
質問者

補足

回答有難うございます。 BSTRで返す理由はDLLの中で返す文字列の長さが動的に変わるのでVB側で文字列長さを決めてDLLに参照型パラメータとして渡すのが困難なだめです。 回答していただいたコードを見ますと、VB側で文字列サイズを決めてDLLに渡しているんですが、僕が意図していることも可能でしょうか。 方法などがご存知でしたら教えてください。

すると、全ての回答が全文表示されます。
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

こんなことをしてるから。 >Dim strRet As String >strRet = StrConv(FunA(), vbFromUnicode) なんでMFC側からBSTRで返すんですか? 簡単に済ますのなら、VBからは普通は戻り値ではなくByValのパラメータでStringをわたし、 VC++側はLPSTRで受け取るのがいいと思うのですが。

jaekuk
質問者

補足

ご回答有難うございます。 テストしてみたんですが,うまく行きません。 もっと具体的なコードが欲しいですが, お願いします。

すると、全ての回答が全文表示されます。

関連するQ&A