我想知道SAFEARRAY的实现。
在我看来,SAFEARRAY结构中没有用于存储元素类型信息的字段,如VT_I4(3)或VT_R4(4),但是SafeArrayGetVartype函数返回正确的类型。
有人在下面的MSDN页面上评论说,cLocks的高字包含类型信息:MSDN的SAFEARRAY结构。
但是,当我通过类型libray将长数组和单个数组从VBA传递到DLL函数时,这些数组的fFeatures都是0x80,cLocks都是0,stll SafeArrayGetVartype可以告诉VT_I4(3)和VT_R4(4)。
发布于 2013-09-13 12:55:10
取决于安全射线是如何创建的,变体类型可以在SAFEARRAY结构开始之前(从开始的偏移量-4处)存储在内存中。FADF_HAVEVARTYPE标志在fFeatures中指示类型是否可用。
类似地,FADF_HAVEIID表示GUID (参见SafeArrayCreateEx)存储在偏移量为-16,并可通过SafeArrayGetIID获得。FADF_HAVEVARTYPE和FADF_HAVEIID永远不可能同时出现(因为否则VARTYPE和GUID将在内存中重叠),但是SafeArrayGetVartype足够聪明,当它看到相应的特性标志时,可以合成VT_RECORD、VT_DISPATCH或VT_UNKNOWN类型之一。
发布于 2013-09-13 12:54:22
您从不手动初始化SAFEARRAY,它始终是调用SafeArrayCreate的产物,它为该结构分配内存。我认为可以假设为SafeArray的内部数据结构分配了一些额外的字节。这就是可以存储任何扩展类型信息的地方。
发布于 2019-08-30 15:16:04
为了进一步扩展SAFEARRAY var类型的存储位置,并探究SafeArrayGetVartype函数和其他SafeArray函数到底在做什么,请参阅:
/* 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...]
*/对于以下使用MS 7的整数数组声明,其中地址引用大小为8个字节。
Dim myArray() As Integer
ReDim myArray(9)SafeArray结构的内存转储,包括前面使用7的隐藏VT数据
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 注: VBA 7 64位显示SAFEARRAYBOUNDS[0...]的偏移量为+24 12月,+18十六进制,这是由于pvData和填充的8字节内存地址造成的。
我希望这有助于进一步解释任何SafeArray函数到底在执行什么,以及SafeArray结构项位于何处。如果有人正在手动操作SafeArray结构,请小心填充,并纠正偏移量。
我还将尝试了解有关VT_I4(3)或VT_R4(4)的查询。
在VBA中肯定有一些额外的内容,那么SafeArray.c函数通过使用SafeArrayDescriptorEx来创建一个初始化的空cbElements数组所执行的操作,cbElements没有设置,前面的VT已经设置好了。奇怪的是,VBA整数数组在没有将cbElements设置为2字节的情况下仍然工作。在创建SafeArrayDescriptor时,我现在手动设置cbElements。
当使用上面的VBA示例创建时,cbElements被适当地设置。
在SafeArray.c函数中,它们不返回SizeOf(VT_I4)或SizeOf(VT_R4),即在C中不受支持,因此我认为在VBA中必须对SafeArray.c函数进行扩展,并满足C中未涉及的数据类型。
对C有更多了解的人也许能更好地澄清或解释。
https://stackoverflow.com/questions/18784470
复制相似问题