|
■No86044 (masa さん) に返信
> 「MoveMemoryの引数に与える値が分かる」=「メモリ上でどのように配置されて
> いるかが理解できている」逆に「メモリ配置が理解できていなければ
> MoveMemoryの引数に与える値が分からない」という理解でした。
VarPtr/StrPtr/ObjPtr の意味や、SAFEARRAY に対してどこまで理解されているのか分からなかったので、
ひとまず String データ(BSTR)の内容を出力するサンプルを書いてみました。
理解の手助けになるかは分かりませんが、参考までに。
' VB6 および VBA7.1(x64) で動作確認してあります
Option Explicit
Option Base 0
#If Win64 Then
Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32" (ByVal dst As LongPtr, ByVal src As LongPtr, ByVal length As Long)
#Else
Private Declare Sub RtlMoveMemory Lib "kernel32" (ByVal dst As OLE_HANDLE, ByVal src As OLE_HANDLE, ByVal length As Long)
#End If
Public Sub Main()
DumpBStr vbNullString
DumpBStr ""
DumpBStr "全角5文字" 'UCS-2
DumpBStr "Hankaku 21 Characters" 'UCS-2
DumpBStr "全半Mixな9文字" 'UCS-2
DumpBStr StrConv("全角5文字", vbFromUnicode, 1041) 'CP932
DumpBStr StrConv("Hankaku 21 Characters", vbFromUnicode, 1041) 'CP932
DumpBStr StrConv("全半Mixな9文字", vbFromUnicode, 1041) 'CP932
End Sub
Private Function ToHexString(ByRef bin() As Byte) As String
Dim length As Long
length = UBound(bin) + 1
Dim result As String, n As Long
result = String(length * 3, "*")
For n = 0 To length - 1
Mid(result, n * 3 + 1, 3) = "," & Right(Hex(bin(n) + &H100), 2)
Next
ToHexString = Mid(result, 2)
End Function
Private Sub DumpBStr(ByVal s As String)
' VarPtr(s)が指す場所
' ↓
' ┏━━┓
' ┃参照┃
' ┗━━┛
' 参照 => StrPtr(s) と等しい
'
'
' StrPtr(s)が指す場所
' ↓
' ┏━━┳━━━━━┯━━┓
' ┃長さ┃文字列本体│終端┃… BSTR データ
' ┗━━┻━━━━━┷━━┛
' 長さ => 2 バイト整数(文字列本体の長さ,終端部含まず)
' 文字列本体 => 0 バイト以上の可変長バイナリ(UTF-16以外でも構わない)
' 終端 => 2 バイト長のゼロ (vbNullChar)
#If Win64 Then
Dim pVar As LongPtr, pStr As LongPtr, p As LongPtr
#Else
Dim pVar As OLE_HANDLE, pStr As OLE_HANDLE, p As OLE_HANDLE
#End If
Dim length As Long
Dim b0 As Byte, b1 As Byte
Dim bin() As Byte
pVar = VarPtr(s)
pStr = StrPtr(s)
If pStr = 0 Then
Debug.Print "s = vbNullString の場合"
Else
Debug.Print "s = """ & s & """ の場合"
End If
Debug.Print "VarPtr(s) が指すアドレス値 = &H"; Hex(pVar)
Debug.Print "StrPtr(s) が指すアドレス値 = &H"; Hex(pStr)
Debug.Print "Len(s) で得られる文字数 = "; Len(s); "文字"
Debug.Print "LenB(s) で得られるサイズ = "; LenB(s); "バイト"
If pStr = 0 Then
Debug.Print
Exit Sub
End If
RtlMoveMemory VarPtr(p), pVar, 4
Debug.Print "VarPtr(s) にて参照された値 = &H"; Hex(p), "… StrPtr(s) の値に等しい"
Debug.Print "StrPtr(p)-4が指すアドレス値 = &H"; Hex(pStr - 4)
RtlMoveMemory VarPtr(length), pStr - 4, 4
Debug.Print "StrPtr(p)-4にて参照された値 = "; length; "バイト", "… LenB(s) の値に等しい"
RtlMoveMemory VarPtr(b0), StrPtr(s) + 0, 1
RtlMoveMemory VarPtr(b1), StrPtr(s) + 1, 1
Debug.Print "StrPtr(p)+0にて参照された値 = &H"; Hex(b0)
Debug.Print "StrPtr(p)+1にて参照された値 = &H"; Hex(b1)
bin = s
Debug.Print "文字列変数sの内部バイナリ値 = {"; ToHexString(bin); "}", "… 下記と等しい"
If length > 0 Then
ReDim bin(0 To length - 1) As Byte
RtlMoveMemory VarPtr(bin(0)), StrPtr(s), length
Else
bin = ""
End If
Debug.Print "StrPtr(p) にて参照された値 = {"; ToHexString(bin); "}"
ReDim bin(0 To 1)
RtlMoveMemory VarPtr(bin(0)), StrPtr(s) + length, 2
Debug.Print "文字列部の後続にある2バイト = {"; ToHexString(bin); "}", "… 常に 00,00"
Debug.Print
End Sub
|