Ottenere il puntatore direttamente ai dati associati a una Struttura

Da Gambas-it.org - Wikipedia.

Per ottenere l'indirizzo dei memoria dei dati associati a una Struttura [nota 1], si possono usare due modalità:

  • con la funzione "VarPtr()";
  • con il Metodo ".Data()" della Classe Object.

Uso della funzione "VarPtr()"

La funzione "VarPtr()" si utilizzerà con la variabile di tipo Struttura con la seguente sintassi:

VarPtr(Variabile_Struttura) As Pointer

V'è da sottolineare che la variabile di tipo Struttura andrà assolutamente dichiarata all'esterno delle routine, come globale, e preceduta dalla parola-chiave Struct:

Private variabile_struttura As Struct STRUTTURA

Il Puntatore alla variabile di tipo Struttura, ritornato dalla funzione "VarPtr()", punta all'indirizzo di memoria dei dati associati alla Struttura, ossia all'indirizzo di memoria del primo membro della Struttura. [nota 1]

Esempio:

Public Struct ABCDE
  a As Byte
  b As Short
  c As Integer
  d As Long
  e As String
End Struct

Private vrSt As Struct ABCDE


Public Sub Main()

  Dim p1, p2 As Pointer

  With vrSt
    .a = 9
    .b = 999
    .c = 999999
    .d = 999999999
    .e = "testo"
  End With


' Ottiene il "Puntatore" alla variabile di tipo "Struttura":
  p1 = VarPtr(vrSt)

' Dereferenzia il "Puntatore" mediante l'apposita funzione nativa di Gambas per leggere un Byte, spostandosi direttamente al numero d'indice "24" dell'area allocata appartenente alla Struttura:
  Print Byte@(p1)

' Per leggere il valore del membro di tipo "Short", usa l'apposita funzione nativa di Gambas, spostandosi al numero d'indice "2" dell'area allocata, e non "1", per rispettare la regola dell'Allineamento dei dati:
  Print Short@(p1 + SizeOf(gb.Short))

' Per leggere il valore del membro di tipo "Integer", usa l'apposita funzione nativa di Gambas, spostandosi al numero d'indice "4" dell'area allocata:
  Print Integer@(p1 + SizeOf(gb.Integer))

' Per leggere il valore del membro di tipo "Long", usa l'apposita funzione nativa di Gambas, spostandosi al numero d'indice "8" dell'area allocata:
  Print Long@(p1 + SizeOf(gb.Long))
 
' Se un membro della "Struttura" è di tipo "Stringa", allora la corrispondente area di memoria contiene un indirizzo di memoria di una "Stringa". In tal caso detto indirizzo di memoria dovrà essere innanzitutto opportunamente dereferenziato con l'apposita funzione nativa di Gambas, adatta per dereferenziare i "Puntatori":
  p2 = Pointer@(p1 + 16)
' Quindi dereferenzia il "Puntatore" ottenuto, per ottenere la stringa:
  Print String@(p2)

End

Si può usare anche un ciclo per l'intera dimensione della "Struttura", mostrando così tutta area di memoria della "Struttura":

 Dim i As Integer
 ......
 ......
 For i = 0 To Object.SizeOf(vrSt) - 1
   If i = Object.SizeOf(vrSt) - 8 Then
     Print String@(p2)
     Break
   Endif
   Print i, Hex(Byte@(p1 + i), 2)
 Next


Uso del Metodo ".Data()" della Classe Object

Il Metodo ".Data()" della Classe Object riporta la seguente sintassi:

Object.Data(Oggetto As Object) As Pointer

In particolare tale Metodo ritorna l'indirizzo di memoria del primo membro della Struttura.
Per ottenere gli indirizzi di memoria dei restanti membri della Struttura, sarà necessario adottare l'aritmetica dei Puntatori avendo riguardo agli eventuali salti dovuti agli allineamenti di byte in memoria.
Pertanto, per ottenere il valore contenuto in un membro della Struttura si dovrà dereferenziare il Puntatore ritornato dal Metodo "Object.Data()".


Note

[1] Vedere anche la seguente pagina: Ottenere il puntatore di una variabile di tipo Struttura