API/COM/系统相关
API中VB字符串作参数传递的本质论
2005-02-06 12:24:38
a    b    d    e     f    chr(0)

字符个数描述符由VB来使用,BSTR指针直接指向第一个字符。

因为大多数API函数是用CC++来编写的,在C/C++(API)中使用叫做LPSTR类型的指针。

  

VB中字符串变量在内存中的存储状态图:

从上图可知:字符串变量X的地址与实际字符串的地址不同,也就是说字符X变量中实际上是存放的字符串的首地址这一点是和C/C++相同的。其实图中descriptor这个描述符就是C中的字符串指针地址。当BSTR指针在忽略字符个数描述前缀的情况下是与LPSTR指针是相同的,在调用API时可以将BSTR以传值方式传递给API采用传值方式传递时实际上传递的是实参中所存放的字符串的首地址,当调用过API后,可以通过它来返回数据,API修改传送给它的那个地址所指向的字符串数据,而没有修改实参字符变量内的内容,所以可以返回数据。即并没有与高级语言中所规定的传值方式调用方式的形参改变不影响实参的规则相冲突。

 

实例:

模块中的代码:

Option Explicit

 

Public Declare Function GetComputerName Lib "kernel32" Alias "GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long

窗体中的代码:

 

Option Explicit

 

Private Sub Command1_Click()

   Dim str As String

   Dim str1 as String

   Dim length As Long

   length = 255

 

   str = String(length, 0)

   str1=str

   Debug.Print VarPtr(str),”     “,varptr(str1)

   Debug.Print StrPtr(str),”      ”,strptr(str1)

   Debug.Print

 

   GetComputerName str, length

 

   Debug.Print str

   Debug.Print VarPtr(str)

   Debug.Print StrPtr(str), Len(str), length

End Sub

 

在立即窗口中可以看到运行结果。字符串变量的地址与字符串的地址不同。

还可以看到字符串变量strstr1的地址不同,而且字符串地址也不同,这说明在进行赋值操作,并不是将字符的首地址赋给str1而是在内存中另开一空间用来存放字符串。而在C语言内则可以使多个字符型指针变量指向同一个字符串的首地址。

当将API中的ByVal lpBuffer As String传值方式改为:ByRef lpBuffer As String传址方式时,运行程序中出错,VB编程环境将崩溃。

出错图:

因为传址时将变量本身的地址传给了API,并没有将字符串的首地址传给API,所以API在修改数据时造成访问错误。

总结

不能用传址方式来调用API,如果用传址方式的话那么传递的是指向指针的指针,API将不能返回数据,并且造成访问数据出错,所以需要用ByVal传递字符串指针。

摘自:CSDN技术中心