使用CopyMemory的API函数,内存拷贝。
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, Source As Any, ByVal Length As Long)
VB代码Sample如下:
功能描述:VB通过调用C++接口读取二进制文件,按照约定格式按序读取Data,读出的二进制内容转换成字符串(16进制格式字符串);
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'C++接口的定义
'typedef struct {
' UINT NoID;
' LPSTR lpData;
' DWORD dwLen;
'}DNLOADDATA;
'
'typedef BOOL (WINAPI *TESTOPENFILE)(char* inszfilename);
'typedef void (WINAPI *TESTCLOSEFILE)(void);
'typedef BOOL (WINAPI *TESTGETINFOBYINDEX)(DWORD dwIndex,DNLOADDATA *dnloadDATA);
'typedef DWORD (WINAPI *TESTGETTOTALNUM)(void);
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function TESTOpenFile Lib "TEST.dll" (ByVal inszfilename As String) As Boolean
Private Declare Sub TESTCloseFile Lib "TEST.dll" ()
Private Declare Function TESTGetTotalNum Lib "TEST.dll" () As Long
'Private Declare Function TESTGetInfoByIndex Lib "TEST.dll" (ByVal dwIndex As Long, ByRef aDNLoadDATA As DNLOADDATA_A) As Boolean
Private Declare Function TESTGetInfoByIndex Lib "TEST.dll" (ByVal dwIndex As Long, ByRef aDNLoadDATA As DNLOADDATA_B) As Boolean
Private Type myDATA
NoID As String
DATA As String
End Type
Private m_myDATA() As myDATA
Private Type DNLOADDATA_B
NoID(4 - 1) As Byte
lpData(1) As Long '第0位:存放Data地址; 第1位:存放Data长度(301个byte);
dwLen As Long
End Type
'Private Type DNLOADDATA_A
' NoID As Long '只能取到内存地址
' lpData As String '不能用string, 遇到ascii 0就自动结束了, 导致数据不全
' dwLen As Long
'End Type
Private Sub FileToArray()
Dim b As Boolean
Dim aDNLoadDATA As DNLOADDATA_B
Dim nIndex As Long
Me.MousePointer = 11
Dim nTotalNum As Long
nTotalNum = TEST_GetTotalNum() '调用TESTGetTotalNum接口
Dim aByte1() As Byte
Dim n As Long
Dim nNoID As Long
Dim sNoID As String
Dim sDATA As String
ReDim m_myDATA(0)
For n = 0 To nTotalNum - 1
b = TEST_GetInfoByIndex_B(n, aDNLoadDATA) '调用TESTGetInfoByIndex接口
If b = False Then
MsgBox "获取第 " & n & " 个DATA Data出错!", vbCritical
Exit Sub
End If
'NoID
nNoID = aDNLoadDATA.NoID(3) + aDNLoadDATA.NoID(2) * 2 ^ 8 + aDNLoadDATA.NoID(1) * 2 ^ 16 + aDNLoadDATA.NoID(0) * 2 ^ 24 '计算NoID值
sNoID = Format$(nNoID, "000000000") '转成固定9位字符串, 不够补零
'Data
ReDim aByte1(aDNLoadDATA.lpData(1) - 1) '重新定义长度(根据data的长度定义), 第1位:存放Data长度(301个byte);
CopyMemory aByte1(0), ByVal aDNLoadDATA.lpData(0), 301 '关键:通过内存拷贝方式把地址中的数据存放到byte数组
'byte转换成string
If ByteToStr(aByte1, sDATA) = False Then
MsgBox "bytetostr error"
Exit Sub
End If
'Check NoID
If Len(sNoID) <> 9 Then
MsgBox "第" & n & "个NoID: " & sNoID & "有错误, 长度不为9."
Exit Sub
End If
If IsNumeric(sNoID) = False Then
MsgBox "第" & n & "个NoID: " & sNoID & "有错误, 不为有效的数字."
Exit Sub
End If
'Check DATA
If Len(sDATA) <> 602 Then
MsgBox "第" & n & "个DATA有错误, 长度不为602."
Exit Sub
End If
'数据放入数组中
ReDim Preserve m_myDATA(n + 1) '增加一个长度
With m_myDATA(n + 1)
.NoID = sNoID
.DATA = sDATA
End With
Next n
Me.MousePointer = 0
End Sub
'byte数组转换为string
Private Function ByteToStr(aByte() As Byte, ByRef sReturnDATA As String) As Boolean
Dim strTmp As String
Dim m As Long
strTmp = ""
For m = 0 To UBound(aByte)
strTmp = strTmp & IIf(aByte(m) < 16, "0" & Hex$(aByte(m)), Hex$(aByte(m))) '& Space(1)
Next m
sReturnDATA = strTmp
ByteToStr = True
End Function
'string转换为byte数组
Private Function StrToByte(ByVal sDATA As String, ByRef aByte() As Byte) As Boolean
Dim n As Long, i As Long
n = Len(sDATA) / 2
If n <= 0 Then
Exit Function
End If
ReDim aByte(n - 1)
For i = 0 To n - 1
aByte(i) = Val("&H" & Mid$(sDATA, i * 2 + 1, 2))
Next i
StrToByte = True
End Function
'封装C++接口
Public Function TEST_OpenFile(ByVal sFileName As String) As Boolean
On Error GoTo errDeal
TEST_OpenFile = TESTOpenFile(sFileName)
Exit Function
errDeal:
MsgBox Err.Description
On Error GoTo 0
End Function
'封装C++接口
Public Function TEST_GetTotalNum() As Long
On Error GoTo errDeal
TEST_GetTotalNum = TESTGetTotalNum()
Exit Function
errDeal:
MsgBox Err.Description
On Error GoTo 0
End Function
'封装C++接口
Public Sub TEST_CloseFile()
On Error GoTo errDeal
Call TESTCloseFile
Exit Sub
errDeal:
MsgBox Err.Description
On Error GoTo 0
End Sub
'封装C++接口
'Public Function TEST_GetInfoByIndex(ByVal nIndex As Long, ByRef aDNLoadDATA As DNLOADDATA_A) As Boolean
' On Error GoTo errDeal
'
' TEST_GetInfoByIndex = TESTGetInfoByIndex(nIndex, aDNLoadDATA)
'
' Exit Function
'
'errDeal:
' MsgBox Err.Description
' On Error GoTo 0
'End Function
'封装C++接口
Private Function TEST_GetInfoByIndex_B(ByVal nIndex As Long, ByRef aDNLoadDATA As DNLOADDATA_B) As Boolean
On Error GoTo errDeal
TEST_GetInfoByIndex_B = TESTGetInfoByIndex(nIndex, aDNLoadDATA)
Exit Function
errDeal:
MsgBox Err.Description
On Error GoTo 0
End Function