Newsgroup: it.comp.lang.c
Titolo: Passaggio di parametri ad una shared library

Ciao a tutti: avrei bisogno di un po' di aiuto.
Sono alle prese con una libreria Open Source che sto cercando di modificare leggermente.
 
Detta libreria e' discretamente complicata per le mie conoscenze di programmazione (usa il cmake per inizializzare il tutto e poi tramite make compila tutto, generando prima una lib.so e poi questa stessa e' utilizzata per generare degli esempi messi a disposizione dagli autori.
 
Io sto cercando di modificare una di questi esempi ed avrei la necessita' di passare un parametro dal main ad una di queste funzioni che poi costituiranno la lib.so
 
Ho tentato di usare una variabile dichiarata fuori dal main e facendo riferimento alla stessa nella funzione di mio interesse precedendola con extern ma la cosa non funziona: durante la compilazione, l'errore e' relativo al fatto che non esiste alcun riferimento alla variabile dichiarata extern.
 
Potreste aiutarmi?
Magari indirizzandomi verso un esempio (se non e' chiedere troppo)
Comunque grazie


Non credo d'aver capito che devi fare - link della lib e cosa vuoi fare? :)
 
Ciao!

 Ciao!
 
Immagina di avere Fun1, Fun2 e Fun3 che fatto la tua libreria shared (lib.so)
 
Poi hai un main che fa riferimento a p. esempio Fun1.
 
Fai il link del main con lib.so attieni un eseguibile e gira.
 
 
Adesso immagina di voler passare un parametro dal main a Fun1, "senza modificare
il prototipo di Fun1": c'e' qualche possibilita'?
Essendo la libreira shared crea dei problemi per il passaggio di parametri,
tramite 
p.es
 file.h?
La strada tradizionale (dichiarata in Fun1 extern e dichiararla fuori dal main
non funziona.
Spero di essere stato piu' chiaro
Grazie comunque

On Thursday, October 29, 2015 at 4:18:14 PM UTC+1, arkkimede wrote:

Non sono sicuro di aver capito cosa stai cercando di fare, ma
credo che il tuo problema sia questo:
stai modificando la libreria introducendo una dipendenza da
un oggetto che e' definito in un sorgente che e' 
all'esterno della libreria stessa perche' lo hai definito
dentro al main che poi chiamera' la libreria.
Questo e' proprio un errore logico: la libreria non puo'
dipendere dal main, casomai e' il contrario.
 
Per ottenere quello che vuoi devi aggiungere un parametro 
in piu' alla funzione che ti serve.
 
ciao
Giacomo


 
Perché vuoi fare una cosa del genere? Se già modifichi Fun1 per farle
capire il nuovo parametro, puoi modificare anche la firma. Se non vuoi
rompere la compatibilità con altri applicativi che usano lib.so, fai una
altra funzione che richiama Fun1, e dal tuo main chiami quella.
 
Ciao!

 
 
E' un errore logico ma su linux si può fare, si mette la variabile extern
nell'applicazione si compila la shared (-fpic, -shared) e l'eseguibile con
-rdynamic.
 
Inutile dire che, per quello che vuole fare l'OP, sarebbe una porcata da
evitare a tutti i costi.
 
Modificare la firma o fare un'altra funzione è sicuramente l'opzione più
sensata-
 
Ciao!

 sensata-
 
Se le funzioni wrapper sono tante e/o il parametro e' preferibile
che sia da specificare una volta sola invece che ad ogni chiamata
ce' anche questa alternativa che e' 
un po' meno porcata della variabile extern: aggiungere il paramtro
come variabile globale NELLA libreria assieme a due funzioni per
impostarla e leggerla. 
In questo mdo puo' anche cambiare tutte le Fun1, Fun2, .. Fun_n della
libreria in modo da usare il nuovo parametro senza dover creare
altrettanti wrapper con il parametro in piu.
 
ciao
Giacomo


Eh, pure questa soluzione mi sembra buona :)
 
Certo, per parlare d'eleganza o porcate bisognerebbe vedere il caso
specifico, altrimenti così andiamo un po' a caso :)
 
Ciao!


La soluzione migliore ti è gia stata spiegata da altri
Una' altra soluzione è che se la libreria ha come input una struct 
sarebbe possibile aggiungere a questa struct un ulteriore campo.
Dal punto di vista logico se il campo da aggiungere è logicamente 
correlato con la struct.
 

Il 29/10/2015 09:18, arkkimede ha scritto:

Un altra soluzione:  aggiungi ... come parametro alla func e tratti la 
funzione come una variable parameter list mantenendo la compatibilità 
(se serve) con il regresso.
Non è una soluzione elegante ma si puo fare.
 

 correlato con la struct.
 
:)
 
Visto che le stiamo dicendo tutte io aggiungo! :D
 
Molte librerie hanno una funzione di inizializzazione che prende dei flags
(ad esempio le SDL hanno SDL_Init() che prende un uint32 dove si mettono
in or i flags relativi ai subsystems che si vogliono controllare).
In questo caso non serve neppure nessuna modifica all'interfaccia esterna:
basta aggiungere una #define! :)
 
Ciao!
 
 
P.S. Comunque, per dire, se l'OP ci diceva che libreria era magari davamo
un consiglio di stile migliore ;)

 un consiglio di stile migliore ;)
 
L'OP vi dice di che libreria si tratta: 
https://github.com/srsLTE/srsLTE
.
Si tratta di una libreria che si interfaccia con una piastra Software Define Radio ed implementa un ricevitore LTE.
La piastra è una Ettus B210 
http://www.ettus.com/product/details/UB210-KIT
 
che implementa sostanzialmente un capionamento ad una frequenza che può andare da 9.2MHz fino a svariate decine di MHz (circa 30), a seconda della  banda della cella che si esamina e questi campioni vengono passati via usb3 al pc con Ubuntu che li elabora (la libreria) per estrarre informazioni relative alle celle LTE in aria.
 
Per motivi su cui non mi dilungo, ho dovuto modificare detta libreria in modo che invece di processare i campioni ottenuti dalla B201, usasse i campioni che la medesima piastra aveva ricevuto e salvato su di un file binario.
 
I parametri che volevo passare erano relativi a come il file dati era stato campionato in modo da impostare le grandezze che non posso ricavare automaticamente come avrebbe fatto la piastra.
 
Osservando l'albero delle directory della libreria vedrete che c'è la directory che si chiama srslte e sotto ci sono le directory lib, include ed examples.
In lib c'è appunto tutto il codice che genera la lib.so e dentro examples ci sono degli esempi (di cui io ne ho modificato uno) che usano la lib.so.
 
Eccovi accontentati


Oh, ora è più chiaro! :)
 
La lib non la conoscevo, ho dato solo un'occhiata al volo ma credo d'essermi
fatto un'idea.
 
Per fare la cosa pulita, come prima cosa dovresti decidere (o, se vuoi fare
una patch, chiedere ad uno degli sviluppatori), se ha senso mascherare questa
funzionalità sotto una funzione che fa, di base, un altro lavoro, oppure
creare un nuovo modulo con delle funzioni dedicate. Immagino dipenda dai
casi d'uso, per cui non ti posso dare alcun parere in merito.
 
Altrimenti, se non t'interessa una roba pulita, tra tutti i suggerimenti
che ti sono stati dati, non essendoci né funzioni d'inizializzazione
globali, né strutture con settaggi generali, ed essendo le funzioni che
richiami molto specifiche, io andrei per il suggerimento di aggiungere
una funzione extra: puoi sia continuare a usare la lib nei casi "standard"
sia usare la nuova funzionalità su richiesta e mantieni la compatibilità
con altri applicativi installati.
 
M2C,
Ciao!

 Ciao!
 
Tentero' il suggerimento di Giacomo Degli Esposti.
Nei file .c che contengono le funzioni a cui devo passare i parametri aggiungero' delle funzioni setParameter1, setParameter2, getParameter1, getParameter2, etc. (ovviamente dichiarandoli nei corrispondenti .h) ed a questo punto le funzioni dovrebbero essere visibili ovunque, anche dal main o dove mi serve.
Posso farlo "agilmente" (almeno lo spero) perche' ogni file contiene piu' funzioni ed il cmake penso faccia riferimento ai file e non alle funzioni.
Sarebbe stato piu' elaborato se ogni funzione era un singolo file.
 
Grazie comunque a tutti.
 

 
Riporto "meglio" a futura memoria.
 
1. In un file (appartenente alla libreira) contenente una funzione a cui voglio passare un parametro, all'inizio, subito dopo gli include, dichiaro una variabile
uguale al parametro che voglio passare. La dichiaro static anche in modo da ritrovarla gia' inizializzata quando ritorno nelle funzioni contenute in questo file. A titolo di esempio
 
static int overSampling:
 
2. Nel medesimo file dichiaro una nuova funzione che imposta questa variabile
void set_overSampling(int over)
{
   overSampling = over;
}
 
3. Nel file corrispondente .h riporto il prototipo di questa funzione.
 
4. Nel main includo il .h modificato e ove ritengo necessario scrivo 
p.es
.
   set_overSampling(8);
 
A questo punto la varibile globale overSampling e' stata inizializzata e 
nelle funzioni contenute nel file .c modificato, posso usarla tranquillamente.