Newsgroup: it.comp.lang.c
Titolo: Problema con puntatori a funzioni

Ciao a tutti, ho un problema con i puntatori a funzione... non riesco a
trovare la soluzione!
Quello che voglio ottenere è di avere la possibilità di indirizzare a
diversi tipi di funzioni con un'unico puntatore.
Vi segno come commento gli errori che mi da
typedef int (* func_p0)(void);
typedef int (* func_p1)(void*);
typedef int (* func_p2)(void*, void*);
typedef void (* render_p1)(void*);
typedef union
{
 func_p0 ip0;
 func_p1 ip1;
 func_p2 ip2;
 render_p1 vp1;
} pfunc;
typedef struct {
 int a,b,c,d;
 pfunc p;
} esempio;
int funzione (void *);
esempio es = {
  1,2,3,4,
  (func_p1)&funzione  // Assignment of pointer to functions
                      // with different number of arguments
                      // assignment of pointer to int function(pointer
                      // to void) to pointer to int function(void)
};
int funzione(void *a)
{
...
}
int main(int argc, char *argv[])
{
...
	es.p(&a);  // found 'pfunc' expected a function, missing prototype
...
}
Grazie mille in anticipo!

Roberto ha scritto:

Forse ci sono altri errori, ma sicuramente devi specificare il membro 
dell'unione.
esempio es;
es.a=5;
es.b=6;
es.c=8;
es.d=11;
es.p.p1=funzione;
Come farlo durante l'inizializzazione non lo so..
-- 
Devaraja (Xdevaraja87^gmail^c0mX)
Linux Registerd User #338167
http://counter.li.org

 es.p.p1=funzione;
Nell'inizializzazione va bene anche come ho fatto, la struttura devo
inizializzarla nel modo che ho scritto e metterla const perchè deve
essere allocata in una rom.
Grazie cmq! 
help! ^_^

Roberto ha scritto:

Ciao prova cosi':
typedef int (* func_p0)(void);
typedef int (* func_p1)(void*);
typedef int (* func_p2)(void*, void*);
typedef void (* render_p1)(void*);
typedef union
{
 func_p0 ip0;
 func_p1 ip1;
 func_p2 ip2;
 render_p1 vp1;
} pfunc;
typedef struct {
 int a,b,c,d;
 pfunc p;
} esempio;
int funzione (void *);
esempio es = {
  1,2,3,4,
  (void *)funzione  // Assignment of pointer to functions
                      // with different number of arguments
                      // assignment of pointer to int function(pointer
                      // to void) to pointer to int function(void)
};
int funzione(void *a)
{
...
}
int main(int argc, char *argv[])
{
...
	es.p.ip1(&a);  // found 'pfunc' expected a function, missing prototype
...
}

Perfetto così funziona, grazie!

La prima cosa che non va, e l'hanno già detto, è che nel momento in
cui devi andare a memorizzare qualcosa in una union, devi specificare
il membro che devi modificare. Ad esempio:
union {
    char c;
    int i;
    float f;
} types;
types.c = 'a';
types.i = 100;
types.f = 12.34;
E naturalmente, l'unione è una struttura che assume la dimensione del
tipo più "voluminoso" che è dichiarato al suo interno. Quindi, una
union per memorizzare un insieme  di puntatori a funzione non mi sembra
la soluzione ideale, perchè potresti memorizzare nella union un membro
dichiarato come char (*p1)(int, int) e andare ad usare un'altro
dichiarato come float (*p2)().
Non ho capito bene per cosa ti serve tutto questo (non l'hai detto ?),
me se ti serve fare qualcosa come memorizzare in una struct una specie
di "ambiente" con dati e funzioni (che magari cambiano in funzione dei
dati), ti conviene usare puntatori a funzioni dichiarati direttamente
nella struct:
struct {
    my_type data[100];
    void (*print_data)();
    int (*sum_data)();
} environment;
Ma naturalmente tutto ciò che ho scritto deriva da una serie di
intuizioni e da un modo di fare strettamente "personale". Dipende tutto
da te, alla fine...

Il problema risolto prima va bene adattando un pò il codice.
Il problema è sorto quando ho implementato un sistema a finestre per un
dispositivo con schermo lcd. Mi sono ispirato alla struttura di windows
quindi ho creato una winprocedure che processa tutti gli eventi di
tutte le finestre.
Quando l'utente preme un tasto devo lanciare la funzione appropriata
per quel tasto.
Ogni funzione può appunto avere parametri differenti, quindi volevo
trovare un modo che con UN semplice puntatore a funzione potesse
chiamare qualsiasi tipo di funzione (evitando di mettere nella
struttura troppi puntatori a funzione poichè lo spazio che ho in rom è
poco).
Con la soluzione di ceppira devo specificare nella struttura il 'tipo'
di funzione che deve essere utilizzata ip0,ip1, e lanciarla con il
puntatore specifico.
Può anche andare bene così, se avete un sistema migliore lo adotterò!

 per quel tasto.
Puoi avere un array di puntatori a funzione e usare un codice associato 
al tasto premuto come indice. Per il problema dei parametri non saprei.. 
potresti aggiungere parametri inutilizzati a tutte le funzioni.
int funz1(int,int,int); /*1 usato*/
int funz2(int,int,int); /*2 usati*/
int funz3(int,int,int); /*tutti usati*/
int (*keyb_fns[3])(int,int,int)={funz1,funz2,funz3};
void keyb_handler(int key_code)
{
	int param1=1;
	int param2=2;
	int param3=0;
	switch(key_code){
		/*imposta i parametri
		  in base al tasto premuto.
		  Se un p. non serve mettilo a 0*/
	}
	keyb_fns[key_code](param1,param2,param3);


 Per il problema dei parametri non saprei.. potresti aggiungere parametri inutilizzati a tutte le funzioni
E' quello che ho fatto fino ad oggi,mi da ovviamente un sfilza di
warning perche' sono parametri inutilizzati.
Tra l'altro utilizzando la soluzione di ceppira funziona egregiamente
sul vc (il vc lo uso per simulare il display con le SDL) pero' quando
mi trovo a compilarlo con il compilatore IAR per il processore usato
sul dispositivo non funziona. :-(

Anche secondo me in questo caso la soluzione migliore sarebbe avere un
solo prototipo di funzione, anche se non tutti gli argomenti sono
utilizzati.
Per quanto riguarda il modello di Windows, poi... la Microsoft non
rispetta i warnings degli utenti, figurarsi quelli del compilatore...

Si alla fine tengo il codice così comè inutile perdere tempo per una
cosa che funziona senza dare problemi. L'idea della union mi è venuta
guardando il codice di doom, avevano abbozzato quest'idea ma non
l'hanno sviluppata e ora mi rendo conto del perchè! :-)
Grazie a tutti comunque!