VBA 32 位和 64 位类型不匹配



已更新请参阅问题的最后一部分以获取更新

完整的源代码在这里:

https://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=30761&lngWId=1

我有一段代码不起作用,可能是由于 32 位和 64 位的差异:

部分代码:(我添加了 PtrSafe,我不应该在第一个(

Private Declare PtrSafe Function ArrPtr& Lib "msvbvm60.dll" Alias "VarPtr" (ptr() As Any)
Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32" (dst As Any, src As Any, ByVal nBytes&)
Private Header1(5) As Long
Private Header2(5) As Long
Private SafeArray1() As Integer
Private SafeArray2() As Integer
Private LUT(8482) As Long
Private Sub Class_Initialize()
Dim i As Long
' Set up our template for looking at strings
Header1(0) = 1              ' Number of dimensions
Header1(1) = 2              ' Bytes per element (integer = 2)
Header1(4) = &H7FFFFFFF     ' Array size, 2.1+ billion should cover us
' Force SafeArray1 to use Header1 as its own header
RtlMoveMemory ByVal ArrPtr(SafeArray1), VarPtr(Header1(0)), 4

我用谷歌搜索了一段时间,发现msvbvm60.dll似乎是旧的32位VBA,已被VBA7.dll取代。已尝试重新注册SysWOW64文件夹中的文件,之后VBE仍报告找不到此文件。所以我评论了第一行,并将最后一行改为:

RtlMoveMemory ByVal VarPtr(SafeArray1), VarPtr(Header1(0)), 4

我相信ArrPtr只是带有别名的VarPtr。

现在我收到类型不匹配错误。我的理解是,代码将 SafeArray1 的标头指向 Header1(0( 的地址。我假设这意味着 SafeArray1[0]~SafeArray[9] 应该包含 Header1(0(~Header1(4( 中的信息,因为 Header1(( 是长而 SafeArray(( 是整数?但是 VarPtr 不应该在 32 位 Office 中返回 Long,为什么可以在整数数组上使用它?

但关键是如何让它在64位Office上运行。由于 VarPtr 现在返回 LongPtr 而不是 Long,我不确定如何修改代码。

更新我找到了另一段代码,它给了我指向数组的指针:

Private Declare PtrSafe Function VarPtrArray Lib "VBE7" Alias _
"VarPtr" (ByRef Var() As Any) As LongPtr

然后我编写一个测试模块:

Private Declare PtrSafe Function VarPtrArray Lib "VBE7" Alias _
"VarPtr" (ByRef Var() As Any) As LongPtr
Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32" (dst As Any, src As Any, ByVal nBytes&)
Private Header1(5) As Long
Private SafeArray1() As Integer
Sub test()
Header1(0) = 1              ' Number of dimensions
Header1(1) = 2              ' Bytes per element (integer = 2)
Header1(4) = &H7FFFFFFF     ' Array size, 2.1+ billion should cover us
RtlMoveMemory ByVal VarPtrArray(SafeArray1), VarPtr(Header1(0)), 4
Debug.Print SafeArray1(0)
End Sub

但是VBE在RtlMoveMemory线上崩溃了。

下面的示例应显示如何处理 32 位和 64 位版本的Declare语句:

Option Explicit
#If VBA7 Then '64 bit
Private Declare PtrSafe Function DrawMenuBar Lib "User32" (ByVal hwnd As LongPtr) As LongPtr
#Else '32 bit
Private Declare Function DrawMenuBar Lib "User32" (ByVal hwnd As Long) As Long
#End If

关于崩溃问题,我注意到了这一行:

RtlMoveMemory ByVal VarPtrArray(SafeArray1), VarPtr(Header1(0)), 4

最后一个参数应该是声明的"long",所以尝试将"4"放在一个长变量中并将其传递给函数。 这是我对自己类似情况的解决方法,希望对您有所帮助。

最新更新