How to get the memory address of a VB (Visual Basic) variable

Problem: Sometimes the address of a variable is needed for calling a DLL function. But there is no documented built-in function or operator in VB to get the address of a variable.

Solution: The Win32 API function MulDiv can be used as a dummy function to get the address of a variable.

Note: The undocumented built-in functions VarPtr and StrPtr could also be used to get the address of a variable.

Examples:

Private Declare Function GetAddrOf Lib "KERNEL32" Alias "MulDiv" (nNumber As Any, Optional ByVal nNumerator As Long = 1, Optional ByVal nDenominator As Long = 1) As Long
   ' This is the dummy function used to get the addres of a VB variable.
Private Declare Sub MoveMemory Lib "KERNEL32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
   ' MoveMemory is used in HexDump to access arbitrary memory.

' This routine shows how to retrieve the address of a byte array.
' It dumps the contents of the array by passing its address to HexDump.
Public Sub Test1()
   Dim A(8) As Byte: A(0) = &H55: A(1) = &HAA: A(2) = &H33
   Dim Addr As Long: Addr = GetAddrOf(A(0))
   HexDump Addr, 4
   End Sub

' This routine shows how to coerce a string into a byte array and back into a string.
Public Sub Test2()
   Dim A() As Byte
   A = "ABCabc"                        ' coerce Unicode string to byte array
   Dim Addr As Long: Addr = GetAddrOf(A(0))
   HexDump Addr, UBound(A) + 1
   A(4) = Asc("Z")                     ' change the third character to "Z"
   Dim S As String: S = A              ' coerce byte array back to string
   Debug.Print "S=" & S
   End Sub

' This routine shows the difference between vbNullString and an empty string ("")
' and how to use "ByVal" when calling a DLL routine.
Public Sub Test3()
   Debug.Print GetAddrOf(ByVal vbNullString)
   Debug.Print GetAddrOf(ByVal "")
   End Sub

' This routine dumps memory in hex.
Public Sub HexDump(ByVal Addr As Long, ByVal Length As Long)
   Dim Offs: Offs = 0
   Do While Offs < Length
      Dim L As Long: L = Length - Offs: If L > 16 Then L = 16
      Dim A As Long: A = Addr + Offs
      Dim Buf(15) As Byte
      MoveMemory Buf(0), ByVal A, L
      Dim S As String: S = Hex(A)
      Dim SC As String: SC = ""
      Dim P As Long
      For P = 0 To L - 1
         Dim b As Byte: b = Buf(P)
         S = S & IIf(P = 8, "-", " ") & IIf(b < 16, "0", "") & Hex(b)
         SC = SC & IIf(b >= 32 And b <= 127, Chr(b), ".")
         Next
      S = S & Space((16 - L) * 3) & " /" & SC & "/"
      Debug.Print S
      Offs = Offs + L
      Loop
   End Sub

Author: Christian d'Heureuse (www.source-code.biz, www.inventec.ch/chdh)
License: Free / LGPL
Index