Differenze tra le versioni di "Ottenere l'indirizzo e il valore di una Costante e di una variabile globale situate in una libreria condivisa"

Da Gambas-it.org - Wikipedia.
(Creata pagina con "Il Metodo ".GetExternSymbol()" della Classe ''System'' ritorna un ''Puntatore'' all'indirizzo di un simbolo situato in una libreria condivisa. Tale simbolo deve essere una <SP...")
 
 
Riga 23: Riga 23:
 
   
 
   
 
   
 
   
  '''Public''' Sub Main()
+
  Public Sub Main()
 
    
 
    
 
   Dim p As Pointer
 
   Dim p As Pointer
Riga 47: Riga 47:
 
   Print Int@(p)
 
   Print Int@(p)
 
   
 
   
  '''End'''
+
  End
  
  
Riga 56: Riga 56:
 
  System.GetExternSymbol("<FONT color=gray>''/percorso/della/libreria/condivisa''</font>", "<FONT color=B22222>variabile_Struttura</font>") As Pointer
 
  System.GetExternSymbol("<FONT color=gray>''/percorso/della/libreria/condivisa''</font>", "<FONT color=B22222>variabile_Struttura</font>") As Pointer
  
===Dereferenziare il Pointer mediante la sua assegnazione alla variabile di tipo Struttura===
+
===Dereferenziare il Puntatore mediante la sua assegnazione alla variabile di tipo Struttura===
 
Successivamente all'assegnamento del ''Puntatore'' alla variabile di tipo ''Struttura'', presente in una libreria esterna, sarà possibile effettuare la dereferenziazione di tale ''Puntatore'' per ottenere i valori dei singoli campi della ''Struttura'' della libreria esterna.
 
Successivamente all'assegnamento del ''Puntatore'' alla variabile di tipo ''Struttura'', presente in una libreria esterna, sarà possibile effettuare la dereferenziazione di tale ''Puntatore'' per ottenere i valori dei singoli campi della ''Struttura'' della libreria esterna.
  
Si potrà ottenere ciò, procedendo in modo analogo a quanto descritto nella pagina di questa WIKI, relativa alla [[ Dereferenziare_senza_Memory-Stream_un_pointer_ad_una_Struttura,_passato_da_una_funzione_esterna|dereferenziazione senza Memory-Stream di un Pointer ad una ''Struttura'']].
+
Si potrà ottenere ciò, procedendo in modo analogo a quanto descritto nella pagina di questa WIKI, relativa alla [[Dereferenziare senza Memory-Stream un Puntatore ad una Struttura, passato da una funzione esterna|dereferenziazione senza Memory-Stream di un Puntatore ad una ''Struttura'']].
  
 
Innanzitutto si provvede a ricreare la ''Struttura'' esterna, come defininita nella libreria esterna. Quindi nel codice si invocherà innanzitutto la funzione estrena, e successivamente il Metodo "System.GetExternSymbol()", indicando nel secondo argomento - come già descritto - il nome della variabile di tipo ''Struttura'' presente nella libreria esterna. Nell'esempio che segue supponiamo che la ''Struttura'', presente nella libreria esterna, abbia tre campi che provvederemo quindi a riconfermarli nella copia della ''Struttura'' in Gambas:
 
Innanzitutto si provvede a ricreare la ''Struttura'' esterna, come defininita nella libreria esterna. Quindi nel codice si invocherà innanzitutto la funzione estrena, e successivamente il Metodo "System.GetExternSymbol()", indicando nel secondo argomento - come già descritto - il nome della variabile di tipo ''Struttura'' presente nella libreria esterna. Nell'esempio che segue supponiamo che la ''Struttura'', presente nella libreria esterna, abbia tre campi che provvederemo quindi a riconfermarli nella copia della ''Struttura'' in Gambas:
  '''Public''' Struct <FONT color=Blue>struttura</font>
+
  Public Struct <FONT color=Blue>struttura</font>
 
   a As Integer
 
   a As Integer
 
   b As Short
 
   b As Short
 
   c As Integer
 
   c As Integer
  '''End''' Struct
+
  End Struct
 
   
 
   
 
  Library "''nome_della_libreria_esterna:numero_versione''"
 
  Library "''nome_della_libreria_esterna:numero_versione''"
Riga 73: Riga 73:
 
   
 
   
 
   
 
   
  '''Public''' Sub main()
+
  Public Sub main()
 
   
 
   
 
   Dim <FONT color=Red>p</font> As Pointer
 
   Dim <FONT color=Red>p</font> As Pointer
Riga 92: Riga 92:
 
   End With
 
   End With
 
   
 
   
  '''End'''
+
  End
  
 
===Dereferenziare il Pointer mediante i ''Memory Stream''===
 
===Dereferenziare il Pointer mediante i ''Memory Stream''===
Riga 101: Riga 101:
 
   
 
   
 
   
 
   
  '''Public''' Sub Main()
+
  Public Sub Main()
 
   
 
   
 
   Dim p As Pointer
 
   Dim p As Pointer
Riga 129: Riga 129:
 
   st.Close
 
   st.Close
 
   
 
   
  '''End'''
+
  End
 
   
 
   
  '''Private''' Procedure Creaso()
+
   
 +
Private Procedure Creaso()
 
    
 
    
 
   File.Save("/tmp/libreria.c", "struct STRUTTURA {\n" &
 
   File.Save("/tmp/libreria.c", "struct STRUTTURA {\n" &
Riga 146: Riga 147:
 
   Shell "gcc -o /tmp/libreria.so /tmp/libreria.c -shared -fPIC" Wait
 
   Shell "gcc -o /tmp/libreria.so /tmp/libreria.c -shared -fPIC" Wait
 
    
 
    
  '''End'''
+
  End

Versione attuale delle 09:51, 5 ago 2023

Il Metodo ".GetExternSymbol()" della Classe System ritorna un Puntatore all'indirizzo di un simbolo situato in una libreria condivisa. Tale simbolo deve essere una variabile Globale o una Costante "cost". Non funziona invece usando la Direttiva #define.
La variabile globale o la Costante può, dunque essere di tipo numerica (Int, Double, Long), ma anche di tipo Puntatore e di tipo Struttura.

Ottenuto l'indirizzo della variabile globale o della Costante, presente nella libreria condivisa, sarà possibile dunque dereferenziare successivamente il Puntatore per ricavare il valore assegnato a quelle risorse.
Tale funzione consente, così, di ricavare il valore di una Costante o di una variabile - purché globale -, anche se la libreria che la contiene non prevede esplicitamente, in modo codificato, il ritorno del suo valore.

Va precisato che la libreria esterna deve essere individuata esclusivamente con il suo semplice nome, privo dell'estensione ".so" e dell'eventuale numero di versione della libreria.


Ottenere l'indirizzo di una Costante, di una variabile globale istanziata e di un'altra non istanziata


Poniamo il caso che la libreria condivisa .so contenga il seguente breve codice scritto in linguaggio C:

const int COSTANTE = 111;
int variabile_globale_istanziata = 222;
int variabile_globale_NON_istanziata;

void funzioneEsterna() {

  variabile_globale_NON_istanziata = 333;

}

e che il codice Gambas sia il seguente:

Private Extern funzioneEsterna() In "/percorso/della/libreria/condivisa"


Public Sub Main()
 
 Dim p As Pointer

' Invoca la funzione esterna, presente nella libreria condivisa, affinché la "variabile_globale_NON_istanziata" assuma il valore numerico previsto:
 funzioneEsterna()

' Usa il Metodo "System.GetExternSymbol()" per ottenere un Puntatore alla Costante "COSTANTE" presente nella libreria condivisa indicata nel primo argomento del predetto Metodo della Classe "System".
' RICORDARE che la libreria esterna deve essere individuata esclusivamente con il suo semplice nome, privo dell'estensione ".so" e dell'eventuale numero di versione della libreria.
 p = System.GetExternSymbol("/percorso/della/libreria/condivisa", "COSTANTE")

' Dereferenzia il Puntatore per ottenere il valore definito della Costante "COASTANTE", e lo mostriamo in console:
 Print Int@(p)

' Ora fa la stessa operazione con la "variabile_globale_istanziata":
 p = System.GetExternSymbol("/percorso/della/libreria/condivisa", "variabile_globale_istanziata")

 Print Int@(p)

 ' Infine con la "variabile_globale_NON_istanziata":
 p = System.GetExternSymbol("/percorso/della/libreria/condivisa", "variabile_globale_NON_istanziata")

 Print Int@(p)

End


Ottenere l'indirizzo di una variabile di tipo Struttura e sua dereferenziazione

Come già detto, è possibile ottenere il puntatore di una variabile di tipo Struttura, presente in una libreria esterna, ossia l'indirizzo di memoria di detta variabile.

Nel secondo argomento si dovrà scrivere la variabile (che ovviamente dovrà essere Globale) della Struttura:

System.GetExternSymbol("/percorso/della/libreria/condivisa", "variabile_Struttura") As Pointer

Dereferenziare il Puntatore mediante la sua assegnazione alla variabile di tipo Struttura

Successivamente all'assegnamento del Puntatore alla variabile di tipo Struttura, presente in una libreria esterna, sarà possibile effettuare la dereferenziazione di tale Puntatore per ottenere i valori dei singoli campi della Struttura della libreria esterna.

Si potrà ottenere ciò, procedendo in modo analogo a quanto descritto nella pagina di questa WIKI, relativa alla dereferenziazione senza Memory-Stream di un Puntatore ad una Struttura.

Innanzitutto si provvede a ricreare la Struttura esterna, come defininita nella libreria esterna. Quindi nel codice si invocherà innanzitutto la funzione estrena, e successivamente il Metodo "System.GetExternSymbol()", indicando nel secondo argomento - come già descritto - il nome della variabile di tipo Struttura presente nella libreria esterna. Nell'esempio che segue supponiamo che la Struttura, presente nella libreria esterna, abbia tre campi che provvederemo quindi a riconfermarli nella copia della Struttura in Gambas:

Public Struct struttura
  a As Integer
  b As Short
  c As Integer
End Struct

Library "nome_della_libreria_esterna:numero_versione"

Private Extern nome_della_Funzione_esterna(parametro_1, parametro_2, etc...)


Public Sub main()

 Dim p As Pointer
 Dim vs As Struttura

 nome_della_Funzione_esterna(par1, par2, etc)

' Otteniamo l'indirizzo di memoria della variabile della Struttura esterna:
 p = System.GetExternSymbol("/percorso/della/libreria/esterna", "variabile_Struttura_esterna")

' Dereferenziamo il "puntatore" ottenuto assegnandolo alla Struttura:
 vs = p

 With vs
   Print a
   Print b
   Print c
 End With

End

Dereferenziare il Pointer mediante i Memory Stream

Si potrà anche fare uso dei Memory Stream, per dereferenziare il Puntatore ottenuto dal Metodo "System.GetExternSymbol()".

Con il seguente esempio pratico, intendiamo raccogliere i valori finali dei tre membri della Struttura esterna:

Private Extern Prova(n As Integer) As Integer In "/tmp/libreria"


Public Sub Main()

 Dim p As Pointer
 Dim st As Stream
 Dim i, c As Integer
 Dim sh As Short
 
 Creaso()
 
 Prova(10)
 
 p = System.GetExternSymbol("/tmp/libreria", "vs")
 
 st = Memory p For Read Write
 
 Read #st, i
 Print i
 
 Read #st, sh
 Print sh
 
 Seek #st, 8
 Read #st, i
 Print i
 Print "---------"

 st.Close

End


Private Procedure Creaso()
 
 File.Save("/tmp/libreria.c", "struct STRUTTURA {\n" &
           "   int a;\n" &
           "   short b;\n" &
           "   int c;\n};\n\n" &
           "struct STRUTTURA vs;\n\n\n" &
           "int Prova(int i) {\n\n"
           "   vs.a = i + 2;\n" &
           "   vs.b = i * 2;\n" &
           "   vs.c = i - 2;\n\n" &
           "   return (0);\n\n}")
 
 Shell "gcc -o /tmp/libreria.so /tmp/libreria.c -shared -fPIC" Wait
 
End