2014-12-15 48 views
5

mam tej funkcji:Jak przekazać do argumentu funkcji funkcję wskaźnika za pomocą funkcji owijki?

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); 
} 

i i chcę zamiast korzystania Exec() używać pthread, więc muszę nazwać cpu_boot:

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

Są to typy argumentów

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

Próbowałem:

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); 
} 

Ale to jest złe. Jak mogę to wdrożyć?

+0

ponieważ dwie zmienne: PT [] i nextproc nie są zdefiniowane (czy są to zmienne globalne?) Jest kilka innych problemów: 1) nie mogą następnych funkcji w C 2) instrukcje typu "wyciągnij" użyj, aby odwołać się do typedef. 3) to: typedef void interrupt_handler(); nie jest prawidłowym prototypem funkcji przerwania. to jest: typedef void interrupt_handler (void); ponieważ funkcje przerwań nie mogły przejść w parametrach, ponieważ nigdy nie są wywoływane. – user3629249

+0

@ user3629249: Dwa typy są "OK"; nazwy typedefs to 'interrupt_handler' i' Task'. Definicja 'interrupt_handler' powinna określać akceptowalne argumenty lub określić' void', jeśli funkcja nie przyjmuje argumentów, ale jest to (względnie) niewielki problem. Zauważ, że standardowe procedury obsługi sygnałów w przestrzeni użytkownika, w której normalnie używane są pthready, mają typ 'void (* handler) (int signum);' - funkcja przyjmuje argument. Obsługiwane są programy obsługi sygnałów i procedury obsługi przerwania; byliby bez sensu, gdyby nigdy nie zostali wezwani. –

Odpowiedz

2

Będziesz chciał coś takiego:

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; 
} 

Następnie można użyć swoje opakowanie tak:

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

Jak mogę przekazać argumentowi bootfunc etykietę funkcji opakowania bez wywoływania jej? Coś jak to cpu_boot (ncores, my_wrapper, nterm); @Grzegorz Szpetkowski –

+0

@Lefteris Sarantaris: możesz przekazać wskaźnik funkcji jako jeszcze jeden parametr my_wrapper. Nie możesz zrobić "cpu_boot (ncores, my_wrapper, nterm)", chyba że 'my_wrapper' jest typu interrupt_handler - w takim przypadku nie będziesz miał opcji przekazania argumentów (argl, args itp.), Ponieważ interrupt_handler nie ma podejmij argumenty ... Myślę, że najbliżej można uzyskać 'my_wrapper (boot_task, boot_func, argl, args)' gdzie boot_func jest wskaźnikiem funkcji. –

1

Bardziej ogólne i wiele więcej flexable sposób ...

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; 
} 

Następnie można użyć opakowania w następujący sposób:

void boot(uint ncores, uint nterm, Task boot_task, int argl, void* args) 
{ 
    boot_data * data = malloc(sizeof *data); 
    //remember to memset if you arent going to fill out all variables! 
    data->argc = argl; 
    data->argv = args; 
    data->boot_task = boot_task; 
    data->handler = some_interrupt_handler; 

    cpu_boot(ncores, my_wrapper(data) , nterm); 

    free(data); 
}