Visual Basic如何传递字符串到动态链接库
现在让我们来面对这个奇怪的问题:Visual Basic如何向外部的动态链接库传递BSTR类型的字符串。
我们已经知道,Visual Basic内部使用Unicode编码,也就是说,BSTR字符串使用Unicode格式。Windows NT了使用Unicode编码,但是,Windows 9x却不支持Unicode(除非某些特例)。让我们来看一下一个BSTR变量传递到一个外部的动态链接库(Win32 API或其它)所经过的过程。
为了兼容Windows 95,Visual Basic总是(甚至在Windows NT下)创建一个ANSI BSTR字符串,将BSTR字符串的Unicode格式的字符数组转换为ANSI格式,将转换完成的字符保存在这个ANSI BSTR字符串中。Visual Basic接下来就把这个ANSI BSTR字符串传递给一个外部的函数。它甚至在需要传送Unicode字符串的Windows NT中也这么做。
传送BSTR字符串之前的准备
在传递一个BSTR字符串到一个外部的动态链接库之前,Visual Basic在其它的内存地址中创建一个新的ANSI BSTR字符串。然后再把ANSI BSTR字符串传递给动态链接库。这种复制并转移的过程如图6-6所示。
Figure 6-6. Translating a BSTR to an ABSTR
当我们第一次介绍函数CopyMemory时,我们使用它来演示Unicode到ANSI的转化过程。现在让我们用另一种方式来重新演示这个过程。(译者注:接下来的程序调用了《Win32 API Programming with Visual Basic》所附的光盘中的动态链接库rpiAPI.dll的一个函数rpiBSTRtoByteArray,由于本人没有该光盘,所以大家无法演示,敬请原谅。在此,我们虽然不能运行该函数,但仅仅拿它来了解作者的程序思想,却未为不可。)rpiAPI.dll类库中有一个函数rpiBSTRtoByteArray,它的作用是返回一个传递到这个函数的字符串的地址值VarPtr和指向值StrPtr。该函数的定义如下:
Public Declare Function rpiBSTRtoByteArray Lib "???\rpiAPI.dll" (ByRef pBSTR As String,ByRef bArray As Byte,pVarPtr As Long,pStrPtr As Long) As Long
第一个参数pBSTR为一个BSTR类型的字符串,并按引用接收。因此,传送的是BSTR的地址,而不是字符串数组的首地址。(也就是说,我们传送了一个字符串的二级指针)
第二个参数是一个缓冲区,用来存放Visual Basic传递过来的ANSI BSTR字符串的首字符内存地址(注意是按引用传递,所以传递的应该是地址。)。
最后的两个参数也是缓冲区。函数在pVarPtr变量存放的是BSTR字符串指针的地址,pStrPtr存放的是BSTR字符串的首地址。
函数返回的是字符串的字符数。最后,函数会将传递给它的字符串的首字母改为字符“x”,这样,通过查看字符串的首字母我们便可以知道动态链接库接收的是哪一个字符串。
以下是演示代码:
Sub BSTRTest()
Dim i As Integer
Dim sString As String
Dim bBuf(1 To 10) As Byte
Dim pVarPtr As Long
Dim pStrPtr As Long
Dim bTarget As Byte
Dim lTarget As Long
sString = "help"
Debug.Print "VarPtr:" & VarPtr(sString) '''' 输出BSTR的地址和指向的字符串的地址
Debug.Print "StrPtr:" & StrPtr(sString)
Debug.Print "Function called. Return value:" & rpiBSTRToByteArray(sString, bBuf(1), pVarPtr, pStrPtr)
Debug.Print "Address of temp ABSTR as DLL sees it: " & pVarPtr ‘ 输出实际传递到外部动态链接库的ANSI BSTR的地址和字符串地址
Debug.Print "Contents of temp ABSTR as DLL sees it: " & pStrPtr
Debug.Print "Temp character array: " ‘ 输出临时建立的传送到外部动态链接库的ANSI BSTR字符串
For i = 1 To 10
Debug.Print bBuf(i)
Next
Debug.Print
VBGetTarget lTarget, pVarPtr, 4 ‘ 函数返回后检查ANSI BSTR字符串原先的地址并将其内容输出
Debug.Print "Contents of temp ABSTR after DLL returns: " & lTarget
Debug.Print "BSTR is now: " & sString‘ 函数返回后输出原BSTR字符串
End Sub
输出结果为:
VarPtr:1242736
StrPtr:2307556
Function called. Return value:4
Address of temp ABSTR as DLL sees it: 1242688
Contents of temp ABSTR as DLL sees it: 1850860
Temp character array: 104 101 108 112 0 0 0 0 0 0
Contents of temp ABSTR after DLL returns: 0
BSTR is now: Xelp
这几段代码首先输出的是Visual Basic中的BSTR字符串指针的地址和字符串首字符的地址。接下来调用动态链接库的函数。
在动态链接库返回后,我们试图输出ANSI BSTR字符 [1] [2] [3] [4] [5] 下一页 [VB.NET程序]有关API字符串--API programmer请看之一
|