Newsgroup: it.comp.lang.c
Titolo: problema con void*

Sto scrivendo un programma che usa delle librerie, le cui funzioni accettano 
valori tramite void *.
Se devo passare un solo parametro è tutto ok (nella funzione faccio un 
cast), ma se devo passare due parametri come posso fare?
Ad esempio devo passare due puntatori a char ad una funzione che accetta un 
void *. Io ho pensato di creare un array di puntatori a char, passare 
l'indirizzo dell'array,  e poi fare un cast, ma mi da errore di 
compilazione.
Per ora passo un solo parametro e l'altro lo rendo globale, ma mi sembra 
poco elegante.Come posso risolvere il problema?

paolo wrote:

Puoi:
- incapsularli in una struttura
- passarli attraverso un array
- usare un parametro globale (ma non e' mai molto bello)
Al di la delle soluzioni che ti ho proposto, penso ci sia un probla di 
interfaccia: una funzione che accetta solo 1 void *, non e' concepita per 
usare piu' di un parametro, ma in genere si adatta a rudimentali funzioni 
di attraversamento.
E' preferibile concepirle con almeno 2 puntatori come fanno nelle glib, piu' 
pulito, piu' versatile: ti permette di utilizzarla come funzione di 
attraversamento di un ADT senza fatica.
Esempio schematico:
    typedef int (*traverse_function) (void * data, void * user_data);
    adt_traverse(ADT *A, traferse_function tf, void * user_data)
        per_ogni elemento a appartemente ad A
            tf(a->data, user_data)
La funzione di attraversamento si occupa di scorrere tutti gli elementi e di 
chiamare su ciascuno di essi la funzione di attraversamento definita 
dall'utente, con i dati che si trova di volta in volta (primo parametro) e 
i dati utente (uguali per tutte le chiamate, come secondo parametro).
Il mio esempio e' rudimentale, per averne qualcuno di piu' completo e 
complesso, guarda le glib.
-- 
Mox
"Trust the programmer."
"Don't prevent the programmer from doing what needs to be done."
"Keep the language small and simple."
"Provide only one way to do an operation."

- usare un parametro globale (ma non e' mai molto bello)
Questo potrebbe non essere possibile, se il codice fa parte di una
libreria.
-- 
Andrea Laforgia
#exclude <windows.h>

Mox wrote:
Purtroppo le librerie non le ho scritte io.
Il problema è che se ho una funzione A:
void A(EZ_Widget *widget, void *data)
{
        EZ_Destroy((EZ_Widget*)data);
}
funziona se passo a data il puntatore a widget.
Ora io voglio passare due puntatori a widget quindi:
EZ_Widget *arr[2];
arr[0] = widget1;/*puntatore al primo widget*/
arr[1] = widget2;/*puntatore al secondo widget*/
se passo arr alla funzione A di prima
void A(EZ_Widget *widget, void *data)
{
        EZ_Destroy((EZ_Widget *)data[0]);
}
ottengo errore di compilazione.
Questo è il problema che devo risolvere.
Come posso fare

 Attenzione, con le strutture potrebbero esserci problemi di "padding".
Scusa, ma non ti seguo, mi spieghi in dettaglio o fai un esempio?


 ottengo errore di compilazione.
Un void * non lo puoi deferenziare, in qualche modo devi prima convertire il 
void * a un tipo (in questo caso l'array di puntatori). Dopo puoi 
deferenziarlo.
<code>
    /* NON testato :P */
    void A(EZ_Widget *widget, void *data)
    {
        EZ_Widget ** tmp = data; /* il cast da void * e' implicito */
        EZ_Destroy(data[0]);
        EZ_Destroy(data[1]);
    }
</code>
In alternativa fai 2 distinge chiamate alla funzione, ciascuna con uno dei 2 
puntatori (se logicamente accettabile).
