Differenze tra le versioni di "Scrivere una libreria esterna che ritorna una Struttura"

Da Gambas-it.org - Wikipedia.
 
(9 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
Di seguito è mostrato un esempio, nel quale la funzione esterna della libreria in C ritorna una ''Struttura''.
+
Di seguito mostriamo alcuni esempi, nei quali la funzione esterna della libreria in C ritorna per "Valore" una ''Struttura''.
 +
==Utilizzare nella funzione esterna una variabile del tipo della Struttura==
  
 +
====1° esempio====
 +
Si può scrivere una libreria esterna condivisa ''ad hoc'', contenente una funzione che ritorna una ''Struttura'' per "valore". Se la funzione esterna, scritta in C nel programma Gambas, prevede il ritorno al codice Gambas del semplice tipo della ''Struttura'', la variabile del tipo della ''Struttura'', usata nel codice scritto in C, dovrà essere dichiarata come ''globale''.
 +
Public Struct Nome_Struttura  <FONT color=gray>' ''Dichiara una "Struttura" simile a quella dichiarata nel codice C''</font>
 +
  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;    <FONT color=blue>// Assegna i valori ai membri della Struttura</font>\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'''
  
Codice della libreria esterna in C:
+
====2° esempio====
  struct nome_struttura {
+
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 memoria della Struttura del codice C, per estrarre i valori dei membri della ''Struttura''.
  int a;
+
  Private Extern Prova() As Pointer In "/tmp/libreria_C"
  char *b;
+
   
  };
 
 
   
 
   
  struct nome_struttura variabile_struttura;</font>
+
  '''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
 
   
 
   
  struct nome_struttura *prova() {
+
  <FONT Color=gray>' ''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):''</font>
 +
  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
 
   
 
   
    variabile_struttura.a = 99;    <FONT color=blue>// Assegna i valori ai membri della Struttura</font>
+
  Print Read #st As Short
    variabile_struttura.b = "prova";
 
 
   
 
   
    return &variabile_struttura;
+
  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'''
  
Codice Gambas:
+
====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
 
  Public Struct Nome_Struttura
 +
  b[4] As Byte
 
   a As Integer
 
   a As Integer
  b As Pointer
 
 
  End Struct
 
  End Struct
 
   
 
   
+
  Private Extern prova() As Nome_Struttura In "/tmp/libprovaC"
Library "/tmp/libprovaC"
 
  Private Extern prova() As Nome_Struttura
 
 
   
 
   
 
   
 
   
Riga 35: Riga 109:
 
   
 
   
 
   Dim nst As New Nome_Struttura
 
   Dim nst As New Nome_Struttura
 
 
  nst = prova()
 
 
   
 
   
  Print nst.a, String@(nst.b)
+
  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';  <FONT color=blue>//assegna un carattere per ciascun elemento del vettore di tipo \"chr\"</font>\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;      <FONT color=blue>// ritorna l'indirizzo di \"variabile_struttura\"</font>\n\n};")
 +
                               
 +
 +
  Shell "gcc -o /tmp/libprovaC.so /tmp/libprovaC.c -shared -fPIC" Wait
 
   
 
   
 
  '''End'''
 
  '''End'''
 +
 +
 +
==Utilizzare nella funzione esterna un Puntatore alla Struttura==
 +
Se la funzione utilizza e ritorna un ''Puntatore'' alla ''Struttura'', allora detto ''Puntatore'' potrà essere dichiarato come locale.
 +
<BR>Si potrà fare uso - come appoggio - di una variabile del tipo della ''Struttura'', la quale permetterà al ''Puntatore'' di puntare alla sua area di memoria. In particolare al ''Puntatore'' alla ''Struttura'' si assegnerà l'indirizzo di memoria della variabile d'appoggio del tipo della ''Struttura''.
 +
Public Struct Struttura  ' Dichiara una "Struttura" simile a quella dichiarata nel codice C
 +
  a As Integer
 +
  b As Pointer
 +
End Struct
 +
 +
Private Extern prova() As Struttura In "/tmp/libprovaC"
 +
 +
 +
Public Sub Main()
 +
 +
  Dim st As New Struttura
 +
 +
  Creaso()
 +
 +
  st = prova()
 +
 +
  Print st.a, String@(st.b)
 +
 +
End
 +
 +
Private Procedure Creaso()
 +
 +
  File.Save("/tmp/libprovaC.c", "struct Nome_struttura {\n" &
 +
                                "  int i;\n" &
 +
                                "  char *c;\n};\n\n" &
 +
                                "struct Nome_struttura * prova() {\n\n" &
 +
                                "  struct Nome_struttura st, *p;\n\n" &
 +
                                "  p = &st;\n" &
 +
                                "  p->i = 9999;\n" &
 +
                                "  p->c = \"prova\";\n\n" &
 +
                                "  return p;\n\n}")
 +
 +
  Shell "gcc -o /tmp/libprovaC.so /tmp/libprovaC.c -shared" Wait
 +
 +
End
 +
oppure (senza usare alcuna variabile d'appoggio) si assegnerà al ''Puntatore'' alla ''Struttura'' un'area di memoria allocat mediante la funzione "malloc()" della libreria standard di C:
 +
Private Procedure Creaso()
 +
 +
  File.Save("/tmp/libprovaC.c", "#include <stdlib.h>\n\n" &
 +
                                "struct Nome_struttura {\n" &
 +
                                "  int i;\n" &
 +
                                "  char *c;\n};\n\n" &
 +
                                "struct Nome_struttura * prova() {\n\n" &
 +
                                "  struct Nome_struttura *p = malloc(sizeof(struct Nome_struttura));\n\n" &
 +
                                "  p->i = 9999;\n" &
 +
                                "  p->c = \"prova\";\n\n" &
 +
                                "  return p;\n\n}")
 +
 +
  Shell "gcc -o /tmp/libprovaC.so /tmp/libprovaC.c -shared" Wait
 +
 +
End

Versione attuale delle 03:07, 23 ott 2022

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

Utilizzare nella funzione esterna una variabile del tipo della Struttura

1° esempio

Si può scrivere una libreria esterna condivisa ad hoc, contenente una funzione che ritorna una Struttura per "valore". Se la funzione esterna, scritta in C nel programma Gambas, prevede il ritorno al codice Gambas del semplice tipo della Struttura, la variabile del tipo della Struttura, usata nel codice scritto in C, dovrà essere dichiarata come globale.

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 memoria 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


Utilizzare nella funzione esterna un Puntatore alla Struttura

Se la funzione utilizza e ritorna un Puntatore alla Struttura, allora detto Puntatore potrà essere dichiarato come locale.
Si potrà fare uso - come appoggio - di una variabile del tipo della Struttura, la quale permetterà al Puntatore di puntare alla sua area di memoria. In particolare al Puntatore alla Struttura si assegnerà l'indirizzo di memoria della variabile d'appoggio del tipo della Struttura.

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

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


Public Sub Main()

 Dim st As New Struttura

 Creaso()

 st = prova()

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

End

Private Procedure Creaso()

 File.Save("/tmp/libprovaC.c", "struct Nome_struttura {\n" &
                               "  int i;\n" &
                               "  char *c;\n};\n\n" &
                               "struct Nome_struttura * prova() {\n\n" &
                               "  struct Nome_struttura st, *p;\n\n" &
                               "  p = &st;\n" &
                               "  p->i = 9999;\n" &
                               "  p->c = \"prova\";\n\n" &
                               "  return p;\n\n}")

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

End

oppure (senza usare alcuna variabile d'appoggio) si assegnerà al Puntatore alla Struttura un'area di memoria allocat mediante la funzione "malloc()" della libreria standard di C:

Private Procedure Creaso()

 File.Save("/tmp/libprovaC.c", "#include <stdlib.h>\n\n" &
                               "struct Nome_struttura {\n" &
                               "  int i;\n" &
                               "  char *c;\n};\n\n" &
                               "struct Nome_struttura * prova() {\n\n" &
                               "  struct Nome_struttura *p = malloc(sizeof(struct Nome_struttura));\n\n" &
                               "  p->i = 9999;\n" &
                               "  p->c = \"prova\";\n\n" &
                               "  return p;\n\n}")

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

End