はじめまして、武藤と申します。
過去ログ検索しましたが、同じ内容はないと思い新規で質問させていただきました。
現在VB6+SPでC言語で書かれているプログラムをVBに移植しています。
CreatFile したファイルを ReadFile しているのですが、
ReadFile で失敗(戻り値が0)してしまいます。
エラーコードを取得すると「メモリロケーションへのアクセスが無効です」と
なっています。ポインタの扱いが間違っているように思うのですが・・・
申し訳ありませんがアドバイスお願いいたします。
Dim fp As Long
Dim file As String
Dim lFileSize As Long
Dim pBuffer As Long
Dim rByte As Long
file = Text10.Text
fp = CreateFile(file, GENERIC_READ, 0&, 0&, OPEN_EXISTING, 0&, 0&)
lFileSize = FileLen(file)
pBuffer = GlobalAlloc(GPTR, lFileSize)
Sts = ReadFile(fp, pBuffer, lFileSize, rByte, 0&)
〜〜エラーチェックしてやりたい処理〜〜
CloseHandle (fp)
Call GlobalFree(pBuffer)
Win32 API部分を、そのままVB6に移行させるには、無理のある部分
があります。
Open "xxx.xxx" for input as #1
Input #1,〜
Close #1
のように、VBに基本で搭載されているコマンドやステートメントで
同様の動きをするコードに置き換えたらいけないのでしょうか?
以上。
岡田様 アドバイスありがとうございます。
VBを本格に的に使うのは今回が初めてでして殆ど予備知識がありません。
OpenやGetを調べて見たのですが、
GlobalAllocなどのように実メモリ上にバッファを確保する方法とは少し違うようです。
とりあえず、ReadFileで悩んでいたのでその先は書きませんでしたが、
やりたいことはReadFileしたバッファのポインタをDLLに渡して
そこである処理をしたいと思っています。
VBではReadFileするのには無理があるというのはどの様なことなのでしょうか?
宜しくお願いいたします。
ReadFileが悪いわけではありません。
私もWin32 APIをDeclareして使っています。またReadFileも使って
います。
ちなみに、GlobalAllocした場合、返ってくるものは、あくまで
ハンドルなので、そこにダイレクトには、書き込めません。
GlobalLockして、ハンドルからポインタに変更してから、そこ
にReadFileさせるバッファとして渡して下さい。
それでReadFileが、正しく読めたバイト数を返してくるように
なるはずです。
使用後は、GlobalUnlockしてからGlobalFreeして解放するのを
忘れずに・・・
ちなみに、DLLもVBで作成されたものですか?
Cであれば、ファイルの読み込み処理ごと、DLL側にもって
いけば、わざわざVBで苦労することもありませんが・・・
以上。
岡田様 再々ありがとうございます。
>ちなみに、GlobalAllocした場合、返ってくるものは、あくまで
>ハンドルなので、そこにダイレクトには、書き込めません。
>GlobalLockして、ハンドルからポインタに変更してから、そこ
>にReadFileさせるバッファとして渡して下さい。
「これだ!!」と思い色々やってみましたがやはりReadFileの戻り値は「0」です。
hBuffer = GlobalAlloc(GPTR, lFileSize)
pBuffer = GlobalLock(hBuffer)
Sts = ReadFile(fp, pBuffer, lFileSize, rByte, 0&)
GlobalSize で lFileSizeで指定したバッファをGlobalAllocが確保していることは確認しましたし、GlobalLock後にpBufferにはそれらしきアドレスが格納されていることも確認しました。
ですが、相変わらず「メモリロケーションへのアクセスが無効です」がでます。
ちなみに、EXEを作成してからアプリを実行すると、
「メモリロケーション〜」のエラーは発生せず正常終了します。
戻り値は相変わらず「0」ですが。
申し訳ありませんが、再度アドバイスお願いします。
この解決方法ではないのですが、
Open file as Binaryで開いて、
Byte型の配列にファイルのデータを読み取って、
その配列をグローバルメモリに挿げ替えるとかはどうでしょう?
ex)
dim buf() as byte
Open File for Binary as #1
redim buf(1 to lof(1))
get #1,1,buf
close #1
'後はグローバルメモリを作成して、CopyMemoryなどでコピー
追伸
APIは、実装している宣言を書かないとその部分の間違いがわかりません。
できれば、APIの宣言部分も載せてください。
いちゆ様 アドバイスありがとうございます。
>その配列をグローバルメモリに挿げ替えるとかはどうでしょう?
早速試してみたいと思います。
とりえず、必要と思われるAPI宣言部分です。
なにかおかしな点等がありましたらアドバイスお願いします。
Public Declare Function CreateFile Lib "kernel32.dll" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Public Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
Public Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Any) As Long
Public Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Public Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Public Declare Function ReadFile Lib "kernel32"
(ByVal hFile As Long, '1
lpBuffer As Any, '2
ByVal nNumberOfBytesToRead As Long, '3
lpNumberOfBytesRead As Long, '4
lpOverlapped As Any) As Long '5
この宣言部分を見る限り、4っつ目の引数がByRefになっています(省略されていますが)
よって、プログラム部分の、
Sts = ReadFile(fp, pBuffer, lFileSize, rByte, 0&)
は
Sts = ReadFile(fp,ByVal pBuffer, lFileSize, rByte, 0&)
ではないでしょうか?
あっ、すいません。
注目するのは、第2引数でした。
いちゆ様 岡田様
ありがとうございました。
ReadFileが成功し目的の動作をさせることができました。
大変感謝しております。
ありがとうございました。
ツイート | ![]() |