アプリ版:「スタンプのみでお礼する」機能のリリースについて

VC++6.0でDLLを作成してVBから呼んでいます。

VC++6.0
__declspec(dllexport) BSTR WINAPI FunA()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());

CString strA
= _T("This is the テストです。.愛する</CsvData>");
return strA.AllocSysString();
}

VB6.0
Private Declare Function FunA _
Lib "Communication.dll" () As String

Dim strRet As String
strRet = StrConv(FunA(), vbFromUnicode)

これを実行すると
『This is the テストです。.愛す?</CsvData>』
がstrRetに格納されます。
『愛する』→『愛す?』になってしまうんですが、
どうしてでしょうか。

A 回答 (4件)

こんなことをしてるから。



>Dim strRet As String
>strRet = StrConv(FunA(), vbFromUnicode)

なんでMFC側からBSTRで返すんですか?

簡単に済ますのなら、VBからは普通は戻り値ではなくByValのパラメータでStringをわたし、
VC++側はLPSTRで受け取るのがいいと思うのですが。

この回答への補足

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

補足日時:2004/01/05 19:53
    • good
    • 0

>テストしてみたんですが,うまく行きません。


>もっと具体的なコードが欲しいですが,

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)

この回答への補足

回答有難うございます。

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

補足日時:2004/01/06 17:32
    • good
    • 0

>回答していただいたコードを見ますと、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()

こんなかな?

この回答への補足

ご回答本当に有難うございます。助かっています。
テストしてみましたが大丈夫でした。
これでまず解決できそうです。

>領域の確保はVC++、解放はVB側で行う
ここで上のソースコード上は確保と開放のところが見当たらないですが、VB側で何もしなくても開放されるのでしょうか。

そしてもしよろしければ2番目のやり方も具体的に教えて頂けませんか。

補足日時:2004/01/07 14:44
    • good
    • 0

>>領域の確保は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/Poin …

参考URL:http://www.bekkoame.ne.jp/~ilgg/VBMain/VB/C/Poin …
    • good
    • 0
この回答へのお礼

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

お礼日時:2004/01/08 13:53

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!