Scrivere una libreria esterna che ritorna una Struttura

Da Gambas-it.org - Wikipedia.

Di seguito mostriamo alcuni esempi, nei quali la funzione esterna della libreria in C ritorna per valore una Struttura.

1° esempio

Public Struct Nome_Struttura   ' Dichiara una "Struttura" simile a quella dichiarata nel codice C
  a As Integer
  b As Pointer
End Struct

Private Extern prova() As Nome_Struttura In "/tmp/libprovaC"


Public Sub Main()

 Dim nst As New Nome_Struttura

 Creaso()
 
 nst = prova()

 Print nst.a, String@(nst.b)

End

Private Procedure Creaso()

 File.Save("/tmp/libprovaC.c", "struct nome_struttura {\n" &
                               "  int a;\n" &
                               "  char *b;\n};\n\n" &
                               "struct nome_struttura variabile_struttura;\n\n" &
                               "struct nome_struttura *prova() {\n\n" &
                               "   variabile_struttura.a = 99;    // Assegna i valori ai membri della Struttura\n" &
                               "   variabile_struttura.b = \"prova\";\n\n" &
                               "   return &variabile_struttura;\n\n}")
 
 Shell "gcc -o /tmp/libprovaC.so /tmp/libprovaC.c -shared -fPIC" Wait

End


2° esempio

In quest'altro esempio nel codice Gambas dell'applicativo non è dichiarata ed usata una Struttura simile a quella dichiarata in C, ma si opererà sul Puntatore ottenuto, contenente l'indirizzo di memeoria della Struttura del codice C, per estrarre i valori dei membri della Struttura.

Private Extern Prova() As Pointer In "/tmp/libreria_C"


Public Sub Main()

 Dim p, po As Pointer
 Dim st, re As Stream
 Dim j, b As Byte
 
 Creaso()
 
 p = Prova()
 If p == 0 Then Error.Raise("Puntatore NULLO !")
  
 st = Memory p For Read
 Print Read #st As Integer

' Posizioniamo il puntatore interno del flusso al byte di indice 8 per gli effetti dell'allineamento, dato che il prossimo valore occupa 8 byte (è un "Puntatore"= 0, 8, 16, 24, 32, ...etc):
 Seek #st, 8
 Read #st, po
 re = Memory po For Read
 For j = 0 To 3
   Read #re, b
   Print Hex(b, 2)
 Next
 re.Close

 Print Read #st As Short

 st.Close

End

Private Procedure Creaso()

 File.Save("/tmp/libreria_C.c", "#include <stdlib.h>\n" &
                                "struct AAA {\n" &
                                "  int i;\n" &
                                "  char * p;\n" &
                                "  short s;\n};\n\n" &
                                "struct AAA a;\n\n" &
                                "struct AAA * Prova() {\n\n" &
                                "   a.i = 444444;\n\n" &
                                "   a.p = (char *) malloc(4);\n" &
                                "   a.p[0] = 0x0A;\n" &
                                "   a.p[1] = 0x0B;\n" &
                                "   a.p[2] = 0x0C;\n" &
                                "   a.p[3] = 0x0D;\n\n" &
                                "   a.s = 0x0400;\n\n" &
                                "   return &a;\n\n}")

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

End


Caso in cui la funzione esterna ritorna una Struttura avente tra i suoi membri uno o più vettori di tipo "char"

Se un membro della Struttura, presente nella libreria esterna in C, è dichiarato come un vettore di tipo "char", allora il corrispondente membro della rispettiva Struttura in Gambas potrà essere dichiarato come vettore di tipo Byte[]. I valori di tale vettore di tipo Byte[] potranno essere recuperati, ai fini della ricomposizione dell'intera stringa di caratteri, con il metodo .ToString().

Public Struct Nome_Struttura
  b[4] As Byte
  a As Integer
End Struct

Private Extern prova() As Nome_Struttura In "/tmp/libprovaC"


Public Sub Main()

 Dim nst As New Nome_Struttura

 Creaso()

 nst = prova()

 Print nst.b.ToString()
 Print nst.a

End

Private Procedure Creaso()

 File.Save("/tmp/libprovaC.c", "struct nome_struttura {\n" &
                               "  char b[4];\n" &
                               "  int a;\n};\n\n" &
                               "struct nome_struttura variabile_struttura;\n\n" &
                               "struct nome_struttura *prova() {\n\n" &
                               "  variabile_struttura.b[0] = 'p';   //assegna un carattere per ciascun elemento del vettore di tipo \"chr\"\n" &
                               "  variabile_struttura.b[1] = 'e';\n" &
                               "  variabile_struttura.b[2] = 'r';\n" &
                               "  variabile_struttura.b[3] = 'a';\n\n" &
                               "  variabile_struttura.a = 99;\n\n" &
                               "  return &variabile_struttura;      // ritorna l'indirizzo di \"variabile_struttura\"\n\n};")
                                

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

End