Converti la sintassi C ++ in obiettivo C
-
29-10-2019 - |
Domanda
La mia esperienza di fondo è C/C ++/C#.
Sto usando una libreria C ++ in un progetto Xcode (per essere specifico la libreria è PJSIP). Per usare la libreria devo collegare un paio di callback sul mio codice come questo:
Siptest.m
#include < pjsua-lib/pjsua.h >
static void on_reg_state(pjsua_acc_id acc_id)
{
// Do work
}
static void Init()
{
// pjsua_config and psjua_config_default are defined in the header file from pjsip
pjsua_config cfg;
psjua_config_default(&cfg);
cfg.cb.on_regstate = &on_reg_state;
}
Voglio cambiare questo Sytnax C ++ all'obiettivo C
così ho fatto:
+(void) on_reg_state:(pjsua_acc_id) acc_id
{
// Do work
}
+(void) Init
{
pjsua_config cfg;
psjua_config_default(&cfg);
cfg.cb.on_regstate = &on_reg_state; // ***** this is causing compile error
// I tried [CLASS NAME on_reg_state] and i get runtime error
}
Ho provato a cercare il delegato in Objective C ma non sono riuscito a trovare un caso simile in cui il callback è già implementato in C ++ e si desidera usarlo con la sintassi di Objective-C.
Grazie
Soluzione
Prima di tutto, non c'è assolutamente bisogno di convertire nulla. Va perfettamente bene chiamare le librerie C ++ da Objective-C.
In secondo luogo, ciò che causa l'errore del compilatore è che stai cercando di attaccare un metodo in un luogo in cui dovrebbe esserci un puntatore della funzione. Non è possibile eseguire un puntatore di funzione da un metodo Objective-C usando il &
Operatore. Tieni semplicemente il tuo on_reg_state()
Funzionalo e usalo come hai fatto prima, ecco anche i callback nei quadri basati su C di Apple (di cui avrai bisogno non appena vai oltre ciò che forniscono le API Objective-C di alto livello).
E in terzo luogo, il tuo + (void)Init
Il metodo sembra un po 'strano. Ti scoraggerei fortemente a scrivere un metodo chiamato Init
(capitalizzato). Se hai intenzione di scrivere un inizializzatore, dovrebbe essere - (id)init
, cioè minuscolo e ritorno id
. E non dimenticare di chiamare l'inizializzatore designato della sua superclasse, controlla il suo valore di ritorno, assegnarlo a sé e restituirlo alla fine del init
Metodo (vedi Implementazione di un inizializzatore in Documentazione di Apple Se non ne hai familiarità). E se il tuo metodo non è un inizializzatore, usa un nome diverso, ad esempio - (void)createConfig
.
Altri suggerimenti
In questo caso vorresti usare i selettori.
+(void) on_reg_state:(pjsua_acc_id) acc_id
{
// Do work
}
+(void) Init
{
pjsua_config cfg;
psjua_config_default(&cfg);
cfg.cb.on_regstate_selector = @selector(on_reg_state:);
cfg.cb.target = self; //Self here is the class object in your 'Init' method, which is poorly named.
//Use this like [cfg.cb.target performSelector:cfg.cb.on_regstate_selector withObject:...etc]
}