09-07-2003, 12:49 PM
I want to use an array as an memory pointer, i have an adress stored into an long value and now I want my dummie array to point to that address, I think that should work as long as array bounds checking is off.
I think I'd have to use CopyMemory to copy the address to whereever the address of my array is stored.... but that's my actual problem - where's the adress of the data my array points to? And how to do all this???
09-07-2003, 01:10 PM
You can use the SafeArray hack for that, here's the module I use:
' begin modSafeArray.bas
Public Type SAFEARRAYBOUND ' 8 bytes
cElements As Long
lLbound As Long
Public Type SAFEARRAYHEADER ' 20 bytes (for one dimensional arrays
dimensions As Integer
fFeatures As Integer
DataSize As Long
cLocks As Long
dataPointer As Long
sab(1) As SAFEARRAYBOUND
Const FADF_AUTO = &H1& '// Array is allocated on the stack.
Const FADF_STATIC = &H2& '// Array is statically allocated.
Const FADF_EMBEDDED = &H4& '// Array is embedded in a structure.
Const FADF_FIXEDSIZE = &H10& '// Array may not be resized or reallocated.
Const FADF_BSTR = &H100& '// An array of BSTRs.
Const FADF_UNKNOWN = &H200& '// An array of IUnknown*.
Const FADF_DISPATCH = &H400& '// An array of IDispatch*.
Const FADF_VARIANT = &H800& '// An array of VARIANTs.
Const FADF_RESERVED = &HF0E8& '// Bits reserved for future use.
Public Enum eDATASIZE
byteArray = 1
integerArray = 2 ' or Boolean Data Type
longArray = 4
singleArray = 4
doubleArray = 8
'Public Declare Function VarPtrArray Lib "msvbvm50.dll" Alias "VarPtr" (Var() As Any) As Long
Public Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Var() As Any) As Long
Public Function RedimArray(ByVal DataSize As eDATASIZE, ByVal lNumElements As Long, ByRef sa As SAFEARRAYHEADER, ByVal lDataPointer As Long, ByVal lArrayPointer As Long, Optional LoBound As Long = 0) As Long
If lNumElements > 0 And lDataPointer <> 0 And lArrayPointer <> 0 Then
.DataSize = DataSize ' byte = 1 byte, integer = 2 bytes etc
.dimensions = 1 '2 ' one dimensional
.dataPointer = lDataPointer ' to unicode string data (or other?)
.sab(0).lLbound = LoBound ' lower bound
.sab(0).cElements = lNumElements ' number of elements
'.sab(1).cElements = lNumElements
'.sab(1).lLbound = LoBound
RtlMoveMemory ByVal lArrayPointer, VarPtr(sa), 4& ' fake VB out
RedimArray = True
Public Sub DestroyArray(ByVal lArrayPointer As Long)
Dim lZero As Long
RtlMoveMemory ByVal lArrayPointer, lZero, 4 ' put the array back to its original state
09-07-2003, 01:15 PM
ok, but how could I find out lDataPointer and lArrayPointer? Does VB still use the same structure when not checking array bounds?
Why do you only copy 4 bytes to the Array pointer and not 20?
09-07-2003, 01:25 PM
lArrayPointer comes from VarPtrArray. Save it to pass to DeleteArray also.
lDataPointer is VarPtr(foo(firstElement) or in your case, the pointer you have to your data.
Copying 4 bytes to make VB use our "fake" SafeArray structure.
09-07-2003, 01:50 PM
This means, I'm not actually manipulating VB's safe array structure I'm just advising VB to use my safe array structure instead of the original one? Isn't there an way to find out where the real struct resists?
Ok, What flags do I have to define in my case? I'm wondering why there are even flags, for me memory is just memory, there shouldn't be any difference between dynamic one and static one or so...
Thx for your help!
09-07-2003, 01:56 PM
VarPtrArray is the pointer to the safearray struct. It's easiest just to temporarily point to your own sa.
You shouldn't have to worry about flags, if you're not passing this "fake" array.
09-07-2003, 02:35 PM
I don't get it.... does the RtlMoveMemory function have to be declared in an special way?
My app always crashes, it seems to have no effect... Here's some of my code:
'These are my dummie arrays I want to use to safe the data
'each array has an SAFEARRAYHEADER containing the informations
'and an pointer to the actual data of the array
Private VertPos(0) As vBPoint
Private sah_pos As SAFEARRAYHEADER
Private pPos As Long
Private VertPV(0) As vPVData
Private sah_pv As SAFEARRAYHEADER
Private pPV As Long
Private VertMV(0) As vMVData
Private sah_mv As SAFEARRAYHEADER
Private pMV As Long
'Create the memory buffers and lock them
Set bBPoint = D3Ddevice.CreateVertexBuffer(vBP_size * numVerts, 0, 0, D3DPOOL_MANAGED)
bBPoint.Lock 0, vBP_size * numVerts, pPos, 0
Set bMVData = D3Ddevice.CreateVertexBuffer(vMV_size * numVerts, 0, 0, D3DPOOL_MANAGED)
bMVData.Lock 0, vMV_size * numVerts, pMV, 0
Set bPVData = D3Ddevice.CreateVertexBuffer(vPV_size * numVerts, 0, 0, D3DPOOL_MANAGED)
bPVData.Lock 0, vPV_size * numVerts, pPV, 0
'Set up the dummie arrays
RedimArray vBP_size, numVerts, sah_pos, pPos, VarPtrArray(VertPos())
RedimArray vMV_size, numVerts, sah_mv, pMV, VarPtrArray(VertMV())
RedimArray vPV_size, numVerts, sah_pv, pPV, VarPtrArray(VertPV())
Dim rVert As BSPvertex 'This is the vertex I read out of my file
....read out the info out of the file and store into my dummie arrays VertMV, VertPV and VertPos
do you have any idea what's the problem here?
09-07-2003, 03:45 PM
Two things I see right off. First, Dim the arrays as dynamic. Second, call DestroyArray before the end of the procedure.
09-08-2003, 08:42 AM
Wow, it works! These "pointers" are very usefull! Could I also set an normal variable to point to another memory location?
09-09-2003, 09:27 AM
Long variables are 32bits and can contain pointers to memory locations.