Differenze tra le versioni di "Utilizzare il metodo 'System.GetExternSymbol()' per richiamare funzioni esterne di librerie condivise"

Da Gambas-it.org - Wikipedia.
(Creata pagina con "E' possibile richiamare funzioni esterne di librerie condivise ''.so'' anche senza l'uso di ''Extern'', ma mediante il metodo ".GetExternSymbol()" della Classe ''System'' . I...")
 
 
Riga 1: Riga 1:
E' possibile richiamare funzioni esterne di librerie condivise ''.so'' anche senza l'uso di ''Extern'', ma mediante il metodo ".GetExternSymbol()" della Classe ''System'' .
+
E' possibile richiamare funzioni esterne di librerie condivise ''.so'' anche senza l'uso di ''Extern'', ma mediante il Metodo ".GetExternSymbol()" della Classe ''System'' .
  
 
In tal caso la procedura è più complessa. Infatti, poiché si farà uso di un [[Scrivere_una_libreria_esterna_che_chiama_una_funzione_esterna_puntata|puntatore alla funzione esterna]] da invocare ed utilizzare, sarà necessario creare una nostra apposita libreria ''ad hoc'', nella quale si chiamerà effettivamente la funzione esterna.
 
In tal caso la procedura è più complessa. Infatti, poiché si farà uso di un [[Scrivere_una_libreria_esterna_che_chiama_una_funzione_esterna_puntata|puntatore alla funzione esterna]] da invocare ed utilizzare, sarà necessario creare una nostra apposita libreria ''ad hoc'', nella quale si chiamerà effettivamente la funzione esterna.
  
Mostriamo di seguito un esempio, nel quale supponiamo di dover invocare una funzione che svolge una semplice moltiplicazione utilizzando il valore ricevuto dal nostro progetto Gambas. Tale funzione esterna, che chiameremo ''FunzioneEsterna()'', è contenuta in una libreria dinamica esterna, che chiameremo ''LibreriaEsterna.c'', il cui semplice codice sorgente in C è il seguente:  <SUP>&#091;[[#Note|Nota 1]]&#093;</sup>
+
Mostriamo di seguito un esempio, nel quale supponiamo di dover invocare una funzione che svolge una semplice moltiplicazione utilizzando il valore ricevuto dal nostro progetto Gambas. Tale funzione esterna, che chiameremo "FunzioneEsterna()", è contenuta in una libreria esterna, il cui file sorgente chiameremo LibreriaEsterna.c, il cui semplice codice sorgente in C è il seguente:  <SUP>&#091;[[#Note|nota 1]]&#093;</sup>
 
  int FunzioneEsterna(int i) {
 
  int FunzioneEsterna(int i) {
 
   
 
   
Riga 11: Riga 11:
 
   
 
   
 
  }
 
  }
Il codice del progetto Gambas sarà il seguente:
+
Il codice del progetto Gambas invece sarà il seguente:
 
  Private Extern Invoca_Funzione(fun_est As Pointer, valore As Integer) As Integer In "/tmp/Libadhoc"
 
  Private Extern Invoca_Funzione(fun_est As Pointer, valore As Integer) As Integer In "/tmp/Libadhoc"
 
   
 
   
 
   
 
   
  '''Public''' Sub Main()
+
  Public Sub Main()
 
   
 
   
 
   Dim libreriaso As String = "/tmp/LibreriaEsterna.so"
 
   Dim libreriaso As String = "/tmp/LibreriaEsterna.so"
Riga 34: Riga 34:
 
   Print "Risultato: "; ris
 
   Print "Risultato: "; ris
 
   
 
   
  '''End'''
+
  End
 
   
 
   
  '''Private''' Procedure CreaLibSoAdHoc()
+
  Private Procedure CreaLibSoAdHoc()
 
   
 
   
 
  <FONT Color=gray>' ''Imposta il codice C della libreria ad hoc da creare:''</font>
 
  <FONT Color=gray>' ''Imposta il codice C della libreria ad hoc da creare:''</font>
Riga 44: Riga 44:
 
   Shell "gcc -o /tmp/Libadhoc.so /tmp/Libadhoc.c -shared" Wait
 
   Shell "gcc -o /tmp/Libadhoc.so /tmp/Libadhoc.c -shared" Wait
 
    
 
    
  '''End'''
+
  End
 
Come si è potuto notare, la parola chiave ''Extern'' è stata comunque utilizzata, anche se però non direttamente per dichiarare la vera funzione esterna da chiamare e da utilizzare (ossia quella contenuta in ''LibreriaEsterna.c''), ma solo per dichiarare la funzione esterna della libreria ''ad hoc'' da noi creata che provvede ad invocare ed utilizzare la predetta funzione esterna di ''LibreriaEsterna.c''.
 
Come si è potuto notare, la parola chiave ''Extern'' è stata comunque utilizzata, anche se però non direttamente per dichiarare la vera funzione esterna da chiamare e da utilizzare (ossia quella contenuta in ''LibreriaEsterna.c''), ma solo per dichiarare la funzione esterna della libreria ''ad hoc'' da noi creata che provvede ad invocare ed utilizzare la predetta funzione esterna di ''LibreriaEsterna.c''.
  
  
 
====Esempio con una funzione esterna della libreria standard di C====
 
====Esempio con una funzione esterna della libreria standard di C====
In quest'altro esempio utilizzeremo in modo semplice la funzione esterna ''printf( )'', dichiarata nel file header "''/usr/include/stdio.h''".
+
In quest'altro esempio utilizzeremo in modo semplice la funzione esterna "'printf()", dichiarata nel file header ''/usr/include/stdio.h''.
 
  Private Extern Invoca_Funzione(FunzioneEsternaPuntata As Pointer) As Integer In "/tmp/libso"
 
  Private Extern Invoca_Funzione(FunzioneEsternaPuntata As Pointer) As Integer In "/tmp/libso"
 
   
 
   
 
   
 
   
  '''Public''' Sub Main()
+
  Public Sub Main()
 
    
 
    
 
   Dim p As Pointer
 
   Dim p As Pointer
Riga 66: Riga 66:
 
   Invoca_Funzione(p)
 
   Invoca_Funzione(p)
 
    
 
    
  '''End'''
+
  End
 
   
 
   
  '''Private''' Procedure CreaSo()
+
  Private Procedure CreaSo()
 
    
 
    
 
  <FONT Color=gray>' ''Scrive e salva il sorgente della nostra libreria esterna ad hoc dinamica condivisa per la chiamata della funzione puntata "printf()":''</font>
 
  <FONT Color=gray>' ''Scrive e salva il sorgente della nostra libreria esterna ad hoc dinamica condivisa per la chiamata della funzione puntata "printf()":''</font>
Riga 77: Riga 77:
 
   Shell "gcc -o /tmp/libso.so /tmp/libso.c -shared -fPIC" Wait
 
   Shell "gcc -o /tmp/libso.so /tmp/libso.c -shared -fPIC" Wait
 
    
 
    
  '''End'''
+
  End
 
Di seguito vediamo un esempio simile al precedente, ma ora passando dei valori agli argomenti della funzione esterna "printf()".
 
Di seguito vediamo un esempio simile al precedente, ma ora passando dei valori agli argomenti della funzione esterna "printf()".
 
  Private Extern Invoca_Funzione(FunzioneEsternaPuntata As Pointer, st As String) As Integer In "/tmp/libso"
 
  Private Extern Invoca_Funzione(FunzioneEsternaPuntata As Pointer, st As String) As Integer In "/tmp/libso"
 
   
 
   
 
   
 
   
  '''Public''' Sub Main()
+
  Public Sub Main()
 
    
 
    
 
   Dim p As Pointer
 
   Dim p As Pointer
Riga 95: Riga 95:
 
   Invoca_Funzione(p, "abcdefg")
 
   Invoca_Funzione(p, "abcdefg")
 
    
 
    
  '''End'''
+
  End
 
   
 
   
  '''Private''' Procedure CreaSo()
+
  Private Procedure CreaSo()
 
    
 
    
 
  <FONT Color=gray>' ''Nella funzione puntata vanno descritti i parametri previsti dalla funzione esterna "printf()":''</font>
 
  <FONT Color=gray>' ''Nella funzione puntata vanno descritti i parametri previsti dalla funzione esterna "printf()":''</font>
Riga 106: Riga 106:
 
   Shell "gcc -o /tmp/libso.so /tmp/libso.c -shared -fPIC" Wait
 
   Shell "gcc -o /tmp/libso.so /tmp/libso.c -shared -fPIC" Wait
 
    
 
    
  '''End'''
+
  End
  
  
  
 
=Note=
 
=Note=
Se si intende provare l'esempio pratico esposto in questa pagina, il codice sorgente della libreria esterna ''LibreriaEsterna.c'' va compilato nel terminale con la seguente riga di comando:
+
[1] Se si intende provare l'esempio pratico esposto in questa pagina, il codice sorgente della libreria esterna ''LibreriaEsterna.c'' va compilato nel terminale con la seguente riga di comando:
 
  ~ $ gcc -o /tmp/LibreriaEsterna.so /tmp/LibreriaEsterna.c -shared
 
  ~ $ gcc -o /tmp/LibreriaEsterna.so /tmp/LibreriaEsterna.c -shared

Versione attuale delle 09:57, 11 giu 2023

E' possibile richiamare funzioni esterne di librerie condivise .so anche senza l'uso di Extern, ma mediante il Metodo ".GetExternSymbol()" della Classe System .

In tal caso la procedura è più complessa. Infatti, poiché si farà uso di un puntatore alla funzione esterna da invocare ed utilizzare, sarà necessario creare una nostra apposita libreria ad hoc, nella quale si chiamerà effettivamente la funzione esterna.

Mostriamo di seguito un esempio, nel quale supponiamo di dover invocare una funzione che svolge una semplice moltiplicazione utilizzando il valore ricevuto dal nostro progetto Gambas. Tale funzione esterna, che chiameremo "FunzioneEsterna()", è contenuta in una libreria esterna, il cui file sorgente chiameremo LibreriaEsterna.c, il cui semplice codice sorgente in C è il seguente: [nota 1]

int FunzioneEsterna(int i) {

   i = i * 10;

   return i;

}

Il codice del progetto Gambas invece sarà il seguente:

Private Extern Invoca_Funzione(fun_est As Pointer, valore As Integer) As Integer In "/tmp/Libadhoc"


Public Sub Main()

 Dim libreriaso As String = "/tmp/LibreriaEsterna.so"
 Dim NomeFunzione As String = "FunzioneEsterna"
 Dim p As Pointer
 Dim ris As Integer

' Carica la funzione esportata da 'mialibreria.so':
 p = System.GetExternSymbol(Replace(libreriaso, ".so", Null), NomeFunzione)
 If p == 0 Then Error.Raise("Impossibile caricare la funzione della libreria esterna !")

' Crea un'apposita libreria condivisa esterna ".so", il cui file del codice sorgente sarà chiamato "Libadhoc.c":
 CreaLibSoAdHoc()

' Invoca la 'FunzioneEsterna' e le passa un Intero:
 ris = Invoca_Funzione(FunzioneEsterna, 44)

 Print "Risultato: "; ris

End

Private Procedure CreaLibSoAdHoc()

' Imposta il codice C della libreria ad hoc da creare:
 File.Save("/tmp/Libadhoc.c", "int Invoca_Funzione(int (*FunzioneEsterna)(int), int r) {\n" &
                              "   return FunzioneEsterna(r); \n}")

 Shell "gcc -o /tmp/Libadhoc.so /tmp/Libadhoc.c -shared" Wait
 
End

Come si è potuto notare, la parola chiave Extern è stata comunque utilizzata, anche se però non direttamente per dichiarare la vera funzione esterna da chiamare e da utilizzare (ossia quella contenuta in LibreriaEsterna.c), ma solo per dichiarare la funzione esterna della libreria ad hoc da noi creata che provvede ad invocare ed utilizzare la predetta funzione esterna di LibreriaEsterna.c.


Esempio con una funzione esterna della libreria standard di C

In quest'altro esempio utilizzeremo in modo semplice la funzione esterna "'printf()", dichiarata nel file header /usr/include/stdio.h.

Private Extern Invoca_Funzione(FunzioneEsternaPuntata As Pointer) As Integer In "/tmp/libso"


Public Sub Main()
 
 Dim p As Pointer
 
' Invoca la procedura per scrivere il sorgente e per creare la libreria dinamica condivisa:
 CreaSo()
 
' Richiama mediante System.GetExternSymbol() la funzione "printf()" della libreria standard di C:
 p = System.GetExternSymbol("libc:6", "printf")
  
' Invoca la funzione esterna da noi creata e le passiamo il Puntatore alla funzione esterna "printf()":
 Invoca_Funzione(p)
 
End

Private Procedure CreaSo()
 
' Scrive e salva il sorgente della nostra libreria esterna ad hoc dinamica condivisa per la chiamata della funzione puntata "printf()":
 File.Save("/tmp/libso.c", "void Invoca_Funzione(int (*FunzioneEsternaPuntata)(const char *__restrict __format)) {\n\n" &
            "   FunzioneEsternaPuntata(\"abcdefg\");\n\n}")
  
' Crea la nostra libreria esterna dinamica condivisa ad hoc:
 Shell "gcc -o /tmp/libso.so /tmp/libso.c -shared -fPIC" Wait
  
End

Di seguito vediamo un esempio simile al precedente, ma ora passando dei valori agli argomenti della funzione esterna "printf()".

Private Extern Invoca_Funzione(FunzioneEsternaPuntata As Pointer, st As String) As Integer In "/tmp/libso"


Public Sub Main()
 
 Dim p As Pointer
 
' Invoca la procedura per scrivere il sorgente e per creare la libreria dinamica condivisa:
 CreaSo()
 
' Richiama mediante System.GetExternSymbol() la funzione "printf()" della libreria standard di C:
 p = System.GetExternSymbol("libc:6", "printf")
  
' Invoca la funzione esterna da noi creata e le passiamo il Puntatore alla funzione esterna "printf()":
 Invoca_Funzione(p, "abcdefg")
 
End

Private Procedure CreaSo()
 
' Nella funzione puntata vanno descritti i parametri previsti dalla funzione esterna "printf()":
 File.Save("/tmp/libso.c", "void Invoca_Funzione(int (*FunzioneEsternaPuntata)(const char *__restrict __format, char * stringa), char * st) {\n\n" &
            "   FunzioneEsternaPuntata(\"%s\\n\", st); \n\n}")
  
' Crea la nostra libreria esterna dinamica condivisa ad hoc:
 Shell "gcc -o /tmp/libso.so /tmp/libso.c -shared -fPIC" Wait
  
End


Note

[1] Se si intende provare l'esempio pratico esposto in questa pagina, il codice sorgente della libreria esterna LibreriaEsterna.c va compilato nel terminale con la seguente riga di comando:

~ $ gcc -o /tmp/LibreriaEsterna.so /tmp/LibreriaEsterna.c -shared