VBA 32位和64位类型不匹配

问题描述 投票:3回答:2

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

这里有完整的源代码:

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

我google了一段时间,发现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()是Long而SafeArray()是Integer?但是,VarPtr不应该在32位Office中返回Long,为什么在Integer数组中使用它呢?

但关键是如何让它在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)

结束子

但是VBE在RtlMoveMemory行上崩溃了。

vba 32bit-64bit
2个回答
1
投票

以下示例应显示如何处理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

1
投票

在崩溃问题上,我注意到这一行:

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

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

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