2014-12-15 23 views
5

ho questa funzione:Come passare l'argomento della funzione una funzione del puntatore usando la funzione wrapper?

void boot(uint ncores, uint nterm, Task boot_task, int argl, void* args) 
{ 

for(int i=0; i<MAX_PROC;i++) { 
    PT[i].ppid = NOPROC; 
} 
nextproc = 0; 

curproc = NOPROC; 
Exec(boot_task, argl, args); 
} 

ed e voglio invece di usare Exec() utilizzare pthread, quindi devo chiamare il cpu_boot:

void cpu_boot(uint cores, interrupt_handler bootfunc, uint serialno) 
{ 
//I cannot change this function 
} 

Questi sono i tipi degli argomenti

typedef void interrupt_handler(); 
typedef int (* Task)(int, void*); 

Ho provato:

void boot(uint ncores, uint nterm, Task boot_task, int argl, void* args) 
{ 
    void my_wrapper() 
    { 

     int y; 
     y= boot_task(argl, args); 
    } 

    cpu_boot(ncores, my_wrapper , nterm); 
} 

Ma questo è sbagliato. Come posso implementarlo?

+0

poiché le due variabili: PT [] e nextproc non sono definiti (sono variabili globali?) Ci sono alcuni altri problemi: 1) non possono le successive funzioni in C 2) le istruzioni typedef hanno bisogno di un nome 'trascinamento' per utilizzare per fare riferimento al typedef. 3) questo: typedef void interrupt_handler(); non è un prototipo valido per una funzione di interruzione. questo è: typedef void interrupt_handler (void); poiché le funzioni di interruzione non possono essere passate nei parametri, poiché non vengono mai chiamate. – user3629249

+0

@ user3629249: I due typedef sono "OK"; i nomi dei typedef sono 'interrupt_handler' e' Task'. La definizione di 'interrupt_handler' dovrebbe specificare gli argomenti accettabili, o specificare' void' se la funzione non accetta argomenti, ma questo è un problema (relativamente) minore. Si noti che i gestori di segnali standard nello spazio utente, dove normalmente vengono utilizzati i pthread, hanno il tipo 'void (* handler) (int signum);' - la funzione accetta un argomento. Vengono chiamati gestori di segnale e gestori di interrupt; sarebbero inutili se non venissero mai chiamati. –

risposta

2

Si vorrà qualcosa di simile:

void some_interrupt_handler(){ 
    /* code here */ 
    return; 
} 

interrupt_handler* my_wrapper(Task boot_task, int argl, void* args) 
{ 
    /* 
     this is where you run boot task 
    */ 
    boot_task(argl, args); 

    /* then pick an interrupt_handler to return... */ 
    void (*function_ptr)() = some_interrupt_handler; 

    return function_ptr; 
} 

Quindi è possibile utilizzare il vostro involucro in questo modo:

void boot(uint ncores, uint nterm, Task boot_task, int argl, void* args) 
{ 
    cpu_boot(ncores, my_wrapper(boot_task, argl, args) , nterm); 
} 
+0

Come posso passare l'argomento bootfunc all'etichetta di una funzione wrapper senza chiamarla ?? Qualcosa come quel cpu_boot (ncores, my_wrapper, nterm); @Grzegorz Szpetkowski –

+0

@Lefteris Sarantaris: è possibile passare il puntatore alla funzione come un altro parametro di my_wrapper. Non si può fare 'cpu_boot (ncores, my_wrapper, nterm)' a meno che 'my_wrapper' sia di tipo interrupt_handler - nel qual caso non si ha la possibilità di passare alcun argomento (argl, args ecc.) Perché interrupt_handler non prendere argomenti ... Penso che il più vicino possibile è 'my_wrapper (boot_task, boot_func, argl, args)' dove boot_func è un puntatore a funzione. –

1

Un modo più generico e molto altro ancora ... flexable

void some_interrupt_handler(){ 
    /* code here */ 
    return; 
} 

typdef struct boot_data_struct { 
    int argc; 
    void * argv; 
    Task boot_task; 
    interrupt_handler * handler; 
} boot_data; 

interrupt_handler* my_wrapper(void * data) 
{ 
    boot_data * bootData = data; 

    /* 
     this is where you run boot task 
    */ 
    data->boot_task(bootData->argc, bootData->argv); 

    return bootData->handler; 
} 

Quindi è possibile utilizzare il wrapper in questo modo: