如何使用 VBA read/write Mac OS X 上的内存?
How to read/write memory on Mac OS X with VBA?
在 Windows 上声明的函数 RtlMoveMemory
提供了一种将字节块从一个地址复制到另一个地址的方法:
Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32" ( _
ByVal dest As LongPtr, _
ByVal src As LongPtr, _
ByVal size As LongPtr)
Mac OS X 上的等价物是什么?
我在 msdn.microsoft.com 上查找了 RtlMoveMemory()
,它似乎只是将一些字节从一个地址复制到另一个地址,处理重叠内存的特殊情况。
达尔文等价物是void* memmove(void *dst, const void *src, size_t len)
primitive/faster 版本是 void* memcpy(void *restrict dst, const void *restrict src, size_t n)
,它不处理重叠内存区域。
做一个man memmove
了解详情。
What is the equivalent on 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
解释:
CopyMemory 函数的 Mac 版本 return 是结果,而 Win 版本则不是。 (结果是 dest 指针,除非发生错误。请参阅 memmove 参考 here。)然而,这两个版本可以完全相同的方式使用,没有括号。
声明差异如下:
64 位 Mac/Win VBA7:
- 使用
PtrSafe
关键字
- 对所有
ByRef
参数使用Any
类型
- 使用
LongPtr
类型作为 ByVal
handle/pointer parameters/return 值
- 对其他 return values/parameter
适当使用 LongLong
类型
32 位 Win VBA7:
- 使用
PtrSafe
关键字
- 对所有
ByRef
参数使用Any
类型
- 使用
LongPtr
类型作为 ByVal
handle/pointer parameters/return 值
- 使用
Long
(not LongLong
) 适当地输入其他 return values/parameter
32 位 Mac/Win VBA6:
- 没有
PtrSafe
关键字
- 对所有
ByRef
参数使用Any
类型
- 为
ByVal
handle/pointer parameters/return 值使用 Long
类型
- 对其他 return values/parameter
适当使用 Long
类型
注意事项:
- 在 Mac Excel 2016 64 位上测试。
在 Windows Excel 2007 32 位上测试。
似乎 Excel 2007 有与双字对齐相关的问题。在这个
示例:
CopyMemory_byVar abytDest(0), abytSrc(0), 4 '-> ABCD
CopyMemory_byVar abytDest(1), abytSrc(1), 8 '-> ABCDEFGHI
CopyMemory()
跳过所有复制,直到双字对齐
达到(在本例中跳过 3 个),然后从第 4 个继续复制
byte.
注意:如果你对我的变量命名规则感到好奇,它是基于 RVBA.
*正确的方式。
在 Windows 上声明的函数 RtlMoveMemory
提供了一种将字节块从一个地址复制到另一个地址的方法:
Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32" ( _
ByVal dest As LongPtr, _
ByVal src As LongPtr, _
ByVal size As LongPtr)
Mac OS X 上的等价物是什么?
我在 msdn.microsoft.com 上查找了 RtlMoveMemory()
,它似乎只是将一些字节从一个地址复制到另一个地址,处理重叠内存的特殊情况。
达尔文等价物是void* memmove(void *dst, const void *src, size_t len)
primitive/faster 版本是 void* memcpy(void *restrict dst, const void *restrict src, size_t n)
,它不处理重叠内存区域。
做一个man memmove
了解详情。
What is the equivalent on 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
解释:
CopyMemory 函数的 Mac 版本 return 是结果,而 Win 版本则不是。 (结果是 dest 指针,除非发生错误。请参阅 memmove 参考 here。)然而,这两个版本可以完全相同的方式使用,没有括号。
声明差异如下:
64 位 Mac/Win VBA7:
- 使用
PtrSafe
关键字 - 对所有
ByRef
参数使用Any
类型 - 使用
LongPtr
类型作为ByVal
handle/pointer parameters/return 值 - 对其他 return values/parameter 适当使用
LongLong
类型- 使用
32 位 Win VBA7:
- 使用
PtrSafe
关键字 - 对所有
ByRef
参数使用Any
类型 - 使用
LongPtr
类型作为ByVal
handle/pointer parameters/return 值 - 使用
Long
(notLongLong
) 适当地输入其他 return values/parameter
- 使用
32 位 Mac/Win VBA6:
- 没有
PtrSafe
关键字 - 对所有
ByRef
参数使用Any
类型 - 为
ByVal
handle/pointer parameters/return 值使用Long
类型 - 对其他 return values/parameter 适当使用
Long
类型- 没有
注意事项:
- 在 Mac Excel 2016 64 位上测试。
在 Windows Excel 2007 32 位上测试。
似乎 Excel 2007 有与双字对齐相关的问题。在这个 示例:
CopyMemory_byVar abytDest(0), abytSrc(0), 4 '-> ABCD CopyMemory_byVar abytDest(1), abytSrc(1), 8 '-> ABCDEFGHI
CopyMemory()
跳过所有复制,直到双字对齐 达到(在本例中跳过 3 个),然后从第 4 个继续复制 byte.
注意:如果你对我的变量命名规则感到好奇,它是基于 RVBA.
*正确的方式。