简体   繁体   中英

VBA 32-bit and 64-bit type mismatch

Updated Please see the last part of the question for updates

Full source-code here:

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

I have a piece of code that does not work, probably due to 32-bit and 64-bit difference:

Part of the code: (I added the PtrSafe, which I shouldn't for the first one)

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

I googled for sometime, found out that msvbvm60.dll seems to be the old 32-bit VBA and has been replaced with VBA7.dll. Tried to re-register the file as it is in SysWOW64 folder, after which VBE still reports that cannot find this file. So I commented the first line, and changed the last line to:

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

As I believe ArrPtr is simply VarPtr with an alias.

Now I get a type mismatch error. What I understand is that the code points the header of SafeArray1 to the address of Header1(0). I assume that it means that SafeArray1[0]~SafeArray[9] should contain the info in Header1(0)~Header1(4) as Header1() is Long and SafeArray() is Integer? But shouldn't VarPtr returns Long in 32-bit Office and how come it is possible to use it on an Integer array?

But the point is how to make it run on 64-bit Office. Since VarPtr now returns LongPtr instead of Long, I'm not sure how to modify the code.

Updates I found another piece of code that gives me pointer to an array:

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

Then I write a test module:

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

But VBE crashes on the RtlMoveMemory line.

The following example should show how to handle Declare statement for 32 and 64 bit versions:

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

on the crash issue, I noticed this line:

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

The last argument should be "long" as declared, so try to put "4" in a long variable and pass it to the function. This is my workaround for my own similar case, and hope that helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM