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に格納されます。
『愛する』→『愛す?』になってしまうんですが、
どうしてでしょうか。
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)
この回答への補足
回答有難うございます。
BSTRで返す理由はDLLの中で返す文字列の長さが動的に変わるのでVB側で文字列長さを決めてDLLに参照型パラメータとして渡すのが困難なだめです。
回答していただいたコードを見ますと、VB側で文字列サイズを決めてDLLに渡しているんですが、僕が意図していることも可能でしょうか。
方法などがご存知でしたら教えてください。
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()
こんなかな?
この回答への補足
ご回答本当に有難うございます。助かっています。
テストしてみましたが大丈夫でした。
これでまず解決できそうです。
>領域の確保はVC++、解放はVB側で行う
ここで上のソースコード上は確保と開放のところが見当たらないですが、VB側で何もしなくても開放されるのでしょうか。
そしてもしよろしければ2番目のやり方も具体的に教えて頂けませんか。
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/Poin …
参考URL:http://www.bekkoame.ne.jp/~ilgg/VBMain/VB/C/Poin …
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) IT初心者です 仕事で、vb.netで作成されたdllをvbaで呼び出すプログラムを作成しろと言われ 1 2023/03/27 08:22
- 英語 この英語の問題が分かりません 3 2023/04/22 20:19
- Access(アクセス) Vba Userformを前面に出すについて 3 2022/04/15 12:29
- 英語 語順 1 2023/01/24 20:54
- 英語 下記はなんていってますか? こんにちは以降、訳していただけたら助かります。 Hello, We’re 1 2023/01/14 00:09
- 英語 While a histological comparison of vital bone form 2 2023/03/12 16:25
- その他(プログラミング・Web制作) python fbprophetについて 1 2022/09/29 19:44
- 英語 This is best accomplished by elevating the membran 1 2023/03/13 18:42
- 英語 できるだけ直訳で英語の翻訳をお願いします。(英語→日本語) 1 2022/10/15 20:59
- 英語 この英文は平易な反面格調高いですか? 1 2023/01/15 12:04
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
mallocについて
-
newしないオブジェクトについて
-
allocってなんですか?
-
stringの最大サイズ
-
ビットをローテートするプログ...
-
C言語 mallocとfreeについて
-
アンマネージド関数でのメモリ...
-
Win32APIでのメモリ管理について
-
C言語に関する質問
-
アセンブラでのメモリの動的確...
-
ヒープメモリの解放について
-
メモリの動的確保(大容量)に...
-
プログラムが途中で強制終了し...
-
64ビットと32ビットの違い
-
VC++6.0 MFC ダイアログバーを...
-
ExcelVBAで質問です。離れた二...
-
c言語
-
C言語 配列の長さの上限
-
パイソンの
-
_tcscpy_s(wcscpy_s)の第二引数...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
mallocについて
-
c言語のポインタへの文字列入力...
-
allocってなんですか?
-
newしないオブジェクトについて
-
ヒープメモリの解放について
-
C++で、メンバもヒープに確保さ...
-
MSDNがgethostbynameではなくge...
-
プログラムが途中で強制終了し...
-
配列の添え字の最大数とは?
-
Accessで、メモリを開放するタ...
-
malloc呼び出し時のセグメンテ...
-
ヒープ領域の限界値設定
-
スタック破壊の上手な見つけ方...
-
C言語 mallocとfreeについて
-
指定したメモリアドレスの値の...
-
stringの最大サイズ
-
16進ダンプのプログラム
-
入れ子になった構造体について
-
64ビットと32ビットの違い
-
free関数で動作が止まる
おすすめ情報