Reputation: 40499
In VBA, I need to declare
a function in a DLL with the ptrSafe
attribute if I am using it in a 64-bit Office environment.
As far as I can see, the ptrSafe
does not technically change anything so that I am not sure what the purpose of the ptrSafe
attribute actually is.
Upvotes: 2
Views: 2978
Reputation: 2824
Realistically, as far as I am concerned, the keyword serves no function other than ensuring that old code will not compile in VBA7.
Existing Declare statements won't compile in 64-bit VBA until they've been marked as safe for 64-bit by using the PtrSafe attribute
This having the impact that Microsoft Office could provide a standard error to users which try to run 32-bit code in VBA7 and force VBA developers to re-assess their code. If code was simply ran, it might cause a crash, which in some cases could happen on Workbook_Open
or similarly "randomly".
Personally, I feel that introduction of the keyword is awful design, and contributes to the schism between VBA and VB6. The use of keyword PtrSafe
provides no guarantees in reality, other than that the user has added the keyword. It does not guarantee they have checked for handles and converted those to LongPtr
. And as a result of this bad design, we now need to use complex macros to compile code for both 64 and 32 bit office...
#if Win64 then
Private Const NULL_PTR as LongLong = 0^
#else
Private Const NULL_PTR as Long = 0&
#end if
#if VBA7 then
Private Declare PtrSafe Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = NULL_PTR) As Long
'...
#else
Private Declare Function OpenClipboard Lib "user32" (Optional ByVal hWnd As Long = NULL_PTR) As Long
'...
#end if
No, instead, Microsoft would have been better:
LongPtr
type.If this were done, the following would suffice for both 32 and 64 bit systems:
Private Declare Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = 0) As Long
And hell even if they didn't release a patch for 32-bit VBA/VB6 we could still use macros and an Enum:
#If VBA7 = 0 then
Enum LongPtr
[_]
End Enum
#End If
Private Declare Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = 0) As Long
'...
But alas, because of the introduction of this keyword we now have to define all our statements twice if we want to remain compatible:
#If VBA7 then
Private Declare PtrSafe Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = 0) As Long
'...
#Else
Enum LongPtr
[_]
End Enum
Private Declare Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = 0) As Long
'...
#End If
If I were Microsoft I'd make PtrSafe
keyword optional. Doing so would do a world of good.
Upvotes: 1
Reputation: 4424
PtrSafe
serves to tell VBA that API declarations are safe: Ptr (pointer)
Safe (safe, safe)
This attribute indicates that we target the 64-bit version.
For Example
Take the ShellExecute
API function, which opens any file in its default application without knowing it. For example, an .xlsx document will open in Excel, a .pdf will open in Acrobat Reader, unless you have installed another PDF reader (such as Sumatra PDF).
The API declaration of this function has changed to 64-bit
version. To make 32 and 64-bit
versions coexist in the same database, write this:
' --- DECLARATION API WINDOWS
#If VBA7 Then
Private Declare PtrSafe Function ShellExecute _
Lib "shell32.dll" _
Alias "ShellExecuteA" ( _
ByVal hwnd As LongPtr, ByVal lpOperation As String, _
ByVal lpFile As String, ByVal lpParameters As String, _
ByVal lpDirectory As String, ByVal nShowCmd As Long) _
As LongPtr
#Else
Private Declare Function ShellExecute _
Lib "shell32.dll" _
Alias "ShellExecuteA" ( _
ByVal hwnd As Long, ByVal lpOperation As String, _
ByVal lpFile As String, ByVal lpParameters As String, _
ByVal lpDirectory As String, ByVal nShowCmd As Long) _
As Long
#End If
Original content can be found there
Upvotes: 0