In VBA, I declared a Windows API function that requires a pointer to a struct
argument. For representing this struct
I created a Public Type
and declared the function parameter as ByRef
.
Now, this struct
pointer may be null
, so I tried to assign Nothing
to a variable of my UDT, but that doesn't work.
How can I make this work?
Here are the basic excerpts from my code:
Private Declare PtrSafe Function GetNumberFormatEx& Lib "Kernel32" ( _
ByVal lpLocaleName As LongPtr, _
ByVal dwFlags&, _
ByVal lpValue As LongPtr, _
ByRef lpFormat As NumberFormat, _
ByVal lpNumberStr As LongPtr, _
ByVal cchNumber& _
)
Public Type NumberFormat
NumDigits As Integer
LeadingZero As Integer
Grouping As Integer
lpDecimalSep As LongPtr
lpThousandSep As LongPtr
NegativeOrder As Integer
End Type
Public Function FormatNumberLocale$(srcValue As Double, lcid$, Optional flags& = 0, Optional customFormat$ = vbNullString)
Dim buffer$
Dim charCount&
Dim numFormat As NumberFormat
buffer = String(100, 0)
'numFormat = Nothing ' THIS DOESN'T WORK !!!
charCount = GetNumberFormatEx(StrPtr(lcid), flags, StrPtr(Str$(srcValue)), numFormat, StrPtr(buffer), 100)
If charCount > 0 Then FormatNumberLocale = Left$(buffer, charCount)
End Function
I changed the declaration to:
Private Declare PtrSafe Function GetNumberFormatEx& Lib "Kernel32" ( _
ByVal lpLocaleName As LongPtr, _
ByVal dwFlags&, _
ByVal lpValue As LongPtr, _
ByVal lpFormat As LongPtr, _
ByVal lpNumberStr As LongPtr, _
ByVal cchNumber& _
)
and called the function like this:
...
Dim value$
buffer = String(100, 0)
value = Str$(srcValue)
charCount = GetNumberFormatEx(StrPtr(lcid), flags, StrPtr(value), CLngPtr(0&), StrPtr(buffer), 100)
But even when calling it with basic parameters, like ?FormatNumberLocale(123,"en")
, charCount
is always 0
, and Err.LastDllError
always returns 87 (0x57): ERROR_INVALID_PARAMETER
.
Any ideas?
The idiomatic VBA way of passing NULL
for a struct pointer is declaring the argument as ByRef As Any
:
Private Declare PtrSafe Function GetNumberFormatEx Lib "Kernel32" ( _
ByVal lpLocaleName As LongPtr, _
ByVal dwFlags As Long, _
ByVal lpValue As LongPtr, _
ByRef lpFormat As Any, _
ByVal lpNumberStr As LongPtr, _
ByVal cchNumber As Long _
) As Long
and then passing either a struct variable (numFormat
in your example) or ByVal 0&
for null.