Differenze tra le versioni di "Richiamare funzioni esterne di librerie scritte in C++"

Da Gambas-it.org - Wikipedia.
Riga 1: Riga 1:
Il richiamo con ''Extern'' di funzioni esterne presenti in librerie dinamiche .so, scritte in C++, non avviene in Gambas in modo identico a quello delle funzioni esterne scritte in linguaggio C.
+
Il richiamo con ''Extern'' di funzioni esterne presenti in librerie condivise .so, scritte in C++, non avviene in Gambas in modo identico a quello delle funzioni esterne scritte in linguaggio C.
  
Infatti, mentre con le librerie dinamiche .so scritte in C è possibile invocare da Gambas una qualsiasi funzione esterna avente un qualsiasi nome identificatore, con le librerie dinamiche .so scritte in C++ risulta possibile soltanto richiamare la funzione principale, quella avente nome identificatore: ''main( )'' .
+
Infatti, mentre con le librerie dinamiche .so scritte in C è possibile invocare da Gambas una qualsiasi funzione esterna avente un qualsiasi nome identificatore, con le librerie dinamiche .so scritte in C++ risulta possibile soltanto richiamare la funzione principale, quella avente nome identificatore: "main()".
  
Se la libreria dinamica .so contiene comunque più funzioni, queste dovranno essere chiamate comunque attraverso la funzione principale ''main( )'', sia per il motivo sopra esposto, sia perché esse non sono direttamente disponibili all'utente come quelle delle librerie dinamiche .so scritte in C.
+
Se la libreria dinamica .so contiene comunque più funzioni, queste dovranno essere chiamate comunque attraverso la funzione principale "main()", sia per il motivo sopra esposto, sia perché esse non sono direttamente disponibili all'utente come quelle delle librerie condivise .so scritte in C.
  
Ciò comporta che con ''Extern'' non è possibile utilizzare direttamente l'API di librerie esterne dinamiche .so, ma si dovrà creare un'apposita libreria dinamica .so contenente la parte di programma, scritto in C++, che comprende la routine principale ''main( )'', nella quale sono poste e vengono chiamate le funzioni esterne che si intendono realmente utilizzare.
+
Ciò comporta che con ''Extern'' non è possibile utilizzare direttamente l'API di librerie esterne condivise .so, ma si dovrà creare un'apposita libreria condivisa .so contenente la parte di programma, scritto in C++, che comprende la routine principale "main()", nella quale sono poste e vengono chiamate le funzioni esterne che si intendono realmente utilizzare.
  
Insomma, non verrà ''direttamente'' dichiarata ed invocata la funzione esterna, che ci interessa, della libreria C++, ma lo sarà una funzione principale ''main( )'' di un'apposita libreria dinamica esterna .so, da noi scritta in C++. All'interno di tale funzione ''main( )'' principale si porrà e si chiamerà la funzione esterna che realmente ci interessa chiamare.
+
Insomma, non verrà ''direttamente'' dichiarata ed invocata la funzione esterna, che ci interessa, della libreria C++, ma lo sarà una funzione principale "main()" di un'apposita libreria condivisa esterna .so, da noi scritta in C++. All'interno di tale funzione "main()" principale si porrà e si chiamerà la funzione esterna che realmente ci interessa chiamare.
  
La routine di ''main( )'' - contenuta nella nostra libreria esterna di appoggio, scritta anch'essa ovviamente in C++ - fa dunque da tramite necessario, come già detto, per invocare le funzioni esterne di librerie scritte in C++ .
+
La routine di "main()" - contenuta nella nostra libreria esterna di appoggio, scritta anch'essa ovviamente in C++ - fa dunque da tramite necessario, come già detto, per invocare le funzioni esterne di librerie scritte in C++ .
  
 
Ricapitolando si profila un rapporto secondo questo schema:
 
Ricapitolando si profila un rapporto secondo questo schema:
  Gambas <--> Nostra libreria dinamica esterna di ''appoggio'' <--> libreria dinamica esterna scritta in C++
+
  Gambas <--> Nostra libreria condivisa esterna di ''appoggio'' <--> libreria condivisa esterna scritta in C++
  
  
Riga 18: Riga 18:
 
Nel caso in cui sia necessario utilizzare più funzioni esterne di una libreria scritta in C++, si possono adottare almeno un paio di soluzioni.
 
Nel caso in cui sia necessario utilizzare più funzioni esterne di una libreria scritta in C++, si possono adottare almeno un paio di soluzioni.
  
1 - Creare per ciascuna funzione un'apposita libreria dinamica .so esterna d'appoggio, ovviamente scritta in C++, nella quale è appunto contenuta la funzione esterna che a noi interessa invocare. In tal caso, quindi, ogni qual volta si debba utilizzare la funzione esterna, si provvederà ad invocare la funzione della libreria dinamica da noi scritta. La libreria esterna, da noi creata, farà nuovamente da veicolo per utilizzare la funzione esterna che ci interessa realmente.
+
1 - Creare per ciascuna funzione un'apposita libreria condivisa .so esterna d'appoggio, ovviamente scritta in C++, nella quale è appunto contenuta la funzione esterna che a noi interessa invocare. In tal caso, quindi, ogni qual volta si debba utilizzare la funzione esterna, si provvederà ad invocare la funzione della libreria condivisa da noi scritta. La libreria esterna, da noi creata, farà nuovamente da veicolo per utilizzare la funzione esterna che ci interessa realmente.
 
<BR>Questa soluzione ha lo svantaggio, però, di dover realizzare - come ovvio - per ciascuna funzione un'apposita libreria esterna
 
<BR>Questa soluzione ha lo svantaggio, però, di dover realizzare - come ovvio - per ciascuna funzione un'apposita libreria esterna
  
  
2 - Creare, comunque, un'apposita libreria dinamica .so esterna, scritta in C++, nella quale porre tutte le funzioni che ci interessano e che dovremo richiamare ed utilizzare.
+
2 - Creare, comunque, un'apposita libreria condivisa .so esterna, scritta in C++, nella quale porre tutte le funzioni che ci interessano e che dovremo richiamare ed utilizzare.
<BR>Si provvederà, poi, all'interno di detta unica libreria dinamica a distinguere l'uso di una o di altra funzione mediante l'invio di valori stringa o numerici univoci che saranno valutati da istruzioni condizionali, le quali consentiranno o meno di accedere ad una determinata funzione tra quelle contenute.
+
<BR>Si provvederà, poi, all'interno di detta unica libreria condivisa .so a distinguere l'uso di una o di altra funzione mediante l'invio di valori stringa o numerici univoci che saranno valutati da istruzioni condizionali, le quali consentiranno o meno di accedere ad una determinata funzione tra quelle contenute.
  
Di questa seconda modalità mostriamo un esempio pratico, nel quale abbiamo una certa libreria esterna .so, scritta in C++, contenente un paio di funzioni:
+
Di questa seconda modalità mostriamo un esempio pratico, nel quale abbiamo una certa libreria esterna condivisa .so, scritta in C++, contenente un paio di funzioni:
 
  #include <cstdlib>
 
  #include <cstdlib>
 
  #include <sstream>
 
  #include <sstream>
Riga 89: Riga 89:
 
   
 
   
 
   
 
   
  '''Public''' Sub Button1_Click()
+
Public  Sub Main()
 
   
 
   
 
   Dim p As Pointer
 
   Dim p As Pointer
Riga 95: Riga 95:
 
   
 
   
 
  <FONT Color=gray>' ''Qui va il nome di una delle due funzioni della libreria esterna in C++ che a noi interessa realmente utilizzare:''</font>
 
  <FONT Color=gray>' ''Qui va il nome di una delle due funzioni della libreria esterna in C++ che a noi interessa realmente utilizzare:''</font>
  p = Alloc("funzione_2")
+
  p = Alloc("funzione_2")
 
   
 
   
  i = main(0, VarPtr(p))
+
  i = main(0, VarPtr(p))
   
+
  Print "Dato ritornato:"
+
  Print "Dato ritornato:"
  If i > -1 Then  
+
  If i > -1 Then  
    Print i
+
    Print i
  Else
+
  Else
    Print String@(p)
+
    Print String@(p)
  Endif
+
  Endif
 
+
  Free(p)
+
  Free(p)
 
   
 
   
  '''End'''
+
  End

Versione delle 17:02, 8 lug 2023

Il richiamo con Extern di funzioni esterne presenti in librerie condivise .so, scritte in C++, non avviene in Gambas in modo identico a quello delle funzioni esterne scritte in linguaggio C.

Infatti, mentre con le librerie dinamiche .so scritte in C è possibile invocare da Gambas una qualsiasi funzione esterna avente un qualsiasi nome identificatore, con le librerie dinamiche .so scritte in C++ risulta possibile soltanto richiamare la funzione principale, quella avente nome identificatore: "main()".

Se la libreria dinamica .so contiene comunque più funzioni, queste dovranno essere chiamate comunque attraverso la funzione principale "main()", sia per il motivo sopra esposto, sia perché esse non sono direttamente disponibili all'utente come quelle delle librerie condivise .so scritte in C.

Ciò comporta che con Extern non è possibile utilizzare direttamente l'API di librerie esterne condivise .so, ma si dovrà creare un'apposita libreria condivisa .so contenente la parte di programma, scritto in C++, che comprende la routine principale "main()", nella quale sono poste e vengono chiamate le funzioni esterne che si intendono realmente utilizzare.

Insomma, non verrà direttamente dichiarata ed invocata la funzione esterna, che ci interessa, della libreria C++, ma lo sarà una funzione principale "main()" di un'apposita libreria condivisa esterna .so, da noi scritta in C++. All'interno di tale funzione "main()" principale si porrà e si chiamerà la funzione esterna che realmente ci interessa chiamare.

La routine di "main()" - contenuta nella nostra libreria esterna di appoggio, scritta anch'essa ovviamente in C++ - fa dunque da tramite necessario, come già detto, per invocare le funzioni esterne di librerie scritte in C++ .

Ricapitolando si profila un rapporto secondo questo schema:

Gambas <--> Nostra libreria condivisa esterna di appoggio <--> libreria condivisa esterna scritta in C++


Caso in cui si debbano utilizzare più funzioni esterne

Nel caso in cui sia necessario utilizzare più funzioni esterne di una libreria scritta in C++, si possono adottare almeno un paio di soluzioni.

1 - Creare per ciascuna funzione un'apposita libreria condivisa .so esterna d'appoggio, ovviamente scritta in C++, nella quale è appunto contenuta la funzione esterna che a noi interessa invocare. In tal caso, quindi, ogni qual volta si debba utilizzare la funzione esterna, si provvederà ad invocare la funzione della libreria condivisa da noi scritta. La libreria esterna, da noi creata, farà nuovamente da veicolo per utilizzare la funzione esterna che ci interessa realmente.
Questa soluzione ha lo svantaggio, però, di dover realizzare - come ovvio - per ciascuna funzione un'apposita libreria esterna


2 - Creare, comunque, un'apposita libreria condivisa .so esterna, scritta in C++, nella quale porre tutte le funzioni che ci interessano e che dovremo richiamare ed utilizzare.
Si provvederà, poi, all'interno di detta unica libreria condivisa .so a distinguere l'uso di una o di altra funzione mediante l'invio di valori stringa o numerici univoci che saranno valutati da istruzioni condizionali, le quali consentiranno o meno di accedere ad una determinata funzione tra quelle contenute.

Di questa seconda modalità mostriamo un esempio pratico, nel quale abbiamo una certa libreria esterna condivisa .so, scritta in C++, contenente un paio di funzioni:

#include <cstdlib>
#include <sstream>
#include <string.h>
 
 
int Funzione_1() {

   int a;
   
   a = 100;

   return a;

}


std::string Funzione_2() {

   std::string s = "testo dalla";

   return s;

}


int main(int c, char *s[]) {

  int ritorno;
  std::string t, r;

  
/* Se abbiamo passato "funzione_1", verrà invocata la "Funzione_1" */
  if (strcmp((char *)s[0], "funzione_1") == 0) {
/* In questo caso viene ritornato un Intero */
    ritorno = Funzione_1();
    return ritorno;
  }

/* Se abbiamo passato "funzione_2", verrà invocata la "Funzione_2". In questo caso viene ritornata per 'riferimento' una Stringa */
  if (strcmp((char *)s[0], "funzione_2") == 0) {
    t = Funzione_2();

/* Vengono unite le stringhe di tipo base */
    r =  t + " " + std::string(s[0]) + " della libreria esterna in C++";
 
/* La variabile base stringa "r" viene convertita nel tipo 'char*', affinché possa essere restituita al codice Gambas attraverso il parametro "char** s" della routine "main()" */
    char* rit = strcpy((char*)malloc(r.length()+1), r.c_str());
    *s =  rit;
    
    return -1;
    
  }

}


Il semplice codice Gambas potrà essere il seguente:

' int main(int c, char *s[])
' E' la routine principale della libreria dinamica condivisa .so da noi creata.
Private Extern main(rit As Integer, po As Pointer) As Integer In "/tmp/libadhoc"


Public  Sub Main()

 Dim p As Pointer
 Dim i As Integer = -1

' Qui va il nome di una delle due funzioni della libreria esterna in C++ che a noi interessa realmente utilizzare:
 p = Alloc("funzione_2")

 i = main(0, VarPtr(p))

 Print "Dato ritornato:"
 If i > -1 Then 
   Print i
 Else
   Print String@(p)
 Endif

 Free(p)

End