• ベストアンサー

DLLのLPSTR 項目の戻り値の取得について

VB.NET初心者です。 C言語で作られたDLLの戻り値の取得で困ったことが発生しました。 どなたかが解決方法を教えてください。 -----------HHL5d.DLL定義(C言語)-----------  int HLFRecv ( LPSTR fileName ); ----------------------VB側宣言部---------- Declare Function HHLFRecvLib "HHL5d.DLL" _ (ByVal fileName As String) As Integer ※ fileName で指定された場所にファイルを書き込みます。 ・ 関数終了時には書き込んだファイルの(ファイル名を含んだ)フルパスがfileNameに上書きされます。 -----------VB側本文---------- Dim strRecvFile As String Dim intCnt As Integer  intRtn = HHLFRecv(strRecvFile) ※処理終了後に、strRecvFileにファイル名を含めたフルパスを戻したい。 byval定義の場合は、HHLFRecv関数内で変数の変更ができないため値の取得ができません・・ これを取得できるようにVB側の構文を書き換えたいのですが、方法がわかりません。 どなたかアドバイスをお願いいたします。

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

  • ベストアンサー
回答No.4

DLLの関数をCallする前に文字列変数に十分な領域を割り当てているでしょうか? 通常、DLL側ではVB用の文字変数に対して、領域確保などはしません。 DLLの関数をCallする前に strRecvFile = String(1000, 0) として intRtn = HHLFRecv(strRecvFile) myFile = Left$(strRecvFile, Instr(1,strRecvFile,Chr$(0))) でどうでしょうか?

kazuha4649
質問者

お礼

回答ありがとうございました。 結局のところ、ファイルの名称を受け取る仕様を組み込む必要がなくなりました。(貴重な回答ありがとうございます。) この方法はいけそうな感じですね。 仕様上は変更なしなのですが、個人的に気なるので試してみます。

その他の回答 (4)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.5

アンマネージドなDLLを呼び出すのであれば <MarshalAs(UnmanagedType.VBByRefStr)> などで引数を修飾してやる必要があります しかし DLL側が書き出すのが LPSTRですとVB.NET側で文字化けしてしまいます Cでラッパーを組むなりしてユニコードとマルチバイト(MBCS)の変換をしないといけないでしょう int MBCS2UNICODE(LPWSTR wstr) {  LPSTR str = (LPSTR)calloc( sizeof(char_w), wsclen( wstr ) );  int nRet = HHLFRecv( str );  int n = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);  MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, n, NULL, NULL);  free( (LPVOID)str);  return nRet; } といった具合にして VB.NET側では Private Declare Function M2U lib "ラッパーDLL" alias "MBCS2UNICODE" _ (<MarshalAs(UnmanagedType.VBByRefStr)>ByRef str as String)) as Integer と宣言して Dim work as String Dim intRet as Integer work = Space(100) intRet = M2U( work ) といった具合にしましょう

kazuha4649
質問者

お礼

回答ありがとうございました。 結局のところ、ファイルの名称を受け取る仕様を組み込む必要がなくなりました。(貴重な回答ありがとうございます。) 上記方法でいけそうな感じですが、C側のDLLの仕様は変更はできないためラッパーを組むなどの方法が取れそうにないです。 ただ今後同様な事象が発生する場合が想定されるので、参考とさせていただきます。

回答No.3

過去の質問ですが、参考になるでしょうか。 http://oshiete1.goo.ne.jp/kotaeru.php3?q=711327

kazuha4649
質問者

お礼

回答ありがとうございました。 過去のログを見てみるようにいたします。参考になりそうですね。

回答No.2

#1です。 すみません先程の回答ですが間違いかもしれません。 WindowsAPIなどで戻り値を受け取る場合でもByValで定義しますね。

kazuha4649
質問者

お礼

ありがとうございます。 ところが、Byvalで定義している状態でも値は受け渡したときと同じ情報が帰ってきているようなんです。 DLLの仕様では、ファイルの書き込みが正常終了した場合に、書き込んだ変数にファイル名を追加して戻すという仕様になっています。

回答No.1

ByVal→ByRefにしてみてください。 ByValは値渡しで、ByRefは参照渡しです。(ByRefは渡した関数側で書き換え可能です。)

kazuha4649
質問者

お礼

さっそくの回答ありがとうございました。 私のその部分は気にしていて、byrefに変更したのですが、HHLFRecvの関数側でstrRecvFileが正常に渡されていないとDLL側で判断されエラーで帰ってきています。 Byrefにした場合に、strRecvFileの内容(例えば"c:\sendfile") が渡されてない感じです。 byvalに変更すると正常に終了します。 strRecvFileの型も変更する必要があるのでしょうか?

関連するQ&A

  • VBAでDLLが見つからないエラー

    CADのVBA(6.0)ですが、DLLが見つからないエラーが出ます ' こっちはエラーが出ない Public Declare Function SearchVBApath Lib _ "C:\Program Files\AppliTool\VB\DDDD.dll" (ByVal env As String, ByVal s As String) As Integer 'こっちだとエラーが出る Public Declare Function SearchVBApath Lib "DDDD.dll" (ByVal env As String, ByVal s As String)    As Integer VBAプロジェクトファイルとDLLは同じフォルダにおいてあります 上記のようにフルパスだとエラーが出ないのですがDLL名だけだとこの関数のところでエラーがでます このDLL関数宣言行の前の方には他のDLL関数も同じようにパス省略で記述しているのですがそちらにはエラーが出ません どなたかヒント下さい、よろしくお願いします。

  • VB .NetのDLL参照について

    名前付パイプの処理をしているのですが、DLLが参照できません。 Public Class ClsJi01   Public Declare Function MakePipe Lib "\DLL\Point.DLL" (ByVal pipe_name As String, ByVal buf_size As Integer, ByVal max_instances As Short, ByVal hpipe As Integer, ByVal err_code As Integer) As Integer  Public Sub M_Pipe()   Dim r As Integer   Dim rpipe As Integer   Dim err_code As Integer   r = MakePipe("\\.\pipe\RS04", 255, 16, rpipe, err_code)  End Sub End Class Point.DLLは以前VB6.0の時に使用していたDLLで自作です。 これで実行すると「オブジェクト参照がオブジェクト インスタンスに設定されていません。」と出ます。 どうしたら良いのでしょうか?

  • 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

  • VB2005 から DLL を呼び出す

    VB 初心者です。 今、VB の練習ということで VB 2005 Express Edition を使って、個人用ブラウザをつくっています。Web ページの表示は Webbrowser コンポーネントを使っています。 その仕様で、閲覧先によって HTTP Proxy を変更するようになっています。(自分で決めたんですが) いろいろ調べてみると、urlmon.dll の UrlMkSetSessionOption() を呼べば自分のアプリケーション限定で Proxy を変更できるようだ、ということがわかりました。 古い VB など(VB 6 とか?)では、 Private Declare Sub UrlMkSetSessionOption Lib "urlmon.dll" _ (ByVal dwOption As Long, ByVal pBuffer As Any, _ ByVal dwBufferLength As Long, _ ByVal dwReserved As Long) このような感じで宣言するとかあったんですが、VB2005 では Any がダメだとか、 Type INTERNET_PROXY_INFO Dim dwAccessType As Long Dim lpszProxy As String Dim lpszProxyBypass As String End Type で Type はダメだとか、呼び出し側で、LenB を使おうとしたら使えないだとか、INTERNET_OPTION_PROXY の値がわからないなど、問題が山積みです。 上記 DLL を VB 2005 で使ったことがある人がいたら(またはわかる人)、使い方を教えてもらえないでしょうか?

  • TextBoxの文字がかけてしまうのですが VB.NET

    VB.NET FrameWork1.1の環境なのですが、 Declare Function WritePrivateProfileString Lib "KERNEL32.DLL" Alias "WritePrivateProfileStringA" ( _ ByVal lpAppName As String, _ ByVal lpKeyName As String, _ ByVal lpString As String, _ ByVal lpFileName As String) As Integer このAPIを使ってファイルに文字列を記録しているのですが、 TextBoxに表示したファイルのフルパスを記録すると このAPIを使った直後にそのTextBoxの文字の後半が欠けてしまいます。 短いパス名なら大丈夫なのですが、長いパス名の場合に欠けてしまいます。 試しに Dim a As String = TextBox1.Text WritePrivateProfileString("TextBox", "1", a, FileName) Console.WriteLine(a) としても同じく欠けてしまいます。 変数aの宣言の型をString ではなく Object にすると 欠けなくなるのですが、変数aやTextBoxの内容は読み取った だけなのになぜ書き換えられてしまうのでしょうか? どの場合でもファイルへの記録は正常に出来ています。 何か問題点などありましたらご教授いただけると助かります。

  • 引数で戻り値を取得するプログラム

    以下のように、引数で戻り値を取得するプログラムを書きたいのですが どのように書けば正しいでしょうか? VB6とVB2005の両方の書き方を教えてください。 sub kekka(byval src as string, byref dst() as string) dim ret() as string ret(0) = "abc" ret(1) = "efg" kekka = ret end sub kekka("xxx", dat() ) msgbox(dat(0)) msgbox(dat(1))

  • VB 動画再生する際にカレントディレクトリを指定して再生

    私は今、あるアプリケーションを作っているのですが、オープニングムービーを再生したいと思っております。 開発環境:Visual studio 2008 言語:VB 現在はサイト等で検索し、 Private Declare Ansi Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Integer, ByVal hwndCallback As Integer) As Integer Const stCurrentDir As String = CurDir$() Const FileName As String = stCurrentDir & """\openning.mpg""" という感じでファイルの場所を指定しているのですが、どうもconstがネックです。 これをdimで指定すると再生されないのです。 だからと言ってconstでやると、普通にカレントディレクトリを指定せずすべて指定するとできるのですが、上のようにカレントディレクトリを求めると、定数式が必要と出てしまいます。 どうにかうまくいく方法等ありませんでしょうか? よろしくお願いいたします!

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

    以前にあった「Cで作成したDLL関数をVBから呼び 引数渡し方法」を試したのですがVB側でデータが受け取れません。 http://oshiete1.goo.ne.jp/kotaeru.php3?q=711327 C側での値設定がわるいのでしょうか? VB側 Public Declare Function testAP Lib "C:\bin\test.dll" (ByVal lpKeyData As String) As Long --------------------------------------------------------------------------- Dim lngRc As Long Dim keydata As String * 128 keydata = String$(128, Chr(0) & Chr(0)) lngRc = testAP(keydata) VC側 __declspec(dllexport) long __stdcall testAP(char *lpdata){ →C側でlpdataに値を設定する lpdata="ABCDEF"; }

  • DLL<->VB間での受け渡し(文字列・ポインタ)

    VBで開発を行っていますが、 DLL<->VBでのやり取りでポインタ?のの引渡しで困っております。 簡単に言うと、指定したキーで、内容(データ)を取出し、さらに 要素ごとにデータを取出すという仕組みです。 例ですが、DLLの仕様は TR_MR(No,Id,Buff)  Noは検索No.  Idは取出す位置  buffはデータバッファ領域のポインタ で、Idで指定された位置からデータをbuffに読み込む (戻り値は、buffにセットされたデータのバイトサイズ) TR_MR_IT(buff,Tagset,Dat) buffは先ほど取り込んだデータバッファ領域のポインタ Tagsetは項目識別子のポインタ Datはデータ上の1項目の文字列 と言う具合です。 VBでの宣言は =================================================== Private Type Tagset tagno As String * 3 Subf As String * 1 seq As Integer End Type Private Declare Function TR_MR Lib "tr.dll" (ByVal no As Integer, ByVal Id As Integer, ByVal buff As String) As Integer Private Declare Function TR_MR_IT Lib "tr.dll" (ByVal buff As String, ByRef tg As Tagset, ByVal dat As String) As Integer Dim buf_size As Integer Dim MR_buff As String MR_buff = String(65562, vbNullChar) buf_size = TR_MR(no, 1, MR_buff) Dim tg As Tagset Dim MR_size As Integer Dim MR_IT_buff As String tg.tagno = "001" tg.Subf = "A" tg.seq = 1 MR_IT_buff = String(12282, vbNullChar) MR_size = TR_MR_IT(MR_buff, tg, MR_IT_buff) =================================================== 長々と書いてしまいましたが、 何か、助言をいただければ幸いです。

  • ユーザー名の取得で

    ユーザー名の取得がうまくいきません。 どなたか教えて下さい。 環境はVB.net 2003です。 '宣言部 Declare Ansi Function GetUserNameByDeclare Lib "advapi32.dll" _ Alias "GetUserNameA" (ByVal lpBuffer As String, ByRef nSize As Integer) As Integer 'ソース内   Const UNLEN As Integer = 256   Dim tusr As String   Dim ln As Integer   tusr = Space(UNLEN)   ln = Len(tusr)   GetUserNameByDeclare(tusr, ln)   strdir = "C:\Documents and Settings\" & tusr & "\My Documents" 上記、ユーザー名(tusr)は取得できるんですが、strdirのtusr以下の部分 "\My Documents" が削られてしまいます。 どこが悪いんでしょう? よろしくお願いします。

専門家に質問してみよう