Results 1 to 8 of 8

Thread: VarPtr strange result

  1. #1

    Thread Starter
    Fanatic Member VBAhack's Avatar
    Join Date
    Dec 2004
    Location
    Sector 000
    Posts
    617

    VarPtr strange result

    This has me baffled:

    Code:
    Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As Any, _
        Source As Any, ByVal bytes As Long)
    
    Sub VarPtrTest()
        Dim L1 As Long, L2 As Long, p1 As Long, A(1) As Long, v1 As Variant
        
        v1 = A                                  'assign array of long to the variant
        p1 = VarPtr(v1(0))
        CopyMemory L1, ByVal p1, 4              'get 1st 4 bytes
        CopyMemory L2, ByVal VarPtr(v1(0)), 4   'get 1st 4 bytes
        Debug.Print p1; VarPtr(v1(0)); L1; L2   '1308228  1308228  0  16387
    End Sub
    1. Any idea why L1 and L2 are not the same even though p1 and VarPtr(v1(0)) are the same number?

    2. Any idea what varPtr(v1(0)) really points to?

  2. #2
    PowerPoster
    Join Date
    Nov 2002
    Location
    Manila
    Posts
    7,629

    Re: VarPtr strange result

    Issue similar to double() in a variant. It was left unanswered. It seems VarPtr doesn't work as expected for arrays in a variant. Try assigning values to the array and you'll see that both results, 0 and 16387, were actually garbage.

  3. #3
    PowerPoster
    Join Date
    Nov 2002
    Location
    Manila
    Posts
    7,629

    Re: VarPtr strange result

    Also, try debug printing VarPtr of other array elements... VarPtr(v1(0)) = VarPtr(v1(1)) = VarPtr(v1(2)) ... it doesn't work, how it came up with 1308228 (or why that particular value was returned) for all array elements remains to be answered.

  4. #4
    Cumbrian Milk's Avatar
    Join Date
    Jan 2007
    Location
    0xDEADBEEF
    Posts
    2,448

    Re: VarPtr strange result

    I don't know why it does that but I can see what it's doing in part. The 1308228 appears to be an address of a variant. The 16387 is the first two bytes of a variant, it indicates that the variant holds a pointer to a long (16384=contains pointer, 3=Long). Try assigning a value to V1(0) and then use the code below
    Code:
        CopyMemory L1, ByVal p1 + 8, 4
        CopyMemory L1, ByVal L1, 4
        
        CopyMemory L2, ByVal VarPtr(v1(0)) + 8, 4
        CopyMemory L2, ByVal L2, 4
        
        Debug.Print L1, L2, v1(0)
    The strange part for me is why when you use Byval P1 the first two bytes of the variant are missing? The rest of the variant is exactly the same.
    Last edited by Milk; Jun 12th, 2008 at 06:30 AM.

  5. #5

    Thread Starter
    Fanatic Member VBAhack's Avatar
    Join Date
    Dec 2004
    Location
    Sector 000
    Posts
    617

    Re: VarPtr strange result

    Quote Originally Posted by Milk
    it indicates that the variant holds a pointer to a long (16384=contains pointer, 3=Long).
    Where did you find that 16384 means pointer? Is there a web reference you can post?

  6. #6
    Cumbrian Milk's Avatar
    Join Date
    Jan 2007
    Location
    0xDEADBEEF
    Posts
    2,448

    Re: VarPtr strange result

    I could not find any reference I'm afraid but testing showed it to be pretty consistent.
    The first byte indicates the data type, the second seems to indicate what is stored in the data section of the Variant structure.

    The second byte always seems to be one of four values...

    00 - The variant contains the variable data (in the case of a Pointer based data types like String and Object this data is a pointer)
    32 - As documented in MSDN this is the vbArray type, got to look at exactly what this means, I suspect it indicates an array of variants. (your original post seems to demonstrate this)
    64 - The variant contains a pointer to the variable data
    96 - The variant contains a pointer to a pointer to a SafeArray structure (same as the return for VarptrArray)

    One thing I did notice today is that there is a big difference between assigning a variable to a variant and passing a variable as a variant. I'm going to look at this in more detail later.

    I also keep seeing the odd thing that talks of a 22 byte char variant, but I've not been able to create one of these.

  7. #7

    Thread Starter
    Fanatic Member VBAhack's Avatar
    Join Date
    Dec 2004
    Location
    Sector 000
    Posts
    617

    Re: VarPtr strange result

    Quote Originally Posted by Milk
    I could not find any reference I'm afraid but testing showed it to be pretty consistent. The first byte indicates the data type, the second seems to indicate what is stored in the data section of the Variant structure.

    The second byte always seems to be one of four values...

    64 - The variant contains a pointer to the variable data
    I see your point. Seems to work as you indicate for arrays of most data types, but it breaks down if variant() is used. This is v-e-r-y strange...

    Code:
        Dim L1 As Integer
        Dim v1 As Variant
        Dim b1 As Byte, b2 As Byte
        Dim a(1) As Long
        Dim b(1) As Double
        Dim c(1) As Byte
        Dim d(1) As Single
        Dim E(1) As Boolean
        Dim F(1) As String
        Dim G(1) As FileDialog
        Dim H(1) As Single
        Dim I(1) As Integer
        Dim J(1) As Variant
    
        v1 = I
        CopyMemory L1, ByVal VarPtr(v1(0)), 2
        CopyMemory b1, ByVal VarPtr(v1(0)), 1
        CopyMemory b2, ByVal VarPtr(v1(0)) + 1, 1
        Debug.Print VarPtr(v1(0)); L1; L1 - vbInteger; "Integer", vbInteger, b1, b2
        v1 = a
        CopyMemory L1, ByVal VarPtr(v1(0)), 2
        CopyMemory b1, ByVal VarPtr(v1(0)), 1
        CopyMemory b2, ByVal VarPtr(v1(0)) + 1, 1
        Debug.Print VarPtr(v1(0)); L1; L1 - vbLong; "Long", , vbLong, b1, b2
        v1 = d
        CopyMemory L1, ByVal VarPtr(v1(0)), 2
        CopyMemory b1, ByVal VarPtr(v1(0)), 1
        CopyMemory b2, ByVal VarPtr(v1(0)) + 1, 1
        Debug.Print VarPtr(v1(0)); L1; L1 - vbSingle; "Single", vbSingle, b1, b2
        v1 = b
        CopyMemory L1, ByVal VarPtr(v1(0)), 2
        CopyMemory b1, ByVal VarPtr(v1(0)), 1
        CopyMemory b2, ByVal VarPtr(v1(0)) + 1, 1
        Debug.Print VarPtr(v1(0)); L1; L1 - vbDouble; "Double", vbDouble, b1, b2
        v1 = F
        CopyMemory L1, ByVal VarPtr(v1(0)), 2
        CopyMemory b1, ByVal VarPtr(v1(0)), 1
        CopyMemory b2, ByVal VarPtr(v1(0)) + 1, 1
        Debug.Print VarPtr(v1(0)); L1; L1 - vbString; "String", vbString, b1, b2
        v1 = G
        CopyMemory L1, ByVal VarPtr(v1(0)), 2
        CopyMemory b1, ByVal VarPtr(v1(0)), 1
        CopyMemory b2, ByVal VarPtr(v1(0)) + 1, 1
        Debug.Print VarPtr(v1(0)); L1; L1 - vbObject; "Object", vbObject, b1, b2
        v1 = E
        CopyMemory L1, ByVal VarPtr(v1(0)), 2
        CopyMemory b1, ByVal VarPtr(v1(0)), 1
        CopyMemory b2, ByVal VarPtr(v1(0)) + 1, 1
        Debug.Print VarPtr(v1(0)); L1; L1 - vbBoolean; "Boolean", vbBoolean, b1, b2
        v1 = c
        CopyMemory L1, ByVal VarPtr(v1(0)), 2
        CopyMemory b1, ByVal VarPtr(v1(0)), 1
        CopyMemory b2, ByVal VarPtr(v1(0)) + 1, 1
        Debug.Print VarPtr(v1(0)); L1; L1 - vbByte; "Byte", , vbByte, b1, b2
        v1 = J
        CopyMemory L1, ByVal VarPtr(v1(0)), 2
        CopyMemory b1, ByVal VarPtr(v1(0)), 1
        CopyMemory b2, ByVal VarPtr(v1(0)) + 1, 1
        Debug.Print VarPtr(v1(0)); L1; L1 - vbVariant; "Variant", , vbVariant, b1, b2
        ' 1307968  16386  16384 Integer             2             2             64
        ' 1307968  16387  16384 Long                3             3             64
        ' 1307968  16388  16384 Single              4             4             64
        ' 1307968  16389  16384 Double              5             5             64
        ' 1307968  16392  16384 String              8             8             64
        ' 1307968  16393  16384 Object              9             9             64
        ' 1307968  16395  16384 Boolean             11            11            64
        ' 1307968  16401  16384 Byte                17            17            64
        ' 195686664  0 -12 Variant                  12            0             0

  8. #8
    Cumbrian Milk's Avatar
    Join Date
    Jan 2007
    Location
    0xDEADBEEF
    Posts
    2,448

    Re: VarPtr strange result

    Your strange result is because V1(0) is an empty variant... 16 bytes of zero.
    195686664 can't be a valid address can it? It would be way off the stack. I've no idea why Varptr appears to be failing in this case.

    Try this
    Code:
        v1 = J
        'v1(0) = "hello" '<--- toggle this
        CopyMemory L1, v1(0), 2
        b1 = L1 And 255
        b2 = L1 \ 256
    Have a look at the other Variant thread you started, the code I posted has had no problems (so far) with any variant I've thought to throw at it (including public udt's)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width