Read ()

Da Gambas-it.org - Wikipedia.

La funzione read(), dichiarata nel file header "/usr/include/unistd.h"

ssize_t read (int __fd, void *__buf, size_t __nbytes)

legge da un file usando il suo file descriptor (1° parametro) un numero di byte definito nel suo 3° parametro, memorizzandoli nel buffer stabilito nel 2° parametro.


Volendola utilizzare in Gambas, bisognerà dichiararla con Extern, nonché dichiarare la libreria di C: libc.so.6, nella quale la funzione è contenuta. Da sottolineare che, poiché questa funzione esterna di C "read( )" è omonima alla funzione di Gambas "Read", bisognerà assegnarle un nome a piacere, ma si dovrà anche richiamare il suo vero nome con il comando Exec.
Dunque avremo ad esempio:

Private Extern read_C(_fd As Integer, __buf As Pointer, __nbytes As Long) As Long In "libc:6" Exec "read"


Mostriamo un semplice esempio pratico, nel quale il programma leggerà quanto scritto nella console/Terminale dall'utente:

Library "libc:6"

Private const STDIN as integer = 0

' ssize_t read (int __fd, void *__buf, size_t __nbytes)
' Read NBYTES into BUF from FD.
Private Extern read_C(__fd As Integer, __buf As Pointer, __nbytes As Long) As Long Exec "read"


Public Sub Main()
 
 Dim bb As New Byte[16]
 
  read_C(STDIN, bb.Data, bb.Count)
  
  Print String@(bb.Data)
  
' ....oppure (nel 2° argomento del Metodo ".ToString()" è necessario individuare la posizione del primo elemento del vettore,
' contenente il valore zero (&h00), affinché la stampa dei caratteri, contenuti dal vettore, si fermi all'ultimo carattere diverso da zero):
  Print bb.ToString(0, bb.Find(0))
  
End


Quest'altro codice prevede l'uso di un'area di memoria allocata, puntata da una variabile di tipo Puntatore, ove memorizzare i dati (caratteri) scritti nella console/terminale:

Library "libc:6"

' ssize_t read (int __fd, void *__buf, size_t __nbytes)
' Read NBYTES into BUF from FD.
Private Extern read_C(__fd As Integer, __buf As Pointer, __nbytes As Long) As Long Exec "read"


Public Sub Main()
 
 Dim p As Pointer
 Dim st As Stream
 Dim i As Integer
  
  p = Alloc(SizeOf(gb.Byte), 32)
  
' Ripuliamo l'area di memoria allocata, scrivendoci valori uguali a zero (&h00).
' Ciò al fine di consentire alla successiva funzione di dereferenziazione di arrestarsi al primo valore zero incontrato:
  st = Memory p For Write
  For i = 0 To 32
    Write #st, 0 As Byte
  Next
  st.Close
  
' Nel primo argomento passiamo l'identificativo del "file-descriptor", ottenuto in altro modo:
  read_C(File.In.Handle, p, 32)
  
  Write String@(p)
 
  Free(p)
  
End


In questo codice, invece, si aprirà il file-device dello standard input mediante la ordinaria istruzione Open nativa di Gambas.

 Library "libc:6"

' ssize_t read (int __fd, void *__buf, size_t __nbytes)
' Read NBYTES into BUF from FD.
Private Extern read_C(__fd As Integer, __buf As Pointer, __nbytes As Long) As Long Exec "read"


Public Sub Main()
 
 Dim fl As File
 Dim sz As Long
 Dim bb As Byte[]
  
' Per permettere che la funzione esterna "read_C" resti in attesa dell'immissione ed invio di uno o più caratteri,
' è necessario utilizzare l'istruzione "For Input" (e non "For Read", nel qual caso non vi sarà attesa).
  fl = Open "/dev/stdin" For Input
  
  bb = New Byte[16]
  
  sz = read_C(fl.Handle, bb.Data, bb.Count)
  
  Print
' Mostriamo tre modalità possibili in questo caso per stampare in console il risultato:
  Print bb.ToString(0, CInt(sz - 1)), String@(bb.Data), bb.ToString(0, bb.Find(0))
  
  fl.Close
  
End

Questo codice mostra come debba essere combinata l'istruzione "Open" nativa di Gambas con la funzione esterna "read( )" di C.

Da notare che se la dimensione del testo immesso è inferiore al valore espresso nel 3° parametro della funzione esterna "read_C", verrà aggiunto anche il carattere &h0A (nuova riga a capo).


In quest'altro esempio leggeremo il contenuto presente in un file, e scriveremo i dati - ivi letti ad uno ad uno - all'interno di un'area di memoria allocata con la funzione nativa " Alloc( ) ", la quale andrà dinamicamente aumentando di volta in volta per memorizzare un dato appena letto dal file.

Library "libc:6"

' ssize_t read (int __fd, void *__buf, size_t __nbytes)
' Read NBYTES into BUF from FD.
Private Extern read_c(__fd As Integer, __buf As Pointer, __nbytes As Long) As Long Exec "read"


Public Sub Main()
 
 Dim fl As File
 Dim l As Long
 Dim p As Pointer
 Dim i As Integer
  
' Apre il file in "lettura":
  fl = Open "/percorso/del/file" For Read
  
' Alloca un iniziale byte dell'area di memoria ove scrivere i dati dal file:
  p = Alloc(SizeOf(gb.Byte), 1)
  
' Inizia il ciclo per leggere dal file un byte di dati alla volta.
' Alla funzione "read_c" viene passato:
' * il numero identificativo del "file-descriptor" del file aperto;
' * la variabile di tipo Puntatore aumentata del valore presente in "i" per spostarci lungo l'area di memoria allocata, al fine di scrivere nel byte disponibile il dato letto dal file;
' * la quantità (pari a 1) di dati da leggere dal file:
  While read_c(fl.Handle, p + i, SizeOf(gb.Byte)) > 0
    Inc i
' Realloca l'area di memoria incrementandola di 1 byte:
    p = Realloc(p, SizeOf(gb.Byte), i + 1)
' Se si è giunti alla fine del file, esce dal ciclo:
  Wend
   
' Dereferenzia la variabile di tipo Puntatore, per scrivere in console i dati letti dal file.
' Usiamo la funzione "Left()", per prendere soltanto i dati effettivamente letti dal file e memorizzati nell'area di memoria allocata:
  Print Left(String@(p), i)
   
' Libera tutta la memoria precedentemente occupata:
  Free(p)
  fl.Close
  
End

Anche in quest'ultimo codice viene mostrato un caso in cui viene combinata l'istruzione "Open" nativa di Gambas con la funzione esterna "read( )" di C.



Riferimenti