VBA 32-битное и 64-битное несоответствие типов - PullRequest
0 голосов
/ 20 мая 2018

Обновлено См. Последнюю часть вопроса об обновлениях

Полный исходный код здесь:

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 () - Long, а SafeArray () - Integer?Но разве VarPtr не должен возвращать Long в 32-битном Office и почему его можно использовать в массиве 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)

End Sub

Но VBE дает сбой в строке RtlMoveMemory.

Ответы [ 2 ]

0 голосов
/ 09 марта 2019

в случае сбоя я заметил следующую строку:

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

Последний аргумент должен быть "длинным", как объявлено, поэтому попробуйте поставить "4" в длинной переменной и передать ее функции,Это мой обходной путь для моего собственного подобного случая, и надеюсь, что это поможет.

0 голосов
/ 20 мая 2018

Следующий пример должен показать, как обрабатывать оператор Declare для 32- и 64-разрядных версий:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...