如何在vba中使用api函数时准确地传递用户自定义类型的变量大小?

在vba中可以在模块级别使用Type语句声明用户自定义的类型。

在VBA中调用DLL中的API函数时,经常需要传递正确的变量类型,才能正常使用API函数。

有不少API函数的参数是结构形式,在VBA中没有结构类型的变量,但是可以通过定义用户自定义类型的变量来当做结构传递。

当进行结构变量的传递时,有很多结构变量都需要预先设置结构的字节大小。

根据如何在vba中返回变量所分配的内存大小? 一文,我们了解到可以使用Len函数返回一些变量类型所分配的内存的字节大小,对于用户自定义类型的变量,它实际所分配的内存的字节大小是怎样的呢。

我们可以通过以下的代码来测试:

Type obj
    i As Long
    str As String
    j As Integer
End Type
Sub QQ1722187970()
    Dim o1 As obj
    With o1
        .i = 1
        .str = "a"
        .j = 2
    End With
    Debug.Print VarPtr(o1), VarPtr(o1.i), VarPtr(o1.str), VarPtr(o1.j)
    Debug.Print VBA.Hex(VarPtr(o1)), VBA.Hex(VarPtr(o1.i)), VBA.Hex(VarPtr(o1.str)), VBA.Hex(VarPtr(o1.j))
End Sub

以上代码我们定义了一个用户自定义类型变量o1,它有三个元素,分别是Long, String,Integer类型。

当运行以下代码时,将在立即窗户中输出以下值:

2551336 2551336 2551340 2551344
26EE28 26EE28 26EE2C 26EE30

从结果可以看出用户自定义类型变量o1的内存地址(2551336)与第一个元素i的内存地址(2551336)是相同的。

o1的第一个元素i是long类型的,它占用的是4个字节的内存大小,故o1的第二个元素的str 内存地址(2551340)与第一个元素的内存地址(2551336 )相差4个字节。

o1的第二个元素为变长字符串变量str,由于变长字符串变量是以BSTR类型存储的, str变量实际存储的是字符串的第一个字符的内存地址,内存地址是4字节的,故str变量实际占用了4个字节,所以它的内存地址(2551340 )与第三个元素j的内存地址(2551344 )相差4个字节。

根据以上的分析结合o1元素的变量类型(4+4+2),实际o1分配的内存空间大小是10个字节,这个值刚好与len(o1)返回的值一致。

那是否可以下这样的结论:用户自定义类型变量所分配的内存大小与Len函数返回的值是一致的?

我们用以下的代码来测试:

Type obj
    i As Long
    str As String * 10
    j As Integer
End Type
Sub QQ1722187970()
    Dim o1 As obj
    With o1
        .i = 1
        .str = "abc"
        .j = 2
    End With
    Debug.Print Len(o1)
    Debug.Print VarPtr(o1), VarPtr(o1.i), VarPtr(o1.str), VarPtr(o1.j)
    Debug.Print VBA.Hex(VarPtr(o1)), VBA.Hex(VarPtr(o1.i)), VBA.Hex(VarPtr(o1.str)), VBA.Hex(VarPtr(o1.j))
End Sub

当运行以上代码后,将在立即窗户中输出以下值:

16
2551320 2551320 2551312 2551344
26EE18 26EE18 26EE10 26EE30

根据以上的结果,会容易产生歧义,好像o1的第二个元素str并不是接着o1的第一个元素i的,实际上对于定长字符串变量,VarPtr返回的值并不是实际的变量地址,有BUG。

通过内存查看软件查询后的结果如下图所示:

26EE18地址处开始存储o1变量的第一个元素i(4个字节),紧接着在26EE1C处开始存储字符串”abc”,然后存储“空格”,最后在26EE30处开始存储o1变量的第三个元素j,2个字节。

从图中可以看出,当用户自定义类型变量的元素含有定长字符串变量时,它所分配的内存大小与Len函数返回的值是不一致的,而与LenB函数返回的值是一致的,vba中一个字符用两个字节存储。

根据以上的分析,总结如下:

用户自定义类型变量所分配的内存大小有以下原则:

  1. 用户自定义类型变量的内存地址与第一个元素的内存地址一致
  2. 当用户自定义类型变量的元素类型为变长字符串变量时,所分配的内存地址是4个字节。
  3. 当用户自定义类型变量的元素类型为定长字符串变量时,所分配的内存地址是 2*字符数 字节。

根据以上的原则,可以结合各个元素所分配的内存大小,算出整个用户自定义类型变量所分配的内存大小字节数。

 

 

 

       

发表评论