Differenze tra le versioni di "Definizione ed uso dei Memory Stream"
Riga 35: | Riga 35: | ||
<Font Color=gray>' ''Si dereferenzia il Puntatore, ossia si accede alla locazione di memoria puntata (quella della variabile "i"):''</font> | <Font Color=gray>' ''Si dereferenzia il Puntatore, ossia si accede alla locazione di memoria puntata (quella della variabile "i"):''</font> | ||
− | + | p = VarPtr(i) <Font Color=#B22222>' '' p = &i;''</font> | |
<Font Color=gray>' ''Si scrive (in Gambas lo si fa usando una variabile di tipo "Stream") nella locazione di memoria puntata (quella della variabile "i"):''</font> | <Font Color=gray>' ''Si scrive (in Gambas lo si fa usando una variabile di tipo "Stream") nella locazione di memoria puntata (quella della variabile "i"):''</font> | ||
− | + | st = Memory p For Write | |
− | + | Write #st, 99999 As Integer <Font Color=#B22222>' '' *p = 99999''</font> | |
− | + | st.Close | |
− | + | Print "i = "; i <Font Color=#B22222>' '' printf("i = %d\n", i);''</font> | |
'''End''' | '''End''' | ||
+ | La modalità in "Scrittura" (''For Write'') risulta ''particolarmente'' utile nel caso si debbano scrivere dei valori all'interno di un'area di memoria riservata, allocata con la funzione ''Alloc()'' . | ||
− | + | In questo esempio, si intende creare all'interno di un'area di memoria riservata con "Alloc()" una sequenza dei seguenti byte: &h80, &h81, &h82, &h83, lo si può fare scrivendo: | |
− | |||
− | |||
− | In questo esempio, si intende creare all'interno di un'area di memoria riservata con | ||
'''Public''' Sub Main() | '''Public''' Sub Main() | ||
Riga 60: | Riga 58: | ||
<Font Color=gray>' ''Questa memoria sarà un flusso (stream) che creeremo appositamente, e...''</font> | <Font Color=gray>' ''Questa memoria sarà un flusso (stream) che creeremo appositamente, e...''</font> | ||
− | st = Memory p For Write | + | st = Memory p <Font Color=#B22222>For Write</font> |
<Font Color=gray>' ''...nel quale andiamo a scrivere i 4 valori byte.'' | <Font Color=gray>' ''...nel quale andiamo a scrivere i 4 valori byte.'' | ||
Riga 79: | Riga 77: | ||
Per mostrare un esempio pratico, poniamo il caso che ad una sub-procedura venga passato un ''Puntatore'', che punta ad un'area riservata precedentemente allocata (come nell'esempio visto nel paragrafo di sopra) al fine di derefenziarlo con i ''Memory Stream''. Si procederà ad estrarre i valori contenuti in quest'aera riservata di memoria: | Per mostrare un esempio pratico, poniamo il caso che ad una sub-procedura venga passato un ''Puntatore'', che punta ad un'area riservata precedentemente allocata (come nell'esempio visto nel paragrafo di sopra) al fine di derefenziarlo con i ''Memory Stream''. Si procederà ad estrarre i valori contenuti in quest'aera riservata di memoria: | ||
+ | '''Public''' Sub Main() | ||
+ | |||
+ | Dim p As Pointer | ||
+ | Dim st As Stream | ||
+ | Dim b As Byte | ||
+ | |||
+ | p = Alloc(SizeOf(gb.Byte), 4) | ||
+ | |||
+ | st = Memory p <Font Color=#B22222>For Write</font> | ||
+ | |||
+ | For b = 80 to 83 | ||
+ | Write #st, b As Byte | ||
+ | Next | ||
+ | <Font Color=gray>' ''Chiudiamo il flusso in "Scrittura":''</font> | ||
+ | st.Close | ||
+ | |||
+ | <Font Color=gray>' ''Invoca la funzione per dereferenziare il Puntatore:''</font> | ||
+ | Dereferenzia(p) | ||
+ | |||
+ | Free(p) | ||
+ | |||
+ | '''End''' | ||
+ | |||
'''Private''' Procedure Dereferenzia(p As Pointer) | '''Private''' Procedure Dereferenzia(p As Pointer) | ||
Riga 85: | Riga 106: | ||
<Font Color=gray>' ''Generiamo la variabile di tipo "Stream" dal "Puntatore" che è stato passato con la chiamata della sub-procedura:''</font> | <Font Color=gray>' ''Generiamo la variabile di tipo "Stream" dal "Puntatore" che è stato passato con la chiamata della sub-procedura:''</font> | ||
− | + | st = Memory p For Read | |
<Font Color=gray>' ''Riprendiamo l'esempio del paragrafo precedente, dove sono stati scritti 4 valori di tipo "byte"; e li andiamo ad "estrarre" leggendo dalla variabile di tipo "Stream":''</font> | <Font Color=gray>' ''Riprendiamo l'esempio del paragrafo precedente, dove sono stati scritti 4 valori di tipo "byte"; e li andiamo ad "estrarre" leggendo dalla variabile di tipo "Stream":''</font> | ||
− | + | For j = 0 To 3 | |
− | + | Read #st, b | |
− | + | Print "---> ", b | |
− | + | Next | |
− | <Font Color=gray>' ''Chiudiamo il flusso:''</font> | + | <Font Color=gray>' ''Chiudiamo il flusso in "Lettura":''</font> |
− | + | st.Close | |
'''End''' | '''End''' | ||
Riga 101: | Riga 122: | ||
==Altri esempi sulla scrittura e lettura delle variabili di tipo "Stream"== | ==Altri esempi sulla scrittura e lettura delle variabili di tipo "Stream"== | ||
Scriviamo nello ''Stream'' un testo, poi lo recuperiamo leggendo lo ''Stream'': | Scriviamo nello ''Stream'' un testo, poi lo recuperiamo leggendo lo ''Stream'': | ||
− | '''Public''' Sub | + | '''Public''' Sub Main() |
Dim p As Pointer | Dim p As Pointer | ||
Riga 175: | Riga 196: | ||
Si procederà ugualmente per dereferenziare i puntatori <SPAN style="text-decoration:underline">passati da funzioni esterne</span>. | Si procederà ugualmente per dereferenziare i puntatori <SPAN style="text-decoration:underline">passati da funzioni esterne</span>. | ||
− | '''Public''' Sub | + | '''Public''' Sub Main() |
Dim p As Pointer | Dim p As Pointer | ||
Riga 182: | Riga 203: | ||
<Font Color=gray>' ''Prendiamo da una funzione esterna un valore di tipo puntatore:''</font> | <Font Color=gray>' ''Prendiamo da una funzione esterna un valore di tipo puntatore:''</font> | ||
− | + | funzione_esterna_che_passa_un puntatore(p) | |
<Font Color=gray>' ''Usiamo i Memory Stream in modalità di "lettura":''</font> | <Font Color=gray>' ''Usiamo i Memory Stream in modalità di "lettura":''</font> | ||
− | + | st = Memory p For Read | |
<Font Color=gray>' ''Andiamo a dereferenziare e, quindi, a leggere il dato:''</font> | <Font Color=gray>' ''Andiamo a dereferenziare e, quindi, a leggere il dato:''</font> | ||
− | + | Read #st, b | |
<Font Color=gray>' ''Chiudiamo il flusso di dati:''</font> | <Font Color=gray>' ''Chiudiamo il flusso di dati:''</font> | ||
− | + | st.Close | |
<Font Color=gray>' ''Ora, ad esempio, mostriamo il valore in console:''</font> | <Font Color=gray>' ''Ora, ad esempio, mostriamo il valore in console:''</font> | ||
− | + | Print b | |
'''End''' | '''End''' |
Versione delle 18:11, 25 nov 2021
La classe Memory-Stream crea flussi di dati che utilizzano la RAM. Pertanto, i "Memory-Stream" sono dei flussi di dati in memoria.
Con la versione 3 di Gambas non è possibile scrivere direttamente in un'area di memoria puntata da un Puntatore. Per fare ciò è necessario utilizzare la risorsa "Memory-Stream", la quale da una variabile di tipo Puntatore crea una variabile di tipo Stream consentendo così di scrivervi (ma anche di leggervi).
Dunque la risorsa Memory-Stream serve per leggere e in particolar modo per scrivere in una variabile di tipo Puntatore che punta ad un'area di memoria riservata.
Dopo la scrittura bisognerà comunque utilizzare nel resto del codice la variabile Puntatore: la variabile di tipo Stream in tal caso serve soltanto per poter scrivere nell'area di memoria allocata e puntata dal "Puntatore".
Tale area di memoria può essere:
- quella di una variabile, dalla quale sarà stato creato un Puntatore (che punta all'indirizzo di detta variabile) con la funzione VarPtr();
- un'area riservata avente una determinata dimensione allocata da noi mediante la funzione Alloc();
- quella di un Puntatore passato da una funzione esterna dichiarata con Extern.
Una volta utilizzata
Come già detto, la scrittura e la lettura avviene utilizzando una variabile di tipo "Stream" generata dalla risorsa Memory-Stream partendo dalla variabile Puntatore.
La sintassi dell'utilizzo dei Memory Stream è la seguente:
variabile_Stream = MEMORY Puntatore FOR [ READ ] [ WRITE ]
- Se la parola chiave READ viene specificata, allora è permessa la lettura.
- Se la parola chiave WRITE viene specificata, allora è permessa la scrittura.
Ovviamente, con riferimento al formato Big-Endian/Little-Endian, la procedura di scrittura e di lettura dei dati nel flusso (stream) è identica alla procedura che avviene con i file.
Una volta utilizzata per leggere o per scrivere nel Puntatore, la variabile di tipo Stream viene abbandonata chiudendo il flusso con il metodo variabile_Stream.Close .
Indice
Memory Stream in modalità "For Write"
Si può quindi scrivere nella variabile Stream con l'istruzione "Write" o anche con l'istruzione "Print".
Riteniamo utile fare un semplice confronto con il codice C:
Public Sub Main() Dim i As Integer ' int i; Dim p As Pointer ' int * p; Dim st As Stream ' Si dereferenzia il Puntatore, ossia si accede alla locazione di memoria puntata (quella della variabile "i"): p = VarPtr(i) ' p = &i; ' Si scrive (in Gambas lo si fa usando una variabile di tipo "Stream") nella locazione di memoria puntata (quella della variabile "i"): st = Memory p For Write Write #st, 99999 As Integer ' *p = 99999 st.Close Print "i = "; i ' printf("i = %d\n", i); End
La modalità in "Scrittura" (For Write) risulta particolarmente utile nel caso si debbano scrivere dei valori all'interno di un'area di memoria riservata, allocata con la funzione Alloc() .
In questo esempio, si intende creare all'interno di un'area di memoria riservata con "Alloc()" una sequenza dei seguenti byte: &h80, &h81, &h82, &h83, lo si può fare scrivendo:
Public Sub Main() Dim p As Pointer Dim st As Stream Dim b As Byte ' Riserviamo 4 byte da qualche parte in memoria: p = Alloc(SizeOf(gb.Byte), 4) ' Questa memoria sarà un flusso (stream) che creeremo appositamente, e... st = Memory p For Write ' ...nel quale andiamo a scrivere i 4 valori byte. ' Ogni valore byte occuperà la dimensione di 1 byte, quindi copriranno esattamente i 4 byte allocati: For b = 80 to 83 Write #st, b As Byte Next ' Chiudiamo il flusso e liberiamo la parte di memoria precedentemente allocata: st.Close Free(p) End
Memory Stream in modalità "For Read"
In modalità "For Read" i Memory-Stream possono essere usati per dereferenziare i puntatori.
Per mostrare un esempio pratico, poniamo il caso che ad una sub-procedura venga passato un Puntatore, che punta ad un'area riservata precedentemente allocata (come nell'esempio visto nel paragrafo di sopra) al fine di derefenziarlo con i Memory Stream. Si procederà ad estrarre i valori contenuti in quest'aera riservata di memoria:
Public Sub Main() Dim p As Pointer Dim st As Stream Dim b As Byte p = Alloc(SizeOf(gb.Byte), 4) st = Memory p For Write For b = 80 to 83 Write #st, b As Byte Next ' Chiudiamo il flusso in "Scrittura": st.Close ' Invoca la funzione per dereferenziare il Puntatore: Dereferenzia(p) Free(p) End Private Procedure Dereferenzia(p As Pointer) Dim j, b As Byte Dim st As Stream ' Generiamo la variabile di tipo "Stream" dal "Puntatore" che è stato passato con la chiamata della sub-procedura: st = Memory p For Read ' Riprendiamo l'esempio del paragrafo precedente, dove sono stati scritti 4 valori di tipo "byte"; e li andiamo ad "estrarre" leggendo dalla variabile di tipo "Stream": For j = 0 To 3 Read #st, b Print "---> ", b Next ' Chiudiamo il flusso in "Lettura": st.Close End
Altri esempi sulla scrittura e lettura delle variabili di tipo "Stream"
Scriviamo nello Stream un testo, poi lo recuperiamo leggendo lo Stream:
Public Sub Main() Dim p As Pointer Dim st As Stream Dim s, ss As String Dim j As Byte p = Alloc(SizeOf(gb.Byte), 4) st = Memory p For Read Write s = "testo qualsiasi" ' Scriviamo la stringa nella variabile di tipo "Stream": Print #st, s ''''''''''''''' ' Leggiamo nella variabile di tipo "Stream" ' Poiché con la precedente scrittura l'indice dello "stream" è incrementato di uno, si dovrà re-impostare la lettura all'indice zero: Seek #st, 0 Line Input #st, ss Print "Contenuto dello stream: "; ss ' Chiudiamo il flusso e liberiamo la parte di memoria precedentemente allocata: st.Close Free(p) End
Secondo esempio - leggiamo con l'istruzione Shell congiunta al comando bash "ls" nella cartella "/proc", e riportiamo in una TextArea il contenuto ivi letto distinguendo ciascuna sub-cartella o file mediante Input.
Nel codice scriveremo in un flusso per mezzo dei Memory Stream tutti i dati ricavati con ls; e per verifica leggeremo dal flusso - sempre per mezzo dei Memory Stream - quei dati scritti poco prima:
Public Sub Button1_Click() Dim s, ss As String Dim p As Pointer Dim m As Stream Dim j As Integer Shell "ls /proc" To s ' Allochiamo sufficiente memoria, e vi puntiamo con una variabile di tipo "puntatore": p = Alloc(SizeOf(gb.Byte), 2048) ' Creiamo la variabile "m" di tipo "Stream": m = Memory p For Read Write ' Scriviamo nella variabile "m" il contenuto della variabile stringa "s": Print #m, s While Not Eof(m) ' Guidiamo la lettura nella variabile "m" mediante il comando "Seek": Seek #m, j Input #m, ss ' Se non vi sono più dati relativi a caratteri alfanumerici, allora si esce dal ciclo: If ss == Null Then Exit TextArea1.Text &= ss & Chr(10) ' Si dà il valore al comando "Seek per far cominciare" la lettura dal byte corrispondente nella variabile "s" ad ogni inizio riga: j = j + Len(ss) + 1 Wend ' Liberiamo la parte di memoria precedentemente allocata: m.Close Free(p) End
In modalità "Lettura" per dereferenziare i puntatori passati da funzioni esterne
Si procederà ugualmente per dereferenziare i puntatori passati da funzioni esterne.
Public Sub Main() Dim p As Pointer Dim st As Stream Dim b As Byte ' Prendiamo da una funzione esterna un valore di tipo puntatore: funzione_esterna_che_passa_un puntatore(p) ' Usiamo i Memory Stream in modalità di "lettura": st = Memory p For Read ' Andiamo a dereferenziare e, quindi, a leggere il dato: Read #st, b ' Chiudiamo il flusso di dati: st.Close ' Ora, ad esempio, mostriamo il valore in console: Print b End