To further expand on where is SAFEARRAY
var type stored and explore what exactly the SafeArrayGetVartype
function and other SafeArray
functions are doing see:
SafeArrayGetVartype
/* Memory Layout of a SafeArray:
*
* -0x10: start of memory.
* -0x10: GUID for VT_DISPATCH and VT_UNKNOWN safearrays (if FADF_HAVEIID)
* -0x04: DWORD varianttype; (for all others, except VT_RECORD) (if FADF_HAVEVARTYPE)
* -0x4: IRecordInfo* iface; (if FADF_RECORD, for VT_RECORD (can be NULL))
* 0x00: SAFEARRAY,
* 0x10: SAFEARRAYBOUNDS[0...]
*/
For the following integer array declaration using MS Access VBA 7 where address references are 8 bytes in size.
Dim myArray() As Integer
ReDim myArray(9)
Memory dump for the SafeArray structure including preceding hidden VT data using MS Access VBA 7
Pos Address Dec Address Hex Hex
0 (1185248224) (46A573E0) >> 0h
1 (1185248225) (46A573E1) >> 0h
2 (1185248226) (46A573E2) >> 0h
3 (1185248227) (46A573E3) >> 0h
4 (1185248228) (46A573E4) >> 0h
5 (1185248229) (46A573E5) >> 0h
6 (1185248230) (46A573E6) >> 0h
7 (1185248231) (46A573E7) >> 0h
8 (1185248232) (46A573E8) >> 0h
9 (1185248233) (46A573E9) >> 0h
10 (1185248234) (46A573EA) >> 0h
11 (1185248235) (46A573EB) >> 0h
-------------------------------------------------------------------------------------
Hidden DWord for VT when FADF_HAVEVARTYPE = 0x0080
VT = 2 i.e. Integer
12 (1185248236) (46A573EC) >> 2h
13 (1185248237) (46A573ED) >> 0h
14 (1185248238) (46A573EE) >> 0h
15 (1185248239) (46A573EF) >> 0h
-------------------------------------------------------------------------------------
cDims = 1 i.e. One dimensional array
16 (1185248240) (46A573F0) >> 1h
17 (1185248241) (46A573F1) >> 0h
-------------------------------------------------------------------------------------
fFeatures = FADF_HAVEVARTYPE
18 (1185248242) (46A573F2) >> 80h
19 (1185248243) (46A573F3) >> 0h
-------------------------------------------------------------------------------------
cbElements = 2 i.e. element size is 2 bytes
20 (1185248244) (46A573F4) >> 2h
21 (1185248245) (46A573F5) >> 0h
22 (1185248246) (46A573F6) >> 0h
23 (1185248247) (46A573F7) >> 0h
-------------------------------------------------------------------------------------
cLocks
24 (1185248248) (46A573F8) >> 0h
25 (1185248249) (46A573F9) >> 0h
26 (1185248250) (46A573FA) >> 0h
27 (1185248251) (46A573FB) >> 0h
-------------------------------------------------------------------------------------
Padding
28 (1185248252) (46A573FC) >> 0h
29 (1185248253) (46A573FD) >> 0h
30 (1185248254) (46A573FE) >> 0h
31 (1185248255) (46A573FF) >> 0h
-------------------------------------------------------------------------------------
pvData
32 (1185248256) (46A57400) >> 0h
33 (1185248257) (46A57401) >> 97h
34 (1185248258) (46A57402) >> DCh
35 (1185248259) (46A57403) >> 1Bh
36 (1185248260) (46A57404) >> 0h
37 (1185248261) (46A57405) >> 0h
38 (1185248262) (46A57406) >> 0h
39 (1185248263) (46A57407) >> 0h
-------------------------------------------------------------------------------------
rgsabound(0).cElements = 10
40 (1185248264) (46A57408) >> Ah
41 (1185248265) (46A57409) >> 0h
42 (1185248266) (46A5740A) >> 0h
43 (1185248267) (46A5740B) >> 0h
-------------------------------------------------------------------------------------
rgsabound(0).lLbound
44 (1185248268) (46A5740C) >> 0h
45 (1185248269) (46A5740D) >> 0h
46 (1185248270) (46A5740E) >> 0h
47 (1185248271) (46A5740F) >> 0h
Note for VBA 7 64 Bit shows the offset for SAFEARRAYBOUNDS[0...]
at +24 Dec, +18 hex due to the 8-byte memory address for pvData
and padding.
I hope that helps further explain what exactly any of the SafeArray
functions are performing and wherein the SafeArray
structure items are located. If anyone is manually manipulating SafeArray
structures be careful of any padding and getting your offsets correct.
I'll also try and get around to your query regarding VT_I4(3) or VT_R4(4).
There's definitely something extra going on in VBA then what the SafeArray.c functions are performing as from testing using SafeArrayDescriptorEx to create an initialized empty Integer Array the cbElements weren't set, the preceding VT was set. Strangely the VBA integer Array still worked without the cbElements set to 2 bytes for an Integer Array. When creating the SafeArrayDescriptor I now set the cbElements, manually.
When created using the above VBA example the cbElements were set appropriately.
In the SafeArray.c functions they aren't returning a SizeOf(VT_I4) or SizeOf(VT_R4) i.e. not supported in C, so I assume in VBA must expanding on the SafeArray.c functions and catering for its data types not covered in C.
Someone more with more knowledge of C might be able to clarify or explain better.