Differenze tra le versioni di "Definizione ed uso dei Memory Stream"

Da Gambas-it.org - Wikipedia.
Riga 57: Riga 57:
 
   
 
   
 
  <Font Color=gray>' ''Riserviamo 4 byte da qualche parte in memoria:''</font>
 
  <Font Color=gray>' ''Riserviamo 4 byte da qualche parte in memoria:''</font>
  p = Alloc(4)
+
  p = Alloc(SizeOf(gb.Byte), 4)
 
   
 
   
 
  <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 For Write
 
   
 
   
 
  <Font Color=gray>' ''...nel quale andiamo a scrivere i 4 valori byte.''
 
  <Font Color=gray>' ''...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:''</font>
 
  ' ''Ogni valore byte occuperà la dimensione di 1 byte, quindi copriranno esattamente i 4 byte allocati:''</font>
  For b = 80 to 83
+
  For b = 80 to 83
    Write #st, b As Byte
+
    Write #st, b As Byte
  Next
+
  Next
 
   
 
   
 
  <Font Color=gray>' ''Chiudiamo il flusso e liberiamo la parte di memoria precedentemente allocata:''</font>
 
  <Font Color=gray>' ''Chiudiamo il flusso e liberiamo la parte di memoria precedentemente allocata:''</font>
  st.Close
+
  st.Close
  Free(p)
+
  Free(p)
 
   
 
   
 
  '''End'''
 
  '''End'''
Riga 83: Riga 83:
 
   Dim j, b As Byte
 
   Dim j, b As Byte
 
   Dim st As Stream
 
   Dim st As Stream
 
 
   
 
   
 
  <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>
Riga 109: Riga 108:
 
   Dim j As Byte
 
   Dim j As Byte
 
    
 
    
    p = Alloc(4)
+
  p = Alloc(SizeOf(gb.Byte), 4)
 
      
 
      
    st = Memory p For Read Write
+
  st = Memory p For Read Write
 
      
 
      
    s = "testo qualsiasi"
+
  s = "testo qualsiasi"
 
      
 
      
 
  <Font Color= #006400>' ''Scriviamo la stringa nella variabile di tipo "Stream":''</font>
 
  <Font Color= #006400>' ''Scriviamo la stringa nella variabile di tipo "Stream":''</font>
    Print #st, s
+
  Print #st, s
 
   
 
   
  <Font Color= #006400>''''''''''''''''''''</font>
+
<Font Color= #006400>''''''''''''''''''''</font>
 
   
 
   
 
  <Font Color= #006400>' ''Leggiamo nella variabile di tipo "Stream"''</font>
 
  <Font Color= #006400>' ''Leggiamo nella variabile di tipo "Stream"''</font>
 
   
 
   
  <Font Color= #006400>' ''Poiché con la precedente scrittura l'indice dello "stream"''
+
  <Font Color= #006400>' ''Poiché con la precedente scrittura l'indice dello "stream" è incrementato di uno, si dovrà re-impostare la lettura all'indice zero:</font>
' ''è incrementato di uno, si dovrà re-impostare la lettura all'indice zero:</font>
+
  Seek #st, 0
      Seek #st, 0
+
  Line Input #st, ss
      Line Input #st, ss
 
 
   
 
   
      Print "Contenuto dello stream: "; ss
+
  Print "Contenuto dello stream: "; ss
 
   
 
   
 
  <Font Color= #006400>' ''Chiudiamo il flusso e liberiamo la parte di memoria precedentemente allocata:''</font>
 
  <Font Color= #006400>' ''Chiudiamo il flusso e liberiamo la parte di memoria precedentemente allocata:''</font>
    st.Close
+
  st.Close
    Free(p)
+
  Free(p)
 
   
 
   
 
  '''End'''
 
  '''End'''
Riga 143: Riga 141:
 
   Dim m As Stream
 
   Dim m As Stream
 
   Dim j As Integer
 
   Dim j As Integer
 
 
 
    
 
    
  Shell "ls /proc" To s
+
  Shell "ls /proc" To s
 
   
 
   
  <Font Color= #006400>' ''Allochiamo sufficiente memoria,''
+
  <Font Color= #006400>' ''Allochiamo sufficiente memoria, e vi puntiamo con una variabile di tipo "puntatore":''</font>
' ''e vi puntiamo con una variabile di tipo "puntatore":''</font>
+
  p = Alloc(SizeOf(gb.Byte), 2048)
  p = Alloc(2048)
 
 
    
 
    
 
  <Font Color= #006400>' ''Creiamo la variabile "m" di tipo "Stream":''</font>
 
  <Font Color= #006400>' ''Creiamo la variabile "m" di tipo "Stream":''</font>
  m = Memory p For Read Write
+
  m = Memory p For Read Write
 
    
 
    
 
  <Font Color= #006400>' ''Scriviamo nella variabile "m" il contenuto della variabile stringa "s":''</font>
 
  <Font Color= #006400>' ''Scriviamo nella variabile "m" il contenuto della variabile stringa "s":''</font>
 
   Print #m, s
 
   Print #m, s
 
   
 
   
+
  While Not Eof(m)
  While Not Eof(m)
 
 
  <Font Color= #006400>' ''Guidiamo la lettura nella variabile "m" mediante il comando "Seek":''</font>
 
  <Font Color= #006400>' ''Guidiamo la lettura nella variabile "m" mediante il comando "Seek":''</font>
    Seek #m, j
+
    Seek #m, j
    Input #m, ss
+
    Input #m, ss
 
 
  <Font Color= #006400>' ''Se non vi sono più dati relativi a caratteri alfanumerici, allora si esce dal ciclo:''</font>
 
  <Font Color= #006400>' ''Se non vi sono più dati relativi a caratteri alfanumerici, allora si esce dal ciclo:''</font>
      If ss = Null Then Exit
+
    If ss == Null Then Exit
+
    TextArea1.Text &= ss & Chr(10)
    TextArea1.Text &= ss & Chr(10)
+
  <Font Color= #006400>' ''Si dà il valore al comando "Seek per far cominciare" la lettura dal byte corrispondente nella variabile "s" ad ogni inizio riga:''</font>
+
    j = j + Len(ss) + 1
  <Font Color= #006400>' ''Si dà il valore al comando "Seek per far cominciare"''
+
  Wend
' ''la lettura dal byte corrispondente nella variabile "s" ad ogni inizio riga:''</font>
 
    j = j + Len(ss) + 1
 
 
  Wend
 
 
   
 
   
 
  <Font Color= #006400>' ''Liberiamo la parte di memoria precedentemente allocata:''</font>
 
  <Font Color= #006400>' ''Liberiamo la parte di memoria precedentemente allocata:''</font>
    m.Close
+
  m.Close
    Free(p)
+
  Free(p)
 
   
 
   
 
  '''End'''
 
  '''End'''

Versione delle 09:15, 29 set 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 soprattuto per scrivere in una variabile di tipo Puntatore che punta ad un'area di memoria riservata.
Dopo la scrittura bisognerà comunque utilizzare la variabile Puntatore: la variabile di tipo Stream quindi 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 .


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


Ma 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:

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:
  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 Button1_Click()

 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 Button1_Click()

 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(VarPtr(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