Passare un`area riservata di memoria ad una funzione esterna

Da Gambas-it.org - Wikipedia.

Considereremo due casi: il caso in cui si debba passare ad una funzione semplicemente un'area allocata di memoria, affinché quella la riempi; ed il caso in cui, dopo aver allocato un'area di memoria, si debba riempirla, ed infine così passarla ad una funzione.


Passare semplicemente un'area allocata di memoria

Qualora una funzione esterna preveda che le si passi una Struttura, o comunque un'altra area allocata di memoria, per mezzo di un puntatore a quest'area riservata, affinché questa venga riempita dalla funzione medesima magari con due o più valori, che possono essere anche di tipo diverso; e che successivamente si debba procedere alla dereferenziazione, procederemo nel modo seguente:

1) allocheremo una sufficiente quantità di memoria, che sarà puntata da una variabile di tipo puntatore;

2) passeremo tale puntatore alla funzione esterna che provvederà a riempirla;

3) procederemo alla dereferenziazione. Se il valore restituito dalla funzione esterna è unico, ossia il suo indirizzo coincide con la struttura (o classe) stessa, e dunque o coincide con la parte iniziale dell'area, allora potranno essere utilizzate le consuete funzioni di dereferenziazione (Byte@(), Int@(), etc). Se invece I valori passati dalla funzione esterna sono più di uno, essi occuperanno in modo coerente con il tipo di valore, rappresentato da ciascuno, l'area di memoria da noi riservata e puntata dalla variabile puntatore, e andranno dereferenziati mediante l'uso dei Memory-Stream.


Vediamo un esempio:

Private p As Pointer

' Dichiariamo la funzione esterna dalla quale riceveremo il puntatore alla "Struttura" esterna:
Private Extern funzione_esterna(pEst As Pointer)

Public Sub Button1_Click()

 Dim ms As Stream
 Dim by As Byte

' Ci riserviamo un'area sufficiente di memoria:
   p = Alloc(quantità_di memoria_da_allocare)

' Passiamo alla funzione esterna il puntatore all'area allocata,
' affinché essa gli assegni il valore dell'indirizzo di memoria puntato:
   funzione_esterna(p)

' Andiamo a dereferenziare il pointer:
   ms = Memory p For Read

' Andiamo a leggere e mostrare in console i dati:
   While Not Eof(ms)
     Read #pS, by
     Print by
   Wend

End


Public Sub Form_Close()

' In fase di chiusura del programma, si procederà anche a "de-allocare",
' cioè a liberare, la porzione di memoria precedentemente allocata:
   Free(p)

End


Riempire un'area allocata di memoria e successivamente passarla ad una funzione

In quest'altro caso viene richiesto di allocare un'area di memoria, e successivamente di riempirla con tipi di valori che occupino ciascuno un ben determinato numero di byte all'interno di detta area riservata. Una volta riempita, come previsto, si passerà alla funzione.


Procederemo generalmente come segue:

1) Si punterà all'area riservata di memoria con una variabile di tipo puntatore;
2) si riempirà l'area con valori del tipo coerente a quelli richesti.;
3) si riempirà l'area di momoria mediente i Memory-Stream, creando dal puntatore una variabile di tipo Stream. Solo usando i Memory-Stream potremo con Gambas riempire un'area di memoria riservata (ossia scriverci dentro) con tipi di dati determinati, e passarla infine ad una funzione (non solo esterna, ma anche interna);
4) si passerà alla funzione la variabile Stream.


Come esempio pratico poniamo il caso di voler riportare in Gambas il seguente codice scritto in C, nel quale la funzione, alla quale deve essere passata l'area riservata di memoria, preveda come parametro, appunto, che venga passata una variabile di tipo puntatore che punta a quell'area riservata:

 unsigned char *data;

/* Viene allocata un'area di memoria */
 data = (unsigned char *)malloc(1024);

/* ...qui avviene il riempimento dell'area riservata con i valori prescritti */
  ......
  ......
  ......etc

/* Quindi viene passato alla funzione il puntatore all'area riempita */
  funz(data);

In Gambas avremo:

Private Extern funz(param As Stream)   ' Nel C era previsto un Pointer, in Gambas prevediamo uno Stream per poter passare l'area allocata riempita !

Public Sub Button1_Click()

 Dim dati As Pointer
 Dim datiStr As Stream
 Dim v1 As ...' tipo di valore in base a quello previsto nel codice C
 Dim v2 As ...' tipo di valore in base a quello previsto nel codice C
 ...etc...

 dati = Alloc(1024)
 
' Dal puntatore creiamo una variabile di tipo "Stream" in "scrittura":
 datiStr = Memory dati For Write

' Scriviamo nella variabile di tipo Stream:
  Write #datiStr, v1 As ...' tipo di valore in base a quello previsto nel codice C
  Write #datiStr, v2 As ...' tipo di valore in base a quello previsto nel codice C
  ...etc...

' Passiamo infine alla funzione esterna la variabile di tipo "Stream",
' che punta all'area riservata di memoria, ora riempita con i previsti valori:
   funz(datiStr)

End