Caricare i dati di un vettore scritto in C in un vettore di un'applicazione Gambas

Da Gambas-it.org - Wikipedia.

Se si ha un codice sorgente, scritto in C, nel quale vi è una variabile vettoriale globale istanziata con dei valori, per assumere e caricare tali valori in una variabile vettoriale di un'applicazione Gambas senza che vengano ricopiati manualmente nel codice sorgente di tale applicazione, si potrà copiare - qualora siano presenti anche altri simboli e risorse - la variabile vettoriale del sorgente C in un nuovo sorgente scritto sempre in linguaggio C, aggiungendovi anche una semplice funzione che restituisca la dimensione del vettore (ossia la quantità di byte/valori contenuti) e finalmente trasformata in un'apposita libreria dinamica condivisa .so da richiamare nell'applicazione Gambas.


Mostriamo di seguito un semplice esempio.

Poniamo il caso che i dati della variabile vettoriale del codice sorgente C siano i seguenti:

unsigned char vettore_C[] = {
   0x70, 0x7d, 0x86, 0x9a, 0xac, 0xb8, 0xbc, 0xc5,
   0x9d, 0xba, 0xd5, 0xe9, 0xf7, 0xfd, 0xfd, 0xf2
};

Dal codice sorgente, nel quale è presente il predetto vettore, si genererà un'apposita libreria esterna dinamica condivisa .so . L'area di memoria del vettore, poi, sarà puntata in Gambas con il meotodo GetExternSymbol() della Classe System. Ottenuto il relativo Puntatore a quell'area di memoria, poiché nel nostro caso non esistono valori uguali a zero, si leggerà all'interno dell'area medesima sino a quando non si giungerà al primo valore pari a zero, che rappresenta così l'uscita dall'area di memoria del vettore. Ad ogni modo, se si conosce (come nel nostro esempio) la quantità di elementi costituenti l'array del sorgente C, sarà ovviamente molto agevole leggere tutti i valori contenuti, ad esempio utilizzando un ciclo For

Public Sub Main()

 Dim p As Pointer
 Dim i As Integer
 Dim bb As New Byte[]
 
' Generiamo l'apposita libreria dinamica condivisa .so:
  CreaSo()

' Puntiamo all'area di memoria della variabile vettoriale ora contenuta dall'apposita libreria dinamica .so:
  p = System.GetExternSymbol("/tmp/Lib_C", "vettore_C")
  If IsNull(p) Then Error.Raise("Puntatore NULLO !")
  
' Leggiamo dall'area di memoria della variabile vettoriale contenuta dallalibreria dinamica .so, fino a che il valore letto non sia zero
' ed assegnamo i valori, così letti, alla variabile vettoriale dell'applicazione Gambas:
  While Byte@(p + i) > 0
    bb.Push(Byte@(p + i))
    Inc i
  Wend
     
' Vediamo semplicemente in console la quantità di elementi del vettore istanziati:
  Print bb.Count

End
 

Private Procedure CreaSo()

  File.Save("/tmp/Lib_C.c", "unsigned char vettore_C[] = {" &
                            "0x70, 0x7d, 0x86, 0x9a, 0xac, 0xb8, 0xbc, 0xc5," &
                            "\n0x9d, 0xba, 0xd5, 0xe9, 0xf7, 0xfd, 0xfd, 0xf2\n};")
   
  Shell "gcc -o /tmp/Lib_C.so /tmp/Lib_C.c -shared" Wait
  
End