SilentRage
asked on
Retrieving an array's pointer
Before the question, I need to be sure we're straight on a few facts:
VISUAL BASIC & ARRAY POINTERS
Dim MyArray(2) As String
MyArray(0) = "jim"
MyArray(1) = "joe"
MyArray(2) = "jon"
In memory the array is comprised of three 4 byte elements. Each element is a pointer to the actual string. To get the element's address in memory you use VarPtr(MyArray(X)). The easy way to get that element's value you may use StrPtr(MyArray(X)).
So here we have an array floating in memory:
Address: VarPtr0 VarPtr1 VarPtr2
Value: StrPtr0 StrPtr1 StrPtr2
It's an easy thing to replace the values for each element so that each element points to a different string. You can find numerous articles on string sorting algorithms using such a technique. However, I need the array variable itself to point to a completely different array. Now of course, we could do something like this:
'We create an array with a null pointer
Dim Array1() As String
'We create an array with a pointer to an allocated array
'(although, each element is a null pointer)
Dim Array2(2) As String
Array1 = Array2
Array1 now has 3 elements. Seems like we did a pointer assignment. But we didn't. Cause if you do this test:
Debug.Print VarPtr(Array1(0)), VarPtr(Array2(0))
You'll find that the element addresses are completely different. If we DID assign a pointer to the entire array to Array1, then if you modified Array2, you'll be modifying Array1. But that is not the case. Instead, VB copied the array.
THE SITUATION
I have a dynamic 3 dimensional array. I am not allowed to ReDimension the array's first 2 dimensions. However, it is required that this array be completely dynamic, and I've been searching for workarounds. My favorite idea is to create a new array by the required dimensions and swap the 2 array variable's pointers. That way when the routine ends, VB will free up the memory pointed to by the temporary array variable, and leave my original array variable, and its new contents, alone.
Nice story huh? Well, I know the theory works cause it works like that with individual elements. You can swap element pointers and have a happy day.
THE PROBLEM
I can't get the address of an array variable.
Diagram:
MyArray---->ADDRESS==ptr1- ->VALUE==p tr2
MyArray(0)->ADDRESS==ptr2- ->VALUE==s trptr
The variable MyArray points to the first element of the actual allocated array. The VALUE of MyArray isn't hard to get. All you have to do is VarPtr() the first element. But I don't have the ADDRESS of MyArray (ptr1 in the diagram). I need that address in order to change the value to the pointer of a different array. VarPtr(MyArray) does not work. I get type errors.
*whew* that's it. Sorry for being so verbose, but I wanted to be absolutely clear.
VISUAL BASIC & ARRAY POINTERS
Dim MyArray(2) As String
MyArray(0) = "jim"
MyArray(1) = "joe"
MyArray(2) = "jon"
In memory the array is comprised of three 4 byte elements. Each element is a pointer to the actual string. To get the element's address in memory you use VarPtr(MyArray(X)). The easy way to get that element's value you may use StrPtr(MyArray(X)).
So here we have an array floating in memory:
Address: VarPtr0 VarPtr1 VarPtr2
Value: StrPtr0 StrPtr1 StrPtr2
It's an easy thing to replace the values for each element so that each element points to a different string. You can find numerous articles on string sorting algorithms using such a technique. However, I need the array variable itself to point to a completely different array. Now of course, we could do something like this:
'We create an array with a null pointer
Dim Array1() As String
'We create an array with a pointer to an allocated array
'(although, each element is a null pointer)
Dim Array2(2) As String
Array1 = Array2
Array1 now has 3 elements. Seems like we did a pointer assignment. But we didn't. Cause if you do this test:
Debug.Print VarPtr(Array1(0)), VarPtr(Array2(0))
You'll find that the element addresses are completely different. If we DID assign a pointer to the entire array to Array1, then if you modified Array2, you'll be modifying Array1. But that is not the case. Instead, VB copied the array.
THE SITUATION
I have a dynamic 3 dimensional array. I am not allowed to ReDimension the array's first 2 dimensions. However, it is required that this array be completely dynamic, and I've been searching for workarounds. My favorite idea is to create a new array by the required dimensions and swap the 2 array variable's pointers. That way when the routine ends, VB will free up the memory pointed to by the temporary array variable, and leave my original array variable, and its new contents, alone.
Nice story huh? Well, I know the theory works cause it works like that with individual elements. You can swap element pointers and have a happy day.
THE PROBLEM
I can't get the address of an array variable.
Diagram:
MyArray---->ADDRESS==ptr1-
MyArray(0)->ADDRESS==ptr2-
The variable MyArray points to the first element of the actual allocated array. The VALUE of MyArray isn't hard to get. All you have to do is VarPtr() the first element. But I don't have the ADDRESS of MyArray (ptr1 in the diagram). I need that address in order to change the value to the pointer of a different array. VarPtr(MyArray) does not work. I get type errors.
*whew* that's it. Sorry for being so verbose, but I wanted to be absolutely clear.
Forget that
what about objptr ??
ASKER
what about objptr. That's for retrieving the pointer to an object variable. That doesn't apply here.
ASKER
I found a suitable solution. Here's the function that will allow you to have complete dynamic control over resizing a multi-dimensional array.
I didn't bother to make this function generic. So feel free to modify to your personal needs. In this example, you should know that 'Maze' is a 3 dimensional array. Also, after resizing it, it has all original data (Preserved). Also, 'MazeRoom' is a user-defined type.
Public Function Resize(ByVal X As Integer, ByVal Y As Integer, ByVal Z As Integer)
Dim TmpMaze() As MazeRoom, IUB As Integer, JUB As Integer, KUB As Integer
'Copy the original array to a temporary array var
TmpMaze = Maze
'Erase the original array
Erase Maze
'Redimension the original array to the new larger or smaller size
ReDim Maze(X, Y, Z) As MazeRoom
'Calculate the upper bound to be used when coping data back in
IUB = IIf(UBound(TmpMaze, 1) > X, UBound(TmpMaze, 1), X)
JUB = IIf(UBound(TmpMaze, 2) > Y, UBound(TmpMaze, 2), Y)
KUB = IIf(UBound(TmpMaze, 3) > Z, UBound(TmpMaze, 3), Z)
'Now we 'Preserve' the data by copying it back to the newly dimensioned array
For I = 0 To IUB
For J = 0 To JUB
For K = 0 To KUB
'Do a pointer/value copy (will not work for Integer or byte arrays)
CopyMemory Maze(I, J, K), TmpMaze(I, J, K), 4
Next
Next
Next
End Function
I may have found the solution to my programming problem. But if there's any way to get the array pointer, that would make things a lot easier - and efficient.
also: general question. If nobody can give me an answer - or if there isn't an answer - is there any way to reclaim my question points?
I didn't bother to make this function generic. So feel free to modify to your personal needs. In this example, you should know that 'Maze' is a 3 dimensional array. Also, after resizing it, it has all original data (Preserved). Also, 'MazeRoom' is a user-defined type.
Public Function Resize(ByVal X As Integer, ByVal Y As Integer, ByVal Z As Integer)
Dim TmpMaze() As MazeRoom, IUB As Integer, JUB As Integer, KUB As Integer
'Copy the original array to a temporary array var
TmpMaze = Maze
'Erase the original array
Erase Maze
'Redimension the original array to the new larger or smaller size
ReDim Maze(X, Y, Z) As MazeRoom
'Calculate the upper bound to be used when coping data back in
IUB = IIf(UBound(TmpMaze, 1) > X, UBound(TmpMaze, 1), X)
JUB = IIf(UBound(TmpMaze, 2) > Y, UBound(TmpMaze, 2), Y)
KUB = IIf(UBound(TmpMaze, 3) > Z, UBound(TmpMaze, 3), Z)
'Now we 'Preserve' the data by copying it back to the newly dimensioned array
For I = 0 To IUB
For J = 0 To JUB
For K = 0 To KUB
'Do a pointer/value copy (will not work for Integer or byte arrays)
CopyMemory Maze(I, J, K), TmpMaze(I, J, K), 4
Next
Next
Next
End Function
I may have found the solution to my programming problem. But if there's any way to get the array pointer, that would make things a lot easier - and efficient.
also: general question. If nobody can give me an answer - or if there isn't an answer - is there any way to reclaim my question points?
Goto Community support -> Cleanup -> Ask a question
Question title Please delete Question
Question Body Link to question
Question title Please delete Question
Question Body Link to question
ASKER
thanks.
Small bug. Serves me right to post before testing. Change out the > with < in the upper bound calculation. Also, since I'm making another post anyway. That part where I say that it doesn't work for byte or integer arrays? that line of code has a 4 on the end. Change to 1 for byte arrays. Change to 2 for integer arrays.
Small bug. Serves me right to post before testing. Change out the > with < in the upper bound calculation. Also, since I'm making another post anyway. That part where I say that it doesn't work for byte or integer arrays? that line of code has a 4 on the end. Change to 1 for byte arrays. Change to 2 for integer arrays.
ASKER
thanks.
Small bug. Serves me right to post before testing. Change out the > with < in the upper bound calculation. Also, since I'm making another post anyway. That part where I say that it doesn't work for byte or integer arrays? that line of code has a 4 on the end. Change to 1 for byte arrays. Change to 2 for integer arrays.
Small bug. Serves me right to post before testing. Change out the > with < in the upper bound calculation. Also, since I'm making another post anyway. That part where I say that it doesn't work for byte or integer arrays? that line of code has a 4 on the end. Change to 1 for byte arrays. Change to 2 for integer arrays.
ASKER
darnit. don't ever refresh a page after posting...
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Private Function GetPointer(obj As Variant) As Long
GetPointer = VarPtr(obj)
End Function