Write ()

Da Gambas-it.org - Wikipedia.

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_WRONLY)

' Asegna alla variabile "i" il vaore da scrivere nel file:
 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


Uso della funzione esterna "write()" con la funzione nativa "Open" di Gambas

Nell'esempio precedente abbiamo visto la funzione esterna "write()" scrivere un dato in un file aperto con la funzione esterna open()" di C.
Nel presente paragrafo vedremo sostituire la funzione esterna "open()" di C con la funzione nativa di Gambas "Open", per aprire in scrittura un file. Successivamente all'apertura del file bisognerà 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" di Gambas.

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

' Asegna alla variabile "i" il vaore da scrivere nel file:
 i = 100
 p = VarPtr(i)

 l = write_C(fl.Handle, p, SizeOf(TypeOf(i)))
 If l == 0 Then Error.Raise("Impossibile scrivere nel file !")
 
 fl.Close

End


Usare la funzione "write() di C con la funzione "fopen() di C

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(__stream 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")

' Asegna alla variabile "i" il vaore da scrivere nel file:
 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.


Riferimenti