|
-
Jun 12th, 2008, 12:17 AM
#1
Thread Starter
Fanatic Member
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?
-
Jun 12th, 2008, 12:36 AM
#2
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.
-
Jun 12th, 2008, 05:10 AM
#3
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.
-
Jun 12th, 2008, 06:27 AM
#4
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.
-
Jun 12th, 2008, 10:26 AM
#5
Thread Starter
Fanatic Member
Re: VarPtr strange result
 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?
-
Jun 12th, 2008, 11:18 AM
#6
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.
-
Jun 13th, 2008, 03:40 PM
#7
Thread Starter
Fanatic Member
Re: VarPtr strange result
 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
-
Jun 13th, 2008, 04:33 PM
#8
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|