Ответ 1
Что такое эквивалент в Mac OS X?
Короткий ответ:
Private Declare PtrSafe Function CopyMemory Lib "libc.dylib" Alias "memmove" _
( _
ByVal dest As LongPtr _
, ByVal src As LongPtr _
, ByVal size As LongLong _
) _
As LongPtr
Длинный ответ: Зависит;)
Ниже приведен полный пример, в котором используется условная компиляция *, позволяющая ему работать на любом компьютере Mac/Windows/32-bit/64-bit. Он также демонстрирует два разных способа объявления и вызова функции (по указателю и переменной).
#If Mac Then
#If Win64 Then
Private Declare PtrSafe Function CopyMemory_byPtr Lib "libc.dylib" Alias "memmove" (ByVal dest As LongPtr, ByVal src As LongPtr, ByVal size As Long) As LongPtr
Private Declare PtrSafe Function CopyMemory_byVar Lib "libc.dylib" Alias "memmove" (ByRef dest As Any, ByRef src As Any, ByVal size As Long) As LongPtr
#Else
Private Declare Function CopyMemory_byPtr Lib "libc.dylib" Alias "memmove" (ByVal dest As Long, ByVal src As Long, ByVal size As Long) As Long
Private Declare Function CopyMemory_byVar Lib "libc.dylib" Alias "memmove" (ByRef dest As Any, ByRef src As Any, ByVal size As Long) As Long
#End If
#ElseIf VBA7 Then
#If Win64 Then
Private Declare PtrSafe Sub CopyMemory_byPtr Lib "kernel32" Alias "RtlMoveMemory" (ByVal dest As LongPtr, ByVal src As LongPtr, ByVal size As LongLong)
Private Declare PtrSafe Sub CopyMemory_byVar Lib "kernel32" Alias "RtlMoveMemory" (ByRef dest As Any, ByRef src As Any, ByVal size As LongLong)
#Else
Private Declare PtrSafe Sub CopyMemory_byPtr Lib "kernel32" Alias "RtlMoveMemory" (ByVal dest As LongPtr, ByVal src As LongPtr, ByVal size As Long)
Private Declare PtrSafe Sub CopyMemory_byVar Lib "kernel32" Alias "RtlMoveMemory" (ByRef dest As Any, ByRef src As Any, ByVal size As Long)
#End If
#Else
Private Declare Sub CopyMemory_byPtr Lib "kernel32" Alias "RtlMoveMemory" (ByVal dest As Long, ByVal src As Long, ByVal size As Long)
Private Declare Sub CopyMemory_byVar Lib "kernel32" Alias "RtlMoveMemory" (ByRef dest As Any, ByRef src As Any, ByVal size As Long)
#End If
Public Sub CopyMemoryTest()
Dim abytDest(0 To 11) As Byte
Dim abytSrc(0 To 11) As Byte
Dim ¡ As Long
For ¡ = LBound(abytSrc) To UBound(abytSrc)
abytSrc(¡) = AscB("A") + ¡
Next ¡
MsgBox "Dest before copy = #" & ToString(abytDest) & "#"
CopyMemory_byVar abytDest(0), abytSrc(0), 4
MsgBox "Dest during copy = #" & ToString(abytDest) & "#"
CopyMemory_byPtr VarPtr(abytDest(0)) + 4, VarPtr(abytSrc(0)) + 4, 4
MsgBox "Dest during copy = #" & ToString(abytDest) & "#"
CopyMemory_byPtr VarPtr(abytDest(8)), VarPtr(abytSrc(8)), 4
MsgBox "Dest after copy = #" & ToString(abytDest) & "#"
End Sub
Public Function ToString(ByRef pabytBuffer() As Byte) As String
Dim ¡ As Long
For ¡ = LBound(pabytBuffer) To UBound(pabytBuffer)
ToString = ToString & Chr$(pabytBuffer(¡))
Next ¡
End Function
Объяснение:
Mac-версия функции CopyMemory возвращает результат, в то время как версия Win не имеет значения. (Результат - указатель dest, если не произошла ошибка. См. Ссылку memmove здесь.) Обе версии, однако, могут быть использованы точно таким же образом, без скобок.
Различия в объявлении таковы:
-
64-разрядный Mac/Win VBA7:
- Используйте ключевое слово
PtrSafe
- Используйте тип
Any
для всех параметровByRef
- Используйте тип
LongPtr
дляByVal
параметров/указателей дескриптора/указателя - Используйте тип
LongLong
для других возвращаемых значений/параметра
- Используйте ключевое слово
-
32-разрядная версия Win VBA7:
- Используйте ключевое слово
PtrSafe
- Используйте тип
Any
для всех параметровByRef
- Используйте тип
LongPtr
дляByVal
параметров/указателей дескриптора/указателя - Используйте тип
Long
( неLongLong
) для других возвращаемых значений/параметра
- Используйте ключевое слово
-
32-разрядный Mac/Win VBA6:
- Нет
PtrSafe
ключевое слово - Используйте тип
Any
для всех параметровByRef
- Используйте тип
Long
дляByVal
параметров/указателей дескриптора/указателя - Используйте тип
Long
для других возвращаемых значений/параметра
- Нет
Предостережения:
- Протестировано в Mac Excel 2016 64-бит.
-
Протестировано в 32-разрядной версии Windows Excel 2007.
-
Похоже, Excel 2007 имеет проблемы, связанные с двойным выравниванием слов. В этом Пример:
CopyMemory_byVar abytDest(0), abytSrc(0), 4 '-> ABCD CopyMemory_byVar abytDest(1), abytSrc(1), 8 '-> ABCDEFGHI
CopyMemory()
пропускает все копии, пока выравнивание двойного слова не будет (в этом случае 3 прыжка), затем продолжается копирование с 4-го байт.
-
Примечание. Если вам интересно о моем соглашении об именах переменных, оно основано на RVBA.
* правильный способ.