|
-
Oct 12th, 2007, 09:51 AM
#1
Thread Starter
Frenzied Member
[RESOLVED] Copymemory array
Hello!
Code:
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
Private Declare Sub ZeroMemory Lib "kernel32" Alias "RtlZeroMemory" (dst As Any, ByVal iLen&)
Dim X As Long, Y As Long
ReDim Source(0 To 500, 0 To 5) As String
For X = 0 To 5
For Y = 0 To 500
Source(Y, X) = "Item " + CStr(Y) + " in col " + CStr(X)
Next Y
Next X
ReDim out(UBound(Source, 1)) As String
CopyMemory ByVal VarPtr(out(0)), ByVal VarPtr(Source(0, 2)), 4 * (UBound(out) + 1)
ZeroMemory ByVal VarPtr(Source(0, 2)), 4 * (UBound(out) + 1)
Erase Source
MsgBox "125th element: " + out(124) + vbNewLine + "126th element:" + out(125)
End
By using this code you can simply move a 2d string arrays one indexed dimension into a single dimension array.
But if you change the variable type to Variant, everything goes to wrong. It copies the first 125 element (0-124), but after the 125th element it copies only null strings.
Do you have any ideas how can i fix this code?
Ok ive found it. Variant type string variants has 8 byte long pointers, but strings has 4. So i have to copy the 8 byte long pointers to get it to work.
Last edited by Jim Davis; Oct 12th, 2007 at 10:10 AM.
-
Oct 12th, 2007, 09:59 AM
#2
Re: Copymemory array
Edited: hang on. Testing something, be back in couple minutes
-
Oct 12th, 2007, 10:02 AM
#3
Thread Starter
Frenzied Member
Re: Copymemory array
Thanks Ive sent a PM to you a few hours before.
-
Oct 12th, 2007, 10:07 AM
#4
Thread Starter
Frenzied Member
Re: Copymemory array
Ahh i cant belive it.. it copies another 25 elements but it copies only the half of the array, then copies nullstrings....
Edited: hang on. Testing something, be back in couple minutes
Ok im waiting.. i have no idea whats wrong with it..
-
Oct 12th, 2007, 10:12 AM
#5
Re: Copymemory array
Ok, I'm back. Variants are a stranger beast. Each Variant contains 16 bytes and within those 16 bytes is a pointer to the string, which I believe is at the 8th byte within the variant structure (don't really recall without testing - FYI).
Verify: ? varptr(source(1,0))-varptr(source(0,0))
When you want to move variant pointers, multiply by 16, not 4.
Also, don't mix/match. Dim source & destination to the same. If Variants, then make destination variant.
-
Oct 12th, 2007, 10:14 AM
#6
Thread Starter
Frenzied Member
Re: Copymemory array
Yeehaw! Maximum respect to you my friend!
Code:
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
Private Declare Sub ZeroMemory Lib "kernel32" Alias "RtlZeroMemory" (dst As Any, ByVal iLen&)
Dim X As Long, Y As Long
ReDim Source(0 To 500, 0 To 5) As Variant
For X = 0 To 5
For Y = 0 To 500
Source(Y, X) = "Item " + CStr(Y) + " in col " + CStr(X)
Next Y
Next X
ReDim out(UBound(Source, 1)) As Variant
CopyMemory ByVal VarPtr(out(0)), ByVal VarPtr(Source(0, 2)), 16 * (UBound(out) + 1)
ZeroMemory ByVal VarPtr(Source(0, 2)), 16 * (UBound(out) + 1)
Erase Source
Thanks a lot.
-
Oct 12th, 2007, 04:45 PM
#7
Thread Starter
Frenzied Member
Re: [RESOLVED] Copymemory array
 Originally Posted by LaVolpe
If your arrays are large, you may want to entertain idea of converting variant to string pointer. Why? Using 500K as example: 16 byte Variant requires 8mb of memory, but 4 byte string pointer, 2mb memory requirement. The logic is simple, but does require a loop, significant changes only...
Code:
ReDim out(UBound(Source, 1)) As String
For Y = 0 To 500
CopyMemory ByVal VarPtr(out(Y)), ByVal VarPtr(Source(Y, 2)) + 8, 4& ' string pointer in variant
CopyMemory ByVal VarPtr(Source(Y, 2)) + 8, 0&, 4& ' clear string pointer in variant
Next
MsgBox "125th element: " + out(124) + vbNewLine + "126th element:" + out(125)
Thanks for sharing this useful piece of code
-
Oct 13th, 2007, 10:22 AM
#8
Re: [RESOLVED] Copymemory array
To finish up. This little hack can be used to convert Variant arrays containing numerical data to a array of just numerical data too. The final 8 bytes in the Variant structure contains the actual numerical data. If the numer is a byte, then just 8th byte used, Longs: 8-11 used, Doubles: 8-15 used.
For example the passed Variant array contains only longs
Code:
ReDim out(UBound(Source, 1)) As Long
For Y = 0 To 500
CopyMemory out(Y), ByVal VarPtr(Source(Y, 2)) + 8, 4& ' Long value in variant
' no need to erase anything, numerical data are not pointers
Next
And if the Variant array contained only Integers
Code:
ReDim out(UBound(Source, 1)) As Integer
For Y = 0 To 500
CopyMemory out(Y), ByVal VarPtr(Source(Y, 2)) + 8, 2& ' Integer value in variant
' no need to erase anything, numerical data are not pointers
Next
And if the Variant array contained only Dates
Code:
ReDim out(UBound(Source, 1)) As Date
For Y = 0 To 500
CopyMemory out(Y), ByVal VarPtr(Source(Y, 2)) + 8, 8& ' Date value in variant
' no need to erase anything, numerical data are not pointers
Next
Last edited by LaVolpe; Oct 13th, 2007 at 10:34 AM.
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
|