Write ()
La funzione write( ), dichiarata nel file header /usr/include/unistd.h con la seguente sintassi:
ssize_t write (int __fd, const void *__buf, size_t __n)
scrive nel file, a cui si riferisce il descrittore di file __fd, un numero di byte definito da __n dal buffer puntato da __buf. Essa ritorna il numero di byte scritti, oppure -1 in caso di errore.
Poiché il suo nome è identico al nome della funzione Write di Gambas, è opportuno dichiararla con Extern mediante un nome fitizio, specificando con Exec il suo nome reale: [Nota 1]
Private Extern write_C(__fd As Integer, __buf As Pointer, __n As Long) As Long Exec "write"
Mostriamo un esempio pratico:
Library "libc:6" Private Enum O_RDONLY = 0, O_WRONLY, O_RDWR ' int open(const char *__file, int __oflag, ...) ' Open FILE and return a new file descriptor for it. Private Extern open_C(__file As String, oflag As Integer) As Integer Exec "open" ' ssize_t write (int __fd, const void *__buf, size_t __n) ' Write N bytes of BUF to FD. Private Extern write_C(__fd As Integer, __buf As Pointer, __n As Long) As Long Exec "write" ' int close(int _fd) ' Deallocates the file descriptor indicated by fildes. Private Extern close_C(_fd As Integer) As Integer Exec "close" Public Sub Main() Dim fd, i As Integer Dim l As Long ' Viene aperto in scrittura un file di testo: fd = open_C("/percorso/del/file", O_RDONLY) i = 1000 ' Scrive nel file, utilizzando il suo "file descriptor" come handle il valore contenuto nella variabile "i", ' avendo però l'accortezza di passare alla funzione esterna "write()" l'indirizzo di memoria di quella variabile: l = write_C(fd, VarPtr(i), SizeOf(TypeOf(i))) If l = -1 Then Error.Raise("Impossibile scrivere nel file !") close_C(fd) End
Indice
Uso della funzione esterna write( ) con la funzione Open di Gambas
Nell'esempio precedente abbiamo visto la funzione esterna write( ) scrivere un dato in un file aperto con la funzione open( ) di C. Nel presente paragrafo vedremo sostituire la funzione esterna open( ) di C con la funzione di Gambas Open per aprire in scrittura un file. Bisognerà successivamente all'apertura del file passare al primo argomento della funzione esterna write( ) di C il file descriptor del file aperto, utilizzando la proprietà .Handle della variabile di tipo File relativa al file aperto con Open.
Mostriamo un semplice esempio pratico:
Library "libc:6" ' ssize_t write (int __fd, const void *__buf, size_t __n) ' Write N bytes of BUF to FD. Private Extern write_C(__fd As Integer, __buf As Pointer, __n As Long) As Long Exec "write" Public Sub Main() Dim fl As File Dim p As Pointer Dim i As Integer Dim l As Long fl = Open "/percorso/del/file" For Write i = 100 p = VarPtr(i) l = write(fl.Handle, p, SizeOf(TypeOf(i))) If l = 0 Then Error.Raise("Impossibile scrivere nel file !") fl.Close End
Usare la funzione write( ) con la funzione fopen( )
Mostriamo in questo paragrafo una particolarità: l'uso di due funzioni esterne per aprire e scrivere in un file non appartenenti alla stessa famiglia dele funzioni I/O. Nello specifico si utilizzerà la funzione esterna write( ) per scrivere in un file aperto con la funzione esterna fopen( ).
Per aprire in lettura e/o scrittura un file, si utilizzano in modo esclusivo le funzioni open( ), read( ) e write( ), oppure le funzioni fopen(), fread() e fwrite(). La funzione di apertura del file "open()" ritorna un valore di tipo Intero che è il "file descriptor" del file aperto e che rappresenta così l'handle per gestire la lettura e/o la scrittura del file medesimo. Se invece si utilizza per l'apertura del file la funzione "fopen()", questa ritorna un Puntatore al file aperto. Tale Puntatore sarà l'handle per gestire la lettura e/o la scrittura di quel file. Da ciò si può facilmente notare che il file potrà essere letto e/o scritto solo mediante le funzioni appartenenti alla medesima famiglia della funzione con la quale il file è stato aperto. Così, ad esempio, se si apre il file con la funzione "fopen()" non si potranno usare le funzioni read( ) e write( ).
Esiste, però, la possibilità di utilizzare la funzione fopen( ) congiuntamente ed in sinergia con le due funzioni di lettura e di scrittura, rispettivamente read( ) e write( ), che di norma - come abbiamo sopra detto - non sono utilizzabili con la funzione di apertura fopen( ). Sappiamo che la funzione fopen( ) restituisce un Puntatore ad una Struttura, il cui identificatore MACRO è "FILE", ed è il "typedef" della Struttura _IO_FILE dichiarata nel file header "/usr/include/libio.h".
Non tutti i membri di detta Struttura sono accessibili in un codice scritto inlinguaggio C, in quanto essa viene richiamata nel file header "stdio.h" con la MACRO "FILE" come un tipo "opaco". Fa eccezione il membro chiamato "_fileno", e lì dichiarato come "int" (Intero), contenente il numero del descrittore del file aperto, al quale si riferisce. Essendo, dunque, tale membro accessibile, sarà possibile leggere il valore ivi contenuto, e che - come già detto - rappresenta il numero identificatore del "file descriptor" del file aperto con la funzione fopen( ). Tutto ciò permetterà di utilizzare le funzioni read( ) e write( ) anche su un file aperto con la funzione 'fopen( ).
Usando tali funzioni in Gambas, poiché nell'area di memoria riservata di detta Struttura il membro in questione, __fileno, è posto al byte di indice 112, si passerà il Puntatore, ritornato dalla funzione esterna fopen( ), al primo argomento della funzione read( ) e/o della funzione write( ), avendo cura di piazzare l'offset nell'area riservata all'indice 112.
Mostriamo un semplice esempio, di un file aperto in "scrittira" mediante la funzione fopen( ), nel quale si scriverà un valore Intero però - con gli accorgimenti sopra descritti - mediante la funzione write( ).
Library "libc:6" ' FILE *fopen (const char *__restrict __filename, const char *__restrict __modes) ' Open a file and create a new stream for it. Private Extern fopen(__filename As String, __modes As String) As Pointer ' ssize_t write (int __fd, const void *__buf, size_t __n) ' Write N bytes of BUF to FD. Private Extern write_C(__fd As Integer, __buf As Pointer, __n As Long) As Long Exec "write" ' int fclose (FILE *__stream) ' Close STREAM. Private Extern fclose(filestream As Pointer) As Integer Public Sub Main() Dim p1, p2 As Pointer Dim i As Integer ' Apriamo un file di testo in scrittura: p1 = fopen("/percorso/del/file", "w") i = 100 p2 = VarPtr(i) Print Int@(p2) ' Scrive nel file descriptor del file due volte il valore presente nella variabile "i" puntata dal Puntatore "p2": write_C(Int@(p1 + 112), p2, SizeOf(gb.Integer)) write_C(Int@(p1 + 112), p2, SizeOf(gb.Integer)) ' Chiude il file precedentemente aperto: fclose(p1) End
Note
[1] Si è visto, però, che se nel corpo del codice la funzione esterna di C, avente un nome simile ad una funzione nativa di Gambas, viene utilizzata con il suo esatto nome, ossia con la lettera iniziale minuscola, essa funziona regolarmente, senza necessità quindi di usare un nome fittizio.