
VB.netでwin32apiを呼び出したが変数にデータが正しくセットされない
vb6.0のプログラムをvb.netに移植作業しています。
vb.netで機器との通信を行うためwinapi32で作られたドライバdllをインポートしたのですが受信データが正常に受け取れません。もう1週間も悩み続けています。
詳しい方お助けください。
//win32api側//
DWORD Receive(HANDLE handle,PBYTE pbReceiveBuffer,WORD wBufferLength, _
PWORD pwReceiveLength,PDWORD pdwErrCode);
//VB側//
<DllImport("Des_DLL", CharSet:=CharSet.Auto)> _
Public Function Receive(ByVal hPath As Intptr, ByRef ReceiveBuffer As IntPtr, _
ByVal ReceiveBuffLength As Ushort ByRef ReceiveLength As Ushort, _
ByRef lErrCode As Uint) As Uint
End Function
Dim rd_buf(1018) As Byte
Dim rbf_l As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(rd_buf)) 'アンマネージメモリ 確保
Marshal.Copy(rbf_l, rd_buf, 0, rd_buf.Length) 'アンマネージメモリからマネージメモリにコピー
ret = Receive(Path, rbf_l, rdbuffer_length, rd_length, ErrCode)
Call des_datawrite(rd_buf, rd_length, 2) ' 受信データの書き込み
For i = 0 To rd_length - 1 ' 受信データセット
DES.rd_buf(DES.rd_cnt) = rd_buf(i)
DES.rd_cnt = DES.rd_cnt + 1
Next i
DesRD_Normal = True
Marshal.FreeCoTaskMem(rbf_l)
End Function
Receive()は機器からの情報吸い上げレスポンス関数です。
Public Sub des_datawrite(ByVal wt_data() As Byte, ByVal length As Integer, ByVal Mode As Integer)
Dim free_num As Integer
Dim i As Integer
Dim cv_buf As String
cv_buf = ""
For i = 0 To length - 1
cv_buf = cv_buf & Microsoft.VisualBasic.Right("00" & Hex(wt_data(i)), 2) & " "
Next i
free_num = FreeFile()
FileOpen(free_num, GetAppPath() & DES_DATA, OpenMode.Append)
If Mode = 1 Then
Print(free_num, "[<-sd(" & DateTime.Now.ToString("yyyyMMddHHmm") & ")]" & Mid (cv_buf, 1, Len(cv_buf) - 1))
ElseIf Mode = 2 Then
ElseIf Mode = 2 Then
Print(free_num, "[->rd(" & DateTime.Now.ToString("yyyyMMddHHmm") & ")]" & Mid(cv_buf, 1, Len(cv_buf) - 1))
End If
FileClose(free_num)
End Sub
No.1ベストアンサー
- 回答日時:
「正しくセットされない」ということですが、正しくセットされる/されない以前に、正しく実行できないのではないですか?
C 側が
PBYTE pbReceiveBuffer
となっているのに、VB 側の Recieve の宣言が
ByRef ReceiveBuffer As IntPtr
となっていると、rbf_l に格納されている値(つまり、Marshal.AllocHGlobal で確保したメモリのアドレス ) を渡したいのに、rbf_1 自身のアドレスを渡してしまいます。
rbuf_1 って、ポインタですから、32 bit 環境なら 4 バイトしかないワケで、4バイトしか確保されていないところに1018 byte ものデータを書き込もうとするとメモリアクセス違反が起きるはずです。
ByVal ReceiveBuffer As IntPtr
にしてみてください。
あと、たぶん、Marshal.Copy と Recieve の順番が逆ですね。
それか、Marshal.AllocHGlobal、Marshal.Copy とかは使用せずに、
<DllImport("D:\Nobuyuki\Projects\Test\VcDllTest\Debug\VcDllTest.dll", CharSet:=CharSet.Auto)> _
Public Function Receive(ByVal hPath As IntPtr, ByVal ReceiveBuffer() As Byte, ByVal ReceiveBuffLength As UShort, ByRef ReceiveLength As UShort, ByRef lErrCode As UInt32) As UInt32
End Function
と宣言しておいて、
Dim ret As Integer = Receive(Path, rd_buf, rd_buf.Length, rd_length, ErrCode)
とするのがシンプルで良いような気もします。
No.2
- 回答日時:
一つ前の回答の
<DllImport・・・
のところは、そちらの環境に合わせてくださいね。
(こちらの環境の内容のまま載せてしまいました・・・。(^^; 一度書き込みしちゃうと修正できないんですよね・・・)
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
allocってなんですか?
-
LoadLibraryでAccess Violation...
-
座標値を読み込んである領域に...
-
gcnew arrayによるメモリ確保に...
-
構造体でchar name[]と*nameの...
-
void*型のデータサイズ
-
DLLで同じメモリ領域を参照する...
-
win32APIのHeapAlloc()の使い方...
-
LPWSTRのコピー
-
C++で、メンバもヒープに確保さ...
-
Win32APIでのメモリ管理について
-
DLLのマルチスレッドの動作につ...
-
mallocで確保するメモリの領域...
-
CreateFileMapping について
-
c言語のポインタへの文字列入力...
-
CStringからchar*への型変換に...
-
C言語 配列の長さの上限
-
char*を初期化したいのですが
-
init関数の意味
-
System.IO.Directory.GetFiles...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
allocってなんですか?
-
c言語のポインタへの文字列入力...
-
HEAP に関すること
-
構造体でchar name[]と*nameの...
-
ビットをローテートするプログ...
-
ヒープメモリの解放について
-
DLLのマルチスレッドの動作につ...
-
グローバル変数のサイズ
-
C++で、メンバもヒープに確保さ...
-
newしないオブジェクトについて
-
free関数で動作が止まる
-
構造体配列の初期化について
-
void*型のデータサイズ
-
MFCのCStringについて
-
mallocで確保するメモリの領域...
-
CreateFileMapping について
-
LPWSTRのコピー
-
c言語のメモリの確保について
-
配列の添え字の最大数とは?
-
C言語の質問です。 以下の命令...
おすすめ情報