Newsgroup: it.comp.lang.visual-basic
Titolo: CopyMemory su Variant

sto uscendo pazzo...
se io faccio così:
dim a(3,3) as variant, b (3,3) as variant
sub Main
(assegno dei valori a a())
(ogni volta che assegno qualche cosa, metto questa istruzione):
BytesTot=BytesTot + len(a(J,K))
(per sapere alla fine a quanto "ammonta" a()).
(poi faccio)
copymemory b(0,0), a(0,0), BytesTot
mi copia solo il primo elemento.
se moltiplico BytesTot per 10, 15, ecc. a volte me copia solo alcuni ,altre
volte me li copia tutti, ma puntualmente dopo un po mi si blocca tutto...
in realtà TUTTI gli elementi di a() contengon dei valori, e quindi nessuno è
vuoto.
sono sicuro che c'è un valore costanrte per cui moltiplicare BytesTot,
essendo al contempo sicuri di copiare tutto, ma senza crashare... qualcuno
lo conosce?
del resto ho provato la stessa cosa con TUTTI gli altri tipi di dati, e ha
sempre funzionato alla grande (BytesTot non andava moltiplicato per niente).
solo con Variant fa questi problemi...
MarioH

 se io faccio cosě:


Ne so poco e niente di CopyMemory, ma credo che il problema sia il tipo di
dato che e' dentro al variant.
Il variant e' solo un contenitore/puntatore (che occupa una spazio fisso) di
un tipo di dato che ha una sua occupazione (variabile a seconda del tipo di
dato).
Se premi F1 e vai su tipi di dati e vai su variant, troviti l'esatta
occupazione di un variant con un certo tipo di dato.
Certo che se nel tuo variant hai dati di tipo diverso la vedo piuttosto
tragica.
Auguri.
Salve
            Dbg
MarioH ha scritto nel messaggio


 ha scritto nel messaggio
news:94qj4c$es857$1...@ID-70152.news.dfncis.de...


 dimensione effettiva occupata da vettori e matrici
Lo e' per un vettore a dimensione fissa.
Non lo per un SAFEARRAY o per un Variant
Per questi due tipi, infatti, esiste un DESCRITTORE, che e' quello a cui
punta il VarPtr, e uno spazio di memoria, che e' l'header vero e proprio, il
cui puntatore e' contenuto nel descrittore.
Un Variant ha una larghezza piu' o meno fissa (dovrebbe esserci
documentazione in merito dato che il COM e' uno standard) ma va manipolato
in modo diverso dalle stringhe e dai tipi predefiniti... Infatti i Variant
vanno trattati come puntatori a una struttura che a sua volta contiene dei
puntatori.
Ciaotutti,
Alessandro

quindi variant aggiunge dei byte anche se la stringa o il numero č piu
piccolo... sulla guida avevo cercato, perche ci avevo pensato, ma non ho
trovato il valore "standard" di un variant.
mario

ma con gli integer, single ecc. mi funziona alla perfezione, e soprattutto
non da nessun problema tipo errore generale...

 puntatori.
e quindi...?? come lo uso questo varptr (che tra l'altro so di che si tratta
piu o meno, ma non c'è sull'help...) ??
mario

sto uscendo pazzo...
La struttura di un variant č questa:
'tradotta in Type
Type TVARIANT
    iVarType As Integer
    dwUnused1 As Integer
    dwUnused2 As Long
    dwData1 As Long ' if data-type is byref this contain the address
    dwData2 As Long
End Type
quindi:
Se il dato č di 4 bytes (es. long) il dato sta nei bytes 9-12.
Se il dato č di 8 bytes (es. double/date) il dato sta nei bytes 9-16.
Se si tratta di stringhe o array (o altro) i bytes 9-12 contengolo il
puntatore (l'indirizzo) dei dati veri e propri.
Comunque, tutto questo per il tuo problema non serve a niente :)
Sappi solo che un variant č lungo 16 bytes (piů i dati veri se il variant
contiene array, stringhe o altro, e questi vanno copiati separatamente).
Quindi se tu devi copiare array di variant(long) ti basta questo:
(1) se usi questa versione di CopyMemory()
    Declare Function CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst
As Any, pSrc As Any, ByVal BytesLen As Long) As Long
Fai
    Call CopyMemory(b(1), a(1), 16 * UBound(a))
(2) Se usi
    Declare Function CopyMemoryL Lib "kernel32" Alias "RtlMoveMemory" (ByVal
pDst As Long, ByVal pSrc As Long, ByVal BytesLen As Long) As Long
Fai
    Call CopyMemoryL(VarPtr(b(1)), VarPtr(a(1)), 16 * UBound(a))
Ciao

scusa questa mi č nuova-nuovissima, cosa č copymemoryL..??? quella L finale
a che serve? d che funzione si tratta? e perche in una ci sono le variabili
e nell'altra i puntatori?
mario

e nell'altra i puntatori?
Beh, qui bisogna partire un po' dall'inizio.
(1) Dato che CopyMemory() è solo un alias di "RtlMoveMemory" puoi dargli il
nome che vuoi.
La funzione nella DLL è "RtlMoveMemory", non "CopyMemory".
Ho aggiunto semplicemente la "L" in fondo perchè così posso averle
dichiarate in modi diversi: una con i parametri "As Any" e l'altra con
"ByVal As Long".
VB così crede che sono due funzioni diverse e non mi dice "dichiarazione
doppia".
(2) A una gli passo i puntatori proprio perchè la dichiarazione richiede il
puntatore.
Mantre usando "As Any" tu passi implicitamente il puntatore (e VB non fa
alcun controllo su cosa viene realmente passato, da qui "As Any"), con
"ByVal As Long" sta a te passare il puntatore ai dati.
Alla fine il risultato è esattamente lo stesso.
In casi particolari è più comodo avere una dichiarazione anzichè l'altra.
Personalmente se posso scelgo sempre quella dove il tipo di dato da passare
lo conosco.
Ciao

Ricordati che i variant sono dei contenitori/puntatori di altri tipi di
dati.
Se il tuo scopo e' copiare un array non hai bisogno di CopyMemory.
Prova questo:
 Dim A() As String, B As Variant, C As Variant
 ReDim A(10)
 A(0) = "zero"
 B = A()
 C = B
 Debug.Print B(0), C(0)
 C(0) = "uno"
 Debug.Print B(0), C(0)
 ReDim C(20)
 Debug.Print UBound(B), UBound(C)
In ogni caso ecco le informazioni sui variant
Variant
(con numeri) 16 byte Qualsiasi valore numerico fino all'intervallo di un
Double
Variant
(con caratteri) 22 byte + lunghezza stringa Stesso intervallo di String a
lunghezza variabile
Definito dall'utente
(utilizzando Type) Numero richiesto dagli elementi L'intervallo di ciascun
elemento č identico a quello del relativo tipo di dati sopraelencato.
Nota   Le matrici di qualsiasi tipo di dati richiedono 20 byte di memoria
piů quattro byte per ogni dimensione della matrice piů il numero di byte
occupati dai dati stessi. La memoria occupata dai dati puň essere calcolata
moltiplicando il numero di elementi dei dati per le dimensioni di ciascun
elemento. I dati in una matrice unidimensionale composti da quattro elementi
di dati Integer di due byte ciascuno, ad esempio, occupano otto byte. Gli
otto byte richiesti dai dati piů i 24 byte di overhead portano a 32 byte la
memoria complessiva richiesta per la matrice.
Un tipo di dati Variant contenente una matrice richiede 12 byte in piů
rispetto al numero di byte richiesti dalla matrice da sola.
Salve
                Dbg
MarioH ha scritto nel messaggio


grande!!!!
ricapitolando, se dichiaro come Long, devo usare VarPtr, se dichiaro come
Any devo passare la variabile.
ecco perche se dichiaro come Any e passo VarPtr non funziona...
avevo molto piu semplicemente provato a scrivere
Dim p1 As Double, p2 As Double
p1 = 42
CopyMemory VarPtr(p2), VarPtr(p1), ByVal CLng(8)
Debug.Print p2
End
e p2 restava = 0, perch copymemory era dichiarata con Any. se dichiaravo con
Long, allora usando VarPtr funzionava, giusto?
grazie 1000

Long, allora usando VarPtr funzionava, giusto?
In pratica copiavi il puntatore al puntatore di p1 su p2 e i 4 bytes
successivi nei quattro successivi al puntatore del puntatore di p2.
Incredibile che tu non abbia avuto un GPF.
Ciao

 Incredibile che tu non abbia avuto un GPF.
Lo ha avuto, lo ha avuto :))
->sono sicuro che c'è un valore costanrte per cui moltiplicare BytesTot,
->essendo al contempo sicuri di copiare tutto, ma senza crashare... qualcuno
->lo conosce?
Ciaotutti,
Alessandro