アプリ版:「スタンプのみでお礼する」機能のリリースについて

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

A 回答 (2件)

一つ前の回答の



<DllImport・・・

のところは、そちらの環境に合わせてくださいね。
(こちらの環境の内容のまま載せてしまいました・・・。(^^; 一度書き込みしちゃうと修正できないんですよね・・・)
    • good
    • 0

「正しくセットされない」ということですが、正しくセットされる/されない以前に、正しく実行できないのではないですか?



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)

とするのがシンプルで良いような気もします。
    • good
    • 0
この回答へのお礼

ありがとうございます。まさにその通りでした。
まだ.netの事があまり分かって無く勉強する日々です
今回は勉強になりました。

お礼日時:2011/01/29 08:18

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!