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

Da Gambas-it.org - Wikipedia.
 
(5 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
Di seguito mostriamo alcuni esempi, nei quali la funzione esterna della libreria in C ritorna ''per valore'' 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====
Codice della libreria esterna in C:
+
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''.
  struct nome_struttura {
+
  Public Struct Nome_Struttura  <FONT color=gray>' ''Dichiara una "Struttura" simile a quella dichiarata nel codice C''</font>
  int a;
 
  char *b;
 
};
 
 
struct nome_struttura variabile_struttura;
 
 
 
struct nome_struttura *prova() {
 
 
    variabile_struttura.a = 99;    <FONT color=blue>// Assegna i valori ai membri della Struttura</font>
 
    variabile_struttura.b = "prova";
 
 
    return &variabile_struttura;
 
 
}
 
 
 
 
 
Codice Gambas:
 
Public Struct Nome_Struttura
 
 
   a As Integer
 
   a As Integer
 
   b As Pointer
 
   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 36: Riga 16:
 
   Dim nst As New Nome_Struttura
 
   Dim nst As New Nome_Struttura
 
   
 
   
  Shell "gcc -o /tmp/libprovaC.so " & Application.Path & "/libprovaC.c -shared -fPIC" Wait
+
  Creaso()
 
    
 
    
  nst = prova()
+
  nst = prova()
 
   
 
   
  Print nst.a, String@(nst.b)
+
  Print nst.a, String@(nst.b)
 
   
 
   
 
  '''End'''
 
  '''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''.
 
Il codice della libreria esterna in C:
 
#include <stdlib.h>
 
 
   
 
   
 +
'''Private''' Procedure Creaso()
 
   
 
   
struct AAA {
+
  File.Save("/tmp/libprovaC.c", "struct nome_struttura {\n" &
  int i;
+
                                "  int a;\n" &
  char * p;
+
                                "  char *b;\n};\n\n" &
   short s;
+
                                "'''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
 
   
 
   
  struct AAA a;
+
  '''End'''
+
 
+
====2° esempio====
struct AAA * Prova() {
+
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"
  a.i = 0x00444444;
 
 
 
  a.p = (char *) malloc(4);
 
  a.p[0] = 0x0A;
 
  a.p[1] = 0x0B;
 
  a.p[2] = 0x0C;
 
  a.p[3] = 0x0D;
 
 
 
  a.s = 0x0400;
 
 
   
 
   
  return &a;
 
 
   
 
   
}
 
 
 
Codice Gambas:
 
Private Extern Prova() As Pointer In "/tmp/libreria_C"
 
 
 
 
  '''Public''' Sub Main()
 
  '''Public''' Sub Main()
 
   
 
   
Riga 87: Riga 50:
 
   Dim j, b As Byte
 
   Dim j, b As Byte
 
    
 
    
 +
  Creaso()
 
    
 
    
  Shell "gcc -o /tmp/libreria_C.so " & Application.Path &/ "libreria_C.c -shared -fPIC" Wait
+
   p = Prova()
    
+
  If p == 0 Then Error.Raise("Puntatore NULLO !")
    p = Prova()
 
    If IsNull(p) Then Error.Raise("Puntatore NULLO !")
 
 
    
 
    
    st = Memory p For Read
+
  st = Memory p For Read
    Print Read #st As Integer
+
  Print Read #st As Integer
 
   
 
   
 
  <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>
 
  <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
+
  Seek #st, 8
    Read #st, po
+
  Read #st, po
    re = Memory po For Read
+
  re = Memory po For Read
    For j = 0 To 3
+
  For j = 0 To 3
      Read #re, b
+
    Read #re, b
      Print Hex(b, 2)
+
    Print Hex(b, 2)
    Next
+
  Next
    re.Close
+
  re.Close
 
   
 
   
  Print Read #st As Short
+
  Print Read #st As Short
 
   
 
   
  st.Close
+
  st.Close
 
   
 
   
 
  '''End'''
 
  '''End'''
 
 
 
===Caso in cui la funzione esterna ritorna una ''Struttura'' avente tra i suoi membri uno o più ''vettori'' di tipo "''char''"===
 
Codice della libreria esterna in C:
 
struct nome_struttura {
 
  char b[4];
 
  int a;
 
};
 
 
   
 
   
  struct nome_struttura variabile_struttura;
+
  '''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}")
 
   
 
   
struct nome_struttura *prova() {
+
  Shell "gcc -o /tmp/libreria_C.so /tmp/libreria_C.c -shared -fPIC" Wait
 
   
 
   
    variabile_struttura.b[0] = 'p';  <FONT color=blue>//assegna un carattere per ciascun elemento del vettore di tipo "chr"</font>
+
'''End'''
    variabile_struttura.b[1] = 'e';
 
    variabile_struttura.b[2] = 'r';
 
    variabile_struttura.b[3] = 'a';
 
 
    variabile_struttura.a = 99;
 
 
    return &variabile_struttura;      <FONT color=blue>// ritorna l'indirizzo di "variabile_struttura"</font>
 
 
};
 
 
 
 
 
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()''.  
 
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
 
   b[4] As Byte
Riga 147: Riga 103:
 
  End Struct
 
  End Struct
 
   
 
   
+
  Private Extern prova() As Nome_Struttura In "/tmp/libprovaC"
Library "/tmp/libprovaC"
 
  Private Extern prova() As Nome_Struttura
 
 
   
 
   
 
   
 
   
Riga 156: Riga 110:
 
   Dim nst As New Nome_Struttura
 
   Dim nst As New Nome_Struttura
 
   
 
   
   Shell "gcc -o /tmp/libprovaC.so " & Application.Path & "/libprovaC.c -shared -fPIC" Wait
+
   Creaso()
 
   
 
   
 
   nst = prova()
 
   nst = prova()
Riga 164: Riga 118:
 
   
 
   
 
  '''End'''
 
  '''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'''
 +
 +
 +
==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