• ベストアンサー

dllを使用しVB側に文字列を返す

VCで作ったdllを使用し VBに文字列を返すことはできますか? extern int CCONV TxtCnt(char *a) { *a='1'; a++; *a='\0'; return 0; } vbの方 dim ret% dim a$ ret=TxtCnt(a) msgbox a ちょっと試しに作りましたが これではなぜ"1"という値が返ってこないのでしょうか? バリアント型に文字列を返すdllをみたことあるのですが これはどうやっているのでしょうか?

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

  • ベストアンサー
  • haporun
  • ベストアンサー率40% (230/562)
回答No.1

declare宣言はできてますか? Declare Function TxtCnt Lib "hoge.dll" (ByVal a As String) As Long ByValを忘れがちです。 さて、ここで原因となっているのは、aに領域が割り当てられていないからです。 通常a = "hoge" とやると、VBでは勝手に4文字+NULLの5(正確にはその2倍)の領域が割り当てられます。 しかし、Dim宣言しただけでは、この領域は割り当てられません。 そして、C側には何も領域を割り当てる文は書いてません。 ちなみに、C側でVBの文字列の領域割り当てをするのは、かなり困難です。 領域が割り当てられていないところに書き込むわけですから、通常はメモリの共有違反で強制終了になるところです。 しかし、VBはDLLの関数を呼び出す前に、特殊な処理をしており、DLLに文字列を渡すときに、勝手に一時的な領域が割り当てられることもあります(割り当てられないときもあります)。 よって、DLL側では一時的な仮想領域に文字を書き込んで、VBは返ってきたその文字を無視します。 a = String(vbNullChar, 20) TxtCnt a などとやって、あらかじめ領域を割り当てるか、 Dim a As String * 20 などと、固定長文字列を宣言して対処するのが普通です。 ちなみにVariantがたの変数を渡して、それに文字を書き込んでもらうのはちょっと高度ですので、あと1年くらいお勉強してからにしましょう。

sha-girl
質問者

お礼

なるほど。勉強になりました。問題は領域を固定していない事でした。ありがとうございました。

関連するQ&A

  • 文字列を返すVCで作成したDLL関数をVBで呼ぶと...

    VC++で文字列を返すDLL関数を作成しました。 LPCSTR GetVcString(void) これをVBでStringとして受け取り、MsgBoxで表示すると正常に取得できているようなのですが、Lenで文字数を取得すると変な値が返ってきます。 1. Dim Ret As String 2. Ret=GetVcString() 3. MsgBox(Ret) ← VCで返された文字列は正常に表示されている 4. MsgBox(Str(Len(Ret))) ← 実際の文字数とはかけ離れた数値になる 2行目と3行目の間に、 Ret=Left(Ret,InStr(Ret,vbNullChar)-1) を噛ませれば文字数は正常な値になるのですが、このような処理をしなくても正常に文字数を取得する方法があれば教えてください。

  • dllを使用しVB側に文字列を返す2

    No.280310の質問の続きになってしまいますが 「VCで作ったdllを使用し VBに文字列を返すことはできますか」 でVCで作ったdllをVBを呼び出す事ができるようになりました。 Declare宣言で疑問に思ったのですが Declare Function TxtCnt Lib "hoge.dll" (ByVal a As String) As Long aはなぜ値渡しなのでしょうか? 変数が書き換えられて戻ってくるので、byrefで指定していました。 それが問題が起こしていた原因一つでした。 ちなみにint型の数値をポインタで渡した場合はbyrefでうまくいきます。 ご教授願います。

  • VC++で作成したDLLをVBから呼ぶと戻り値が化けてしまう

    はじめまして。いつも勉強させていただいております。 VCは今回初めてやっておりますので当たり前の質問 になってしまうかもしれませんがご教授願います。 以下のような仕様でものづくりを行っております。 1.VBよりVC++で作成したDLLを呼び出す。 2.VC++で作成したDLL側ではパラメータより取得した   値を元に足し算をした結果を   戻り値にセットして要求元に返却する。 といった流れで考えています。 2の部分についてはExeを一度作成し実行させた ところDOS窓に値が表示されました。(printfで) しかし、正しくOUTPUTされた値がVB側の戻り値と して返却された時点で参照すると「-6348」 となっています。 なぜこうなってしまうのか原因がわからず投稿 させて頂きました。 ご存知の方、ご教授下さい。 ************************************************* VC++ DLL側のソース ************************************************* #include <windows.h> #define DLL_EXPORT __declspec(dllexport) extern "C" { DLL_EXPORT int add(int a,int b); } int add(int a,int b) { return a+b; } ************************************************* VB  DLL呼び出し元 ************************************************* Option Explicit Private Declare Function add Lib "C:\Program Files\Microsoft Visual Studio\test\Debug\test.dll" Alias "_add@8" (a As Long, b As Long) As Integer Private Sub Command1_Click() Dim ret As Long ret = add(1, 2) MsgBox ret End Sub 環境 OS:WinXP 言語:VC++6.0    VB6.0(SP6)

  • DLL VBとC++

    VBAからVC++2005のDLLを呼び出すプログラムを書いています。 VB側で作成したcpp_proc関数を呼ぶとVBアプリ自体が落ちました。 DLLのreturnの直前に以下のMessageBoxで表示させるとそこまでは表示され、 リターンを押すと、落ちました。 VB側の引数の値 String * 8192が悪いのでしょうか? return直前まで動作していたので、DLLの戻り値に何か原因があるのでしょうか? ついでの質問ですが、DEFの @1は無くても動くのでしょうか? 意味が知りたいです。 // ----- C++ (DLL側) ----- int __stdcall cpp_proc(LPCSTR inp, LPSTR out) { ... 省略 MessageBox(0, "ここまで通過", "debug", MB_OK); return 0; } // ----- DEF ----- LIBRARY "example" DESCRIPTION 'テスト' EXPORTS ; 明示的なエクスポートはここへ記述できます cpp_proc @1 '----- 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 * 8192 ret = cpp_proc(inp, out) MsgBox("ret=[" & Cstr(ret) & "]"); End Sub

  • MFC-DLL VBからCallしStackError[No.741430の続き]

    #DLLをCOMにしたり、タイプライブラリを作成すればString型(BSTR)でも 特に問題はなくなります。 VC++で文字列を返すDLLを作ってVBで呼んでいます。 DLLの中でのスタック(Stack)サイズの問題みたいですが、 DLLは自分のスタックを持たなくてそれを使うAppのスタックを使うとしていますが、間違っていたら教えてください。そしてどうすればこのエラーを避けることができて、ただしくデータをVB側で受け取ることができるのでしょうか。 しかし返すデータが大きく(たとえば3MBの文字列)なると『実行エラー28 スタック領域が不足しています。』というエラーメッセージが出て終了されます。 VC++6.0 __declspec(dllexport) VARIANT WINAPI FunA() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); COleVariant vntA = <3MB程度の文字列> ; return vntA.Detach(); } VB6.0 Private Declare Function FunA _ Lib "Communication.dll" () As Variant Dim strRet As String strRet = FunA()

  • VB6からVCで作成したDLLへのvoidポインタの受け渡し

    VB6でVCで作成されたDLLの関数から戻り値としてvoidポインタを受け取り、 それをDLLの別の関数を呼び出す際に引数として渡すプログラムを作成しようとして 詰まっています。以下サンプルです。 ===VB側 Public Type Param   sStr As String   lNum As Long End Type Declare Function Create Lib "test.dll" (ByRef tParam As Param) As Long Declare Function Free Lib "test.dll" (ByVal pSt As Any) As Long Dim pSt As Long Dim lRet As Long Dim tParam As Param With tParam   .sStr = "test" & Chr(0)   .lNum = 10 End With pSt = Conn(tParam) lRet = Free(pSt) ===VC側 typedef struct stParaA {   char * aaa;   char * bbb; } PARAM_A; typedef struct stParaB {   char * ccc;   int iNum; } PARAM_B; extern "C" void * __stdcall Create(PARAM_B* stParaB) {   PARAM_A stParaA;   //stParaAの各メンバ領域をMallocで確保   return((void*)stParaA); } extern "C" int __stdcall Free(void* stParaA) {   //stParaAの各メンバ領域をfree   return 0; //正常終了の場合 } VC側でデバッグしてみたところ、stParaBの各メンバの値はVC側で取得できているので、 DLLの呼び出し自体には問題はないようですが、Create()でreturnする時と、Free()に 入ってきたときではstParaAのアドレスが変わってしまい、異常終了します。 VC側はソースはあるのでデバッグは可能なのですが、DLLの修正自体は不可となって いるため、VB側を直すしかないのですが、どのようにすればアドレスの受け渡しが できるのでしょうか。

  • Cで作成したDLL関数をVBから呼ぶ(.NET)

    以前の質問に「Cで作成したDLL関数をVBから呼ぶ」(QNo.1703839)がありますが、下記のコードを見るとVB6での内容だと思います。 Dim keydata As String * 128 keydata = String$(128, Chr(0) & Chr(0)) VB.NETでVC++のDLLで変更した文字列を受けたいのですが、 どのようにすればよいのでしょうか? VB.NET2003 <DllImport("DllTest.dll")> Private Shared Function _ Test(ByVal s1 As String) As String End Function Private Sub btnTest_Click(...) ... Dim s1 As String = "abc" Dim s2 As String Dim s3 As String s2 = Test(s1) MessageBox.Show(s2) ' "1"が表示される s3 = StrConv(s2, VbStrConv.None) MessageBox.Show(s3) ' 同じく"1"が表示 end sub VC++のDLL extern "C" __declspec (dllexport) BSTR __stdcall Test(char* s1) { AfxMessageBox(s1); // "abc"が表示される OK strcpy(s1, "123"); CString s2; s2 = "123"; return s2.AllocSysString(); } また、文字列に全角を含めても大丈夫でしょうか? Unicodeの変換処理を行う必要があるのでしょうか? よろしくお願いします。

  • dllを使用しVB側に文字列を返す3

    いつもこの教えてgooで回答してくださってる方々にはお世話になってます。 前の質問でVCで作成したdllをvbから呼び出して 文字列を渡して返すということを教えて頂いたのですが その件に関連して質問があります。 eucをsjisに変換する自作の dllを使用しているのですが、問題が発生しました。 それは一部、漢字が正確に変換できないのです。 (ちなみにCから呼び出す分には問題は発生しません。) 例えば「これは全角です。」をeuc→sjisは問題ありません。 問題がでるのはある特定漢字コード、具体的には「野」です。 EUCでの「野」の漢字コードはCCEEかと思いますが open~input文で読みとったところCCFBになってしまいます。 これは何故なのでしょうか? またvbのstring型をbyrefで渡したときどの部分に 文字列長の情報が入ってるのでしょうか?184バイト目以降から 2バイト置きに渡した文字列が入っていましたが それ以前の情報は何が何を表しているのかまったくわかりませんでした。 どうかご教授お願いします。

  • VCでのDLLからVBへの文字列の引渡し

    ===VB(Ver.6.0 SP5)側=== Public Declare Function GetStrSample Lib "Test.dll" () As String ・・・・・ Label1.Caption = GetStrSample ===VC側(Ver6.0)=== const char *StrSample="ABCDE01234";   ・・・・ _declspec(dllexport) BSTR _stdcall GetStrSample() { CString strResult; strResult = StrSample; return strResult.AllocSysString(); } 上記のようなコードで、VC側をDLLとしてVBから呼び出すと、 Label1には "A" しか表示されず、ブレークを置いてGetStrSample の戻り値を調べてみると、0x41,0x00,0x42,0x00,のように、 0x00が挟まれてしまいました。 ( ?hex(asc(mid(GetStrSample,3,1))) のようにして調べました。)  何故なのでしょうか? 文字コードの違いでしょうか? 正常にABCDE01234が渡せるようにするにはどうすればいいでしょうか? VCは初心者で、本や他人の作ったコードやMSDNを見て作成してみました。 目的は、DLLのバージョン等の情報をVB側に渡したいのです。 よろしくお願いします。

  • DLLの作成でで

    DLLの作成でで extern "C" int test(void) { int a; a=2; return a; } test の前のintは返す値の型なのでしょうか? もし文字を返す場合はcharでいいのでしょうか? また複数の値を返す場合は別に追加しなければいけないのでしょうか?よろしくお願いいたします。 初心者なので説明が下手ですがよろしくお願いいたします。

専門家に質問してみよう