2014-12-15 25 views
5

Ben bu işlevi vardır:İşlev argümanında sarıcı işlevini kullanarak bir işaretçi işlevi nasıl iletilir?

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

ve ben bunun yerine pthread kullanmak Exec() kullanmanın istiyorum, bu yüzden cpu_boot aramak zorunda:

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

Bunlar parametre tipleri

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

denedim:

Fakat bu yanlış. Bunu nasıl uygulayabilirim?

+0

iki değişken olduğundan: PT [] ve sonrakiproc tanımlanmamış (bunlar genel değişkenler midir?) Birkaç sorun daha vardır: 1) C 2'de bir sonraki işlevler olamaz) typedef ifadelerinin "sondaki" bir adı olması gerekir. typedef başvurmak için kullanın. 3) bu: typedef void interrupt_handler(); kesme işlevi için geçerli bir prototip değildir. Bu: typedef void interrupt_handler (void); interrupt fonksiyonları hiç bir zaman çağrılmadıkları için parametreler içinde geçemezler. – user3629249

+0

@ user3629249: İki yazım hatası 'Tamam'; typedeflerin adları 'interrupt_handler' ve' Task' dir. 'Interrupt_handler' tanımı kabul edilebilir argümanları belirtmeli veya işlev argüman almazsa 'void' değerini belirtmelidir, ancak bu (nispeten) küçük bir sorundur. Normalde normalde kullanılan pthreads öğelerinin kullanıldığı standart sinyal işleyicileri, void (* işleyici) (int signum) türüne sahiptir; - işlev bir argüman alır. Sinyal işleyicileri ve kesme işleyicileri denir; Hiç çağrılmadıkları takdirde anlamsız olurlar. –

cevap

2

Böyle bir şey istersiniz:

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

Sonra bu gibi kapsayıcı kullanabilir:

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

Argüman işlevinde etiketini çağırmadan argüman bootfunc etiketinde nasıl geçebilirim ?? Böyle bir şey cpu_boot (ncores, my_wrapper, nterm); @Grzegorz Szpetkowski –

+0

@Lefteris Sarantaris: fonksiyon göstergesini my_wrapper'ın bir başka parametresi olarak geçebilirsiniz. 'My_wrapper' türünde interrupt_handler yoksa' cpu_boot (ncores, my_wrapper, nterm) 'yapamazsınız - bu durumda, herhangi bir argüman (argl, args vb.) Aktarma seçeneğine sahip olmazsınız çünkü interrupt_handler argümanlar al ... Ben en yakın bulabilirim 'my_wrapper (boot_task, boot_func, argl, args)' 'boot_func bir fonksiyon göstericisidir. –

1

Bir daha genel ve çok daha flexable yolu ...

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

Daha sonra sargınızı şu şekilde kullanabilirsiniz:

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); 
} 
İlgili konular