在64位office中调用MultiByteToWideChar()得到错误的结果。

问题描述 投票:1回答:1

我有一个Excel VBA项目,我正在适应64位Office。在其中一部分,我调用了 MultiByteToWideChar() 使用20多个不同的代码页中的任何一个。(所以StrConv不是一个替代方案。)

多年来,我在32位Office中使用以下代码一直在工作 declare:

Declare Function MultiByteToWideChar Lib "kernel32" ( _
  ByVal codepage As Long, _
  ByVal dwFlags As Long, _
  lpMultiByteStr As Any, _
  ByVal cbMultiByte As Long, _
  ByVal lpWideCharStr As Long, _
  ByVal cchWideChar As Long _
  ) As Long
    'params: UINT, DWORD, LPCSTR, int, LPWSTR, int
    'return: int

但我对64位的适应不是这样。我得到了错误的结果(例如,一个空字符串,而预期的是非空字符串),并经常崩溃。我使用的是一个 declare 我得到的 微软提供的Win32API_PtrSafe.TXT文件。. (当然,它可能有bug。)

所以,我猜测是声明语句或我的调用方式有问题。

下面是一个最小的示例,重现的。

'Windows API declarations

Public Const MB_PRECOMPOSED = &H1       'use precomposed chars

Declare PtrSafe Function MultiByteToWideChar Lib "kernel32" ( _
  ByVal CodePage As Long, _
  ByVal dwFlags As Long, _
  ByVal lpMultiByteStr As String, _
  ByVal cchMultiByte As Long, _
  ByVal lpWideCharStr As String, _
  ByVal cchWideChar As Long _
  ) As Long
    'params: UINT, DWORD, LPCSTR, int, LPWSTR, int
    'return: int


' My function that calls MultiByteToWideChar

Private Function EncodedStringByteArrayToString(abStringData() As Byte, lngArrLen As Long, CodePage As Long) As String
    Dim lngStrLen As Long, str As String

    lngStrLen = MultiByteToWideChar(CodePage, MB_PRECOMPOSED, ByVal VarPtr(abStringData(1)), lngArrLen, 0&, 0)
    str = String(lngStrLen, " ")
    lngStrLen = MultiByteToWideChar(CodePage, MB_PRECOMPOSED, ByVal VarPtr(abStringData(1)), lngArrLen, StrPtr(str), lngStrLen)
    EncodedStringByteArrayToString = str
End Function


' Sample routine to produce repro

Private Sub TestMB2WCBug()
    Dim abStringData(1 To 9) As Byte
    Dim resultString As String

    abStringData(1) = 67
    abStringData(2) = 111
    abStringData(3) = 112
    abStringData(4) = 121
    abStringData(5) = 114
    abStringData(6) = 105
    abStringData(7) = 103
    abStringData(8) = 104
    abStringData(9) = 116

    resultString = EncodedStringByteArrayToString(abStringData(), 9, 10000)
End Sub
excel vba winapi
1个回答
2
投票

在32位的Office中,这对我来说已经工作了很多年。

它不可能与 Declare 你所展示的。

MultiByteToWideChar 期待一个 LPWSTR 作为输出缓冲区。当将字符串传递到 Declared函数,所以该函数不可能接收一个指向宽字符串缓冲区的指针,当 lpWideCharStr 被宣布为 As String. 最多只能接收一个足够大的缓冲区,这样就不会发生缓冲区溢出的情况,然后VB会在从函数返回时执行转换回Unicode,所以你最终会得到一个双unicode字符串。

lpMultiByteStr 也不是一个字符串,它是一个字节数组,在 某种编码.


里面的代码 EncodedStringByteArrayToString 似乎知道所有这些,因为它正确地传递了一个字节数组给 lpMultiByteStr 和一个 StrPtr 对于 lpWideCharStr. 在目前宣布的情况下,这种情况不可能发生。MultiByteToWideChar.

中的代码所假设的声明。EncodedStringByteArrayToString 是。

Declare PtrSafe Function MultiByteToWideChar Lib "kernel32" ( _
  ByVal CodePage As Long, _
  ByVal dwFlags As Long, _
  ByVal lpMultiByteStr As LongPtr, _
  ByVal cchMultiByte As Long, _
  ByVal lpWideCharStr As LongPtr, _
  ByVal cchWideChar As Long _
  ) As Long

很明显,你以前有,所以把它放回去。

© www.soinside.com 2019 - 2024. All rights reserved.