From: Ralph on 12 Oct 2009 08:31 "Dee Earley" <dee.earley(a)icode.co.uk> wrote in message news:uUP1jnySKHA.1236(a)TK2MSFTNGP05.phx.gbl... > On 11/10/2009 02:23, Ralph wrote: > > Also notice that StrPtr() and ValPtr() do not report the same item when used > > on a VB String variable. > > They won't. > > The variable has a location which you can get with VarPtr (I assume you > meant VarPtr, not ValPtr) which, for numbers is the data itself. > For a string, this will be another pointer which refers to the start of > the string data (which you can get via StrPtr). > > Essentially, if you copy 4 bytes of data from varptr(stringvar), you > should end up with the same value as strptr(stringvar). > Unless the string is 'empty'. <g> Dim A As String Debug.Print VarPtr(A) ' will return an address Debug.Print StrPtr(A) ' will return 0 In which case adding 4 bytes to the VarPtr value will give you the address of where the buffer is likely to be once it is filled with something. Seems a bit a disheartening in VB but makes perfect sense when used to communicate to an outside API (read C) - "0" is a null. Which is just another nuance of using these undocumented, 'semi-supported', calls. [And we haven't even got to ObjPtr() which can have even more unexpected results. <g>] I apologized for my incomplete post, and I should also apologize for not having stuck to my original point - these calls outside of a narrow context of dealing with APIs are best avoided by the VB programmer. -ralph
From: Schmidt on 12 Oct 2009 09:08 "Ralph" <nt_consulting64(a)yahoo.com> schrieb im Newsbeitrag news:uW7xofzSKHA.352(a)TK2MSFTNGP02.phx.gbl... > > "Dee Earley" <dee.earley(a)icode.co.uk> wrote in message > news:uUP1jnySKHA.1236(a)TK2MSFTNGP05.phx.gbl... > > On 11/10/2009 02:23, Ralph wrote: > > > Also notice that StrPtr() and ValPtr() do not report the same item when > used > > > on a VB String variable. > > > > They won't. > > > > The variable has a location which you can get with VarPtr (I assume you > > meant VarPtr, not ValPtr) which, for numbers is the data itself. > > For a string, this will be another pointer which refers to the start of > > the string data (which you can get via StrPtr). > > > > Essentially, if you copy 4 bytes of data from varptr(stringvar), you > > should end up with the same value as strptr(stringvar). > > > > Unless the string is 'empty'. <g> > Dim A As String > Debug.Print VarPtr(A) ' will return an address > Debug.Print StrPtr(A) ' will return 0 No, what Dee meant was: Dim A As String, StrPtr_A as Long CopyMemory StrPtr_A, Byval VarPtr(A), 4 Debug.Print StrPtr_A, StrPtr(A) This should always be "in sync" - no matter if A contains a valid string, or "an empty string" (which is identical with a Zero-Value, a NullPointer - or just vbNullString). Olaf
From: Ralph on 12 Oct 2009 12:44 "Schmidt" <sss(a)online.de> wrote in message news:eBVQy4zSKHA.1268(a)TK2MSFTNGP04.phx.gbl... > > "Ralph" <nt_consulting64(a)yahoo.com> schrieb im Newsbeitrag > news:uW7xofzSKHA.352(a)TK2MSFTNGP02.phx.gbl... > > > > "Dee Earley" <dee.earley(a)icode.co.uk> wrote in message > > news:uUP1jnySKHA.1236(a)TK2MSFTNGP05.phx.gbl... > > > On 11/10/2009 02:23, Ralph wrote: > > > > Also notice that StrPtr() and ValPtr() do not report the same item > when > > used > > > > on a VB String variable. > > > > > > They won't. > > > > > > The variable has a location which you can get with VarPtr (I assume you > > > meant VarPtr, not ValPtr) which, for numbers is the data itself. > > > For a string, this will be another pointer which refers to the start of > > > the string data (which you can get via StrPtr). > > > > > > Essentially, if you copy 4 bytes of data from varptr(stringvar), you > > > should end up with the same value as strptr(stringvar). > > > > > > > Unless the string is 'empty'. <g> > > Dim A As String > > Debug.Print VarPtr(A) ' will return an address > > Debug.Print StrPtr(A) ' will return 0 > > No, what Dee meant was: > Dim A As String, StrPtr_A as Long > CopyMemory StrPtr_A, Byval VarPtr(A), 4 > > Debug.Print StrPtr_A, StrPtr(A) > > This should always be "in sync" - no matter if A contains > a valid string, or "an empty string" (which is identical with > a Zero-Value, a NullPointer - or just vbNullString). > True, but note "CopyMemory" is an outside API call. -ralph
From: Eduardo on 12 Oct 2009 23:36 Ok, here are the conversion functions: Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (Destination As Any, Source As Any, ByVal Length As Long) Private Function GetStrFromStrPtr(ByVal nStrPtr As Long) As String Dim iB() As Byte Dim iStr As String Dim iLength As Long If nStrPtr = 0 Then Exit Function CopyMemory iLength, ByVal nStrPtr - 4&, 4& ReDim iB(iLength) CopyMemory iB(0), ByVal nStrPtr, iLength iStr = CStr(iB) GetStrFromStrPtr = iStr End Function Private Function GetStrFromVarPtr(ByVal nVarPtr As Long) As String Dim iB() As Byte Dim iStr As String Dim iStrPtr As Long Dim iLength As Long CopyMemory iStrPtr, ByVal nVarPtr, 4& If iStrPtr = 0 Then Exit Function CopyMemory iLength, ByVal iStrPtr - 4&, 4& ReDim iB(iLength) CopyMemory iB(0), ByVal iStrPtr, iLength iStr = CStr(iB) GetStrFromVarPtr = iStr End Function
From: Schmidt on 13 Oct 2009 08:08
"Eduardo" <mm(a)mm.com> schrieb im Newsbeitrag news:hb0sjg$t9$1(a)aioe.org... > Ok, here are the conversion functions: >... Nice, since they give some more insight (also with regards to the BSTR-Definitions with their "left-shifted ByteLen-Descriptor"). You can avoid one allocation (the ByteArray-Redim) and one Copy-Over (iStr = CStr(iB)), if you work more directly on the returned "StringBuffer". But that would be more out of "speed-reasons"... - it is then less "speaking-code". Private Function GetStrFromStrPtr(ByVal nStrPtr As Long) As String Dim iLength As Long If nStrPtr = 0 Then Exit Function CopyMemory iLength, ByVal nStrPtr - 4&, 4& 'now with only one allocation and one Copy-Over GetStrFromStrPtr = Space$(iLength \ 2) CopyMemory ByVal StrPtr(GetStrFromStrPtr), ByVal nStrPtr, iLength End Function Private Function GetStrFromVarPtr(ByVal nVarPtr As Long) As String Dim iStrPtr As Long If nVarPtr = 0 Then Exit Function CopyMemory iStrPtr, ByVal nVarPtr, 4& 'only the dereferencing... GetStrFromVarPtr = GetStrFromStrPtr(iStrPtr) '...and the delegation End Function Olaf |