Scrivere una libreria esterna che chiama una funzione esterna puntata

Da Gambas-it.org - Wikipedia.

Una libreria esterna appositamente può essere scritta per utilizzare una funzione esterna puntata da un Puntatore.


Nel seguente esempio abbiamo un codice sorgente in linguaggio C, che chiameremo "sorgente_C.c", nel quale è presente la funzione che vogliamo utilizzare e che è puntata da un Puntatore a Funzione:

int Funzione_Puntata(int valore) {

  return valore + 1;

}

L'applicativo Gambas sarà invece il seguente:

Private Extern Chiamata_Funzione(vI As Integer) As Integer In "/tmp/libadhoc"


Public Sub Main()

 Dim i As Integer = 999

' Va a generare la libreria esterna condivisa da noi scritta:
 Creaso()

 i = Chiamata_Funzione(i)

 Print "Valore ritornato dalla funzione-puntatore: "; i

End


Private Procedure Creaso()

 File.Save("/tmp/libadhoc.c", "#include \"/percorso/del/file/sorgente_C.c\"\n\n" &
                              "int (*po)(int);\n\n" &
                              "int Chiamata_Funzione(int i) {\n\n" &
                              "   po = Funzione_Puntata;   //inizializzazione del Puntatore a funzione\n\n" &
                              "   return (*po)(i);\n}")

 Shell "gcc -o /tmp/libadhoc.so /tmp/libadhoc.c -shared  -fPIC" Wait

End

Uso della sola libreria esterna condivisa .so

Il codice presente nel file sorgente_C.c dell'esempio precedente può anche essere più semplicemente contenuto nella sola libreria esterna condivisa .so, come segue:

Private Extern Chiamata_Funzione(vI As Integer) As Integer In "/tmp/libadhoc"


Public Sub Main()

 Dim i As Integer = 999

' Va a generare la libreria esterna condivisa da noi scritta:
 Creaso()
 
 i = Chiamata_Funzione(i)

 Print "Valore ritornato dalla funzione-puntatore: "; i

End


Private Procedure Creaso()

 File.Save("/tmp/libadhoc.c", "int (*po)(int);\n\n" &
                              "int Funzione_Puntata(int valore) {\n\n" &
                              "   return valore + 1;\n}\n\n" &
                              "int Chiamata_Funzione(int i) {\n" &
                              "   po = Funzione_Puntata;   //inizializzazione del Puntatore a funzione\n\n" &
                              "   return (*po)(i);\n}")

 Shell "gcc -o /tmp/libadhoc.so /tmp/libadhoc.c -shared  -fPIC" Wait

End


Uso del metodo System.GetExternSymbol()

E' possibile utilizzare anche il metodo .GetExternSymbol() della Classe System, come segue (poniamo tutto il codice C nella sola libreria esterna condivisa, che chiameremo libadhoc.so e che provvederemo a creare all'interno del codice stesso di Gambas):

Private Extern Chiamata_Funzione(po As Pointer, i As Integer) As Integer In "/tmp/libadhoc"


Public Sub Main()

 Dim p As Pointer
 Dim i As Integer
 
 Creaso()
 
 p = System.GetExternSymbol("/tmp/libadhoc", "Funzione_Puntata")

 i = Chiamata_Funzione(p, 99)
 
 Print i

End


Private Procedure Creaso()
 
' Salva il codice, scritto in C, della nostra libreria esterna condivisa:
 File.Save("/tmp/libadhoc.c", "int Funzione_Puntata(int valore) {\n" &
           "   return valore + 1;\n}\n\n" &
           "int Chiamata_Funzione(int (*p)(int), int i) {\n" &
           "   return (*p)(i);\n}")
 
' Genera la libreria esterna condivisa da noi scritta:
 Shell "gcc -o /tmp/libadhoc.so /tmp/libadhoc.c -shared -fPIC" Wait
 
End


Uso di una semplice variabile di tipo Puntatore

E' possibile utilizzare una semplice variabile di tipo Puntatore al posto del metodo .GetExternSymbol() appena sopra prima visto. A detta variabile di tipo Puntatore sarà assegnata la funzione, presente nella libreria esterna condivisa, da puntare.

Anche questa volta dobbiamo porre tutto il codice C nella sola libreria esterna condivisa, che chiameremo libadhoc.so e che provvederemo a creare all'interno del codice stesso di Gambas:

Library "/tmp/libadhoc" 

Private Extern Chiamata_Funzione(po As Pointer, i As Integer) As Integer
Private Extern Funzione_Puntata()


Public Sub Main()

 Dim p As Pointer
 Dim i As Integer
 
 Creaso()

 p = Funzione_Puntata

 i = Chiamata_Funzione(p, 99)
 
 Print i

End


Private Procedure Creaso()
 
' Salva il codice, scritto in C, della nostra libreria esterna condivisa:
 File.Save("/tmp/libadhoc.c", "int Funzione_Puntata(int valore) {\n" &
           "   return valore + 1;\n}\n\n" &
           "int Chiamata_Funzione(int (*p)(int), int i) {\n" &
           "   return (*p)(i);\n}")
 
' Genera la libreria esterna condivisa da noi scritta:
 Shell "gcc -o /tmp/libadhoc.so /tmp/libadhoc.c -shared -fPIC" Wait
 
End