Newsgroup: it.comp.lang.visual-basic
Titolo: [!] Ottenere la stringa dato il suo puntatore

Sono arrivato a questa soluzione dopo aver rimaneggiato un po' i
suggerimenti di H.P.L.
Dato il puntatore al descrittore di una stringa ottenuto con VarPtr() (e non
con StrPtr() che restituisce direttamente il puntatore alla stringa), si può
ottenere la stringa di partenza in questo modo:
Declare Function SysStringByteLen Lib "Oleaut32" (ByVal bstr As Long) As
Long
Function StrFromPtr(ByVal lpAddress As Long) As String
    Dim ptr As Long
    ' ottengo il puntatore alla stringa, come con StrPtr()
    Call CopyMemory(ptr, ByVal lpAddress, 4&)
    ' ottengo la lunghezza della stringa
    StrFromPtr = String$(SysStringByteLen(ptr), 0)
    ' ottengo la stringa in formato unicode
    Call CopyMemory(ByVal StrFromPtr, ByVal ptr, Len(StrFromPtr))
    ' converto la stringa da unicode
    StrFromPtr = StrConv(StrFromPtr, vbFromUnicode)
End Function
Private Sub Command1_Click()
    ' provare per credere
    Dim s As String
    Dim s2 As String
    Dim ptr As Long
    s = "ciao"
    ptr = VarPtr(s)
    s2 = StrFromPtr(ptr)
End Sub


susa quale è la differenza tra il puntatore alla stringa e il puntatore al
descrittore della stringa?
cosa è il descrittore? e quanto è grande?
grazie
MarioH

 cosa č il descrittore? e quanto č grande?
VarPtr() = [descrittore] --> [indirizzo primo char della stringa]
StrPtr() = [indirizzo primo char della stringa]
il descrittore di una stringa č un puntatore 32 bit che contiene l'indirizzo
del primo carattere della stringa.
Insomma, con VarPtr() c'č un passaggio in piů da fare.
Ciao

E' un puntatore al puntatore insomma?
--
__________________
www.sasim.cjb.net


cosa è il descrittore? e quanto è grande?
le stringhe VB 5 e 6 sono delle BSTR (mi pare) di OLE, in pratica una 
roba del genere:
typedef struct _tagBSTR{
 DWORD  length
 WCHAR *buffer
} BSTR; *PBSTR;
tradotto in VB:
Type BSTR
 Length As Long
 Buffer As Long
End Type
VarPtr() su stringa restituisce il puntatore ad una struttura BSTR, 
mentre StrPtr() restituisce il valore di Buffer. Il valore di Length lo 
si legge con Len() (o LenB? non ricordo se il parametro è in byte o 
caratteri)

 } BSTR; *PBSTR;
stavo per scrivere anch'io questa cosa ma mi hanno detto che a causa
di qualche idiozia di VB non č possibile leggere la posizione VarPtr-4
o StrPtr-4 ma non ho provato.
stasera ci provo ^_^
--
Fibia "Sakamoto" FBI
E-mail: 
fibi...@hotmail.com
ICQ UIN 63586057
Sito Personale: 
http://www.geocities.com/fibiafbi
VB Simple: 
http://vbsimple.virtualave.net
Membro #25 delle Mitiche Brigate Takahashi sezione Sud

 E' un puntatore al puntatore insomma?
Il primo elemento che vedi e' sicuramente il puntatore alla stringa
Si dice che VB conservi la dimensione della stringa stessa in una zona
vicina alla stringa o al suo descrittore, ovvero o
Type VBString
    lStringSize As Long
    sString() As Integer ' Le BSTR sono a 16 bit
End Type
Type VBStringDescriptor
    lStringPointer As Long
End Type
E nel descrittore hai l'indirizzo a sString(), oppure
Type VBStringDescriptor
    lStringPointer As Long
    lStringSize As Long
End Type
Type VBString
    sString() As Integer ' Le BSTR sono a 16 bit
End Type
La voce comune dice che la dimensione della stringa e' nei 4 byte
immediatamente precedenti la stringa...
#include <disclaimer.h>
per ogni eventualita' :P
Ciaotutti,
*

 VarPtr() su stringa restituisce il puntatore ad una struttura BSTR,
No, e' qui il problema: VarPtr restituisce il WCHAR** alla BSTR, DIETRO la
quale (4 locazioni prima) si trova la sua dimensione...
Ecco la spiegazione:
There are several important things to note about the BSTR data type.
The BSTR is the actual pointer variable. It has size 32 bits, like all
pointers, and points to a Unicode character array. Thus, a Unicode character
array and a BSTR are not the same thing. It is correct to refer to a BSTR as
a string (or VB string) but, unfortunately, the Unicode character array is
also often called a string! Hence, we will not refer to a BSTR simply as a
string--we will refer to it by its unequivocal name--BSTR.
[Ecco la parte importante]
The Unicode character array that is pointed to by a BSTR must be preceded by
a 4-byte length field and terminated by a single null 2-byte character (ANSI
= 0).
 [E anche questa non e' poco significativa...]
There may be additional null characters anywhere within the Unicode
character array, so we cannot rely on a null character to signal the end of
the character array. This is why the length field is vital.
[Questo e' un remark non da poco]
Again, the pointer points to the beginning of the character array, not to
the 4-byte length field that precedes the array. As we will see, this is
critical to interpreting a BSTR as a VC++-style string.
The length field contains the number of bytes (not the number of characters)
in the character array, excluding the terminating null bytes. Since the
array is Unicode, the character count is one-half the byte count.
We should emphasize that an embedded null Unicode character is a 16-bit 0,
not an 8-bit 0. Watch out for this when testing for null characters in
Unicode arrays.
[...]
Il tutto da MSDN, per la precisione da:
Chapter 6: Strings
Steven Roman
O'Reilly & Associates, Inc.
www.romanpress.com
Reproduced from Win32 API Programming with Visual Basic, by Steven Roman, by
permission of O'Reilly & Associates, Inc. ISBN 1-56592-631-5. Copyright
1999, O'Reilly & Associates. All rights reserved. For further information,
please contact 
nu...@oreilly.com
, or call 
1-800-998-9938
, or visit their Web
site at 
http://www.oreilly.com
.
Purchase this title online from FatBrain.com.
Ciaotutti,
Asterix


Se leggi VarPtr - 4 ad occhio ti si inchioda la macchina.
StrPtr - 4 invece dovrebbe essere accessibile...
ciaotutti,
*


provato con Win2000 Pro
Dim Stringa As String
Dim dati As Long
Stringa = "hello ICLVB"
MsgBox "test 1: " & Len(Stringa)
    ovviamente funziona
RtlMoveMemory dati, VarPtr(Stringa) - 4, 4
MsgBox "test 2: " & dati
    VarPtr(Stringa) restituisce un indirizzo valido (<> 0)
    ma la copymemory crasha
RtlMoveMemory dati, StrPtr(Stringa) - 4, 4
MsgBox "test 3: " & dati
    StrPtr(Stringa) restituisce un indirizzo valido (<> 0)
    ma la copymemory crasha pure



Ehm... Ma leggere PRIMA la dichiarazione della CopyMemory no?
I primi due parametri sono As ANY, quindi e' ovvio che devi passarli
ByVal(CLng()), altrimenti passi il puntatore al puntatore decrementato, non
il puntatore stesso!
    Dim Stringa As String
    Dim dati As Long
    Stringa = "hello ICLVB"
    MsgBox "test 1: " & LenB(Stringa)
            LenB, non Len, c'e' la dimensione in BYTE nella BSTR
    CopyMemory dati, ByVal (CLng(VarPtr(Stringa) - 4)), 4
    MsgBox "test 2: " & dati
            Ritorna 0
    CopyMemory dati, ByVal (CLng(StrPtr(Stringa) - 4)), 4
    MsgBox "test 3: " & dati
            Ritorna 22... Funziona.
Ciaotutti,
*

             Ritorna 22... Funziona.
la stessa riga:
RtlMoveMemory dati, ByVal (CLng(StrPtr(Stringa) - 4)), 4
MsgBox "test 3: " & dati
a me crasha tacitamente invece, ovvero senza messaggio di errore.
chiude l'ide (o l'exe) e basta. provati entrambi con win2k.
provato anche su Win98SE e nell'ultimo caso con exe compilato
(il pc non ha vb) restituisce il valore 0.
ottenuti gli stessi risultati utilizzando la dichiarazione
Private Declare Sub RtlMoveMemory Lib "kernel32.dll" (Destination As _
Any, Source As Any, ByRef Length As Long)
mah.. misteri di mamma MS
--
Fibia "pascal ha puntatori, c pure, perché quelli di VB fanno schifo?" FBI


 As Long, Source As Long, ByRef Length As Long)
                                    ^^^^^^^^^^^^^^^^^^^^^
Hai usato questa declare? E non ti ha sputato in faccia? Fortunato...
Vorrei capire come mai, dato che il parametro length va passato byval...
Prova usando la declare che ti ho postato sopra, poi ne riparliamo :P
Ciaotutti,
*

 Prova usando la declare che ti ho postato sopra, poi ne riparliamo :P
hai ragionissima
quella cavolo di declare l'ho presa dall'API Toolshed di 
allapi.net
argh.. non posso fidarmi neanche dell'api guide?
--
Fibia "Munch - The Scream" FBI



Caspita... Mandagli un'e-mail, questo e' un bug coi contro...fiocchi :P
Ciaotutti,
*


ho scaricato la nuova versione 3.6 dell'api toolshed (che ora si chiama
API Viewer) e l'API incriminata persiste
nell'essere dichiarata per riferimento (ma come ca$$$ parlo?)
Declare Sub RtlMoveMemory Lib "kernel32.dll" (Destination As Any, _
Source As Any,ByRef Length As SIZE_T )
Perň notiamo un'altra finezza di casa 
allapi.net
nell'api-guide la dichiarazione č corretta
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(pDst As Any, pSrc As Any, ByVal ByteLen As Long)
mah.. dove andremo a finire?
come dite? .NET? no no no.. io mi tengo VB5 ;)
--
Fibia "piů vecchio di suo nonno" FBI
