Scrivere una libreria esterna alla quale viene passata una struttura

Da Gambas-it.org - Wikipedia.

Qualora si debba scrivere una propria libreria dinamica condivisa (.so) esterna, bisognerà tenere conto nel codice sorgente, scritto in C, della libreria esterna di quanto segue:
- si dovrà riprodurre una Struttura omogenea - in ordine alla tipologia dei suoi membri - alla Struttura di Gambas passata;
- il parametro della funzione della libreria esterna, che riceve la Struttura di Gambas passata, deve essere dichiarato come Puntatore alla Struttura definita nel codice sorgente C della libreria medesima.


Mostriamo un semplice esempio, nel quale verrà creato in linguaggio C il codice sorgente della nostra libreria dinamica condivisa esterna come di seguito:

struct STRUTTURA_C {
  double x;
  double y;
  double z;
};


double FunzioneEsterna(struct STRUTTURA_C * sC) {

  double d;
 
  d = sC->x + sC->y + sC->z;

  return d;
}


L'intero codice Gambas, nel quale provvederemo anche a scrivere e creare sia il codice sorgente in C della libreria esterna, sia il file .so della libreria medesima, sarà il seguente:

Public Struct STRUTTURA_Gambas
  x As Float
  Y As Float
  z As Float
End Struct

' double FunzioneEsterna(STRUTTURA_C * sC)
Public Extern FunzioneEsterna(struG As STRUTTURA_Gambas) As Float In "/tmp/lib_esterna"


Public Sub Main()

 Dim sG As New STRUTTURA_Gambas
 Dim ris As Float
 
  creaso()
  
  With sG
    .x = 1.111
    .Y = 2.222
    .z = 3.333
  End With
  
  ris = FunzioneEsterna(sG)
  
  Print ris
  
End


Private Procedure creaso()
 
 Dim s As String
 
  s = "struct STRUTTURA_C {" &
   "\n  double x;" &
   "\n  double y;" &
   "\n  double z;\n};" &
   "\n\n" &
   "\ndouble FunzioneEsterna(struct STRUTTURA_C *sC) {" &
   "\n\n  double d;" &
   "\n\n  d = sC->x + sC->y + sC->z;" &
   "\n\n  return d;\n}"
   
   File.Save("/tmp/lib_esterna.c", s)
 
   Shell "gcc -o /tmp/lib_esterna.so /tmp/lib_esterna.c -shared" Wait
  
End


Scrivere una libreria esterna alla quale viene passata una struttura e che ritorna una Struttura

Nel caso in cui la libreria esterna, da noi scritta in C, prevede il passaggio di una Struttura dal Programma principale Gambas ad una funzione della libreria esterna, con ritorno della medesima Struttura, detto ritorno potrà essere di due tipi:

  • ritorno mediante return;
  • ritorno per indirizzo.

In particolare nel ritorno della Struttura mediante return la Struttura, passata dal programma Gambas, sarà esplicito oggetto del ritorno mediante return alla fine della funzione esterna chiamata.


Mostriamo un esempio pratico, nel quale verranno mostrati entrambi i casi sopra esposti:

Public Struct STRUTTURA_Gambas
  x As Float
  Y As Float
  z As Float
End Struct

Library "/tmp/libesterna"

' struct STRUTTURA_C * FunzioneEsterna(STRUTTURA_C *p)
Public Extern FunzioneEsterna(struG As STRUTTURA_Gambas) As STRUTTURA_Gambas


Public Sub Main()

 Dim stG As New STRUTTURA_Gambas
 Dim rit As STRUTTURA_Gambas
 
  creaso()
    
  With stG
    .x = 1.111
    .Y = 2.222
    .z = 3.333
  End With
  
  rit = FunzioneEsterna(stG)
  
  With rit
    Print .x
    Print .Y
    Print .z
  End With
   
  With stG    ' Valori ritornati per indirizzo
    Print .x
    Print .Y
    Print .z
  End With
  
End


Private Procedure creaso()
 
 File.Save("/tmp/libesterna.c", "struct STRUTTURA_C {" &
           "double x\n;" &
           "double y\n;" &
           "double z;};" &
           "\n\n" &
           "\nstruct STRUTTURA_C * FunzioneEsterna(struct STRUTTURA_C *p) {" &
           "\n\n"
           "   p->x *= 11.11;\n" &
           "   p->y *= 22.22;\n" &
           "   p->z *= 33.33;\n" &
           "   return p;\n}")
  
  Shell "gcc -o /tmp/libesterna.so /tmp/libesterna.c -shared" Wait
  
End