Con codebase e librerie esterne piuttosto grandi, nell'applicazione C,
quali sarebbero i pro e i contro di due approcci (o suggerire altri):
(supponete che ci siano NESSUNA api richieste per questo)
Modifica dal commento: l'obiettivo è selezionare un approccio più gradevole a lungo termine - per la manipolazione di "alcuni elementi" dal motore ecc., dove "alcuni elementi" potrebbero appartenere alla GUI o ad altri moduli (entrambi concettualmente, da un altro modulo di traduzione, separati per metterlo in una parola).
-
passa il puntatore a struct contenente vari puntatori per "alcune etichette, pulsanti, ecc.", al motore, e in seguito = a ogni funzione del motore che deve manipolare quegli elementi.
-
mantieni le maniglie statiche globali su "alcune etichette, pulsanti, ecc." in gui_help.c, inizializzate da gui - e fornisci loro l'accesso con qualche getter ("nome_what") esposto da gui_help.h
Esempio minimo (rimossi custodi di intestazione, gestione di mem, verifiche di errori, ecc.):
Scorri sotto per uno snipplet Python veloce per configurare l'esatto di sotto localmente.
// ## main.c ##
#include "gui.h"
int main(int argc, char *argv[]){
gui();
return 0;
}
// ## gui.h ##
void gui();
typedef struct { int many_variables_and_pointers; } gui_struct;
// ## gui.c ##
#include "gui.h"
#include "gui_help.h"
#include "engine.h"
void gui(){
gui_struct gs;
gs.many_variables_and_pointers = init_a_from_gui_help();
//gs.other_variables_and_pointers = init_b_from_gui_help();
//...foo, bar
// engine callbacks are registered here.
// GUI LOOPS here in engine event loop, other threads handle user interaction.
engine_loop();
}
// ## gui_help.h ##
init_a_from_gui_help();
//init_b_from_gui_help();
// ## gui_help.c ##
int init_a_from_gui_help(){
return 42;
}
// ## engine.h ##
void engine_loop();
void some_engine_callback_example_1(void* data);
void some_engine_callback_example_2();
// ## engine.c ##
void engine_loop(){
volatile int a;
while(1){
a = 1;
}
printf("%d", a);
}
void some_engine_callback_example_1(void* data){
// data->some_gui_element->manipulate();
// would require initializing struct data with gui elements,
// and passing pointer to this struct from engine to any other call,
// possibly nesting several stack levels, limiting somewhat "encapsulation"
// Possible synchronization issues as well?
}
void some_engine_callback_example_2(){
// my_local_gui_element_pointer_copy = getter("label1");
// my_local_gui_element_pointer_copy.manipulate();
// would require #include "gui_help.h", exposing api,
// and keeping static global handles to labels, buttons, etc.
}
Snipplet Python per configurarlo localmente, compattato per evitare di scorrere questa pagina ancora di più.
# Python - THIS CODE GENERATES ABOVE STRUCTURE, for easier browsing. Run in new dir.
a = ["main.c", "gui.h", "gui.c", "gui_help.h", "gui_help.c", "engine.h", "engine.c"]
main_c = """ #include "gui.h"\nint main(int argc, char *argv[]){\ngui();\nreturn 0;\n}"""
gui_h = """void gui();\ntypedef struct {int many_variables_and_pointers;} gui_struct;"""
gui_c = """#include "gui.h"\n#include "gui_help.h"\n#include "engine.h"\nvoid gui(){\n
gui_struct gs;\ngs.many_variables_and_pointers = init_a_from_gui_help();\n
\n//gs.other_variables_and_pointers = init_b_from_gui_help();\n//...foo, bar\n// engine callbacks are registered here.\n// GUI LOOPS here in engine event loop, other threads handle user interaction.\nengine_loop();\n}"""
gui_help_h = """init_a_from_gui_help();\n//init_b_from_gui_help();"""
gui_help_c = """int init_a_from_gui_help(){\n return 42;\n}"""
engine_h = """void engine_loop();\nvoid some_engine_callback_example_2();\nvoid some_engine_callback_example_1(void* data);"""
engine_c = """void engine_loop(){\n\tvolatile int a;\n\twhile(1){\n\t\ta = 1;\n\t}\n\tprintf("%d", a);\n}\nvoid some_engine_callback_example_1(void* data){\n\t// data->some_gui_element->manipulate();\n\t// would require initializing struct data with gui elements,\n\t// and passing pointer to this struct from engine to any other call,\n\t// possibly nesting several stack levels, limiting somewhat "encapsulation"
\n\t// Possible synchronization issues as well?\n\t}\nvoid some_engine_callback_example_2(){\n\t// my_local_gui_element_pointer_copy = getter("label1");\n\t// my_local_gui_element_pointer_copy.manipulate();\n\t// would require #include "gui_help.h", exposing api, \n\t// and keeping static global handles to labels, buttons, etc.\n\t}"""
b = [main_c, gui_h, gui_c, gui_help_h, gui_help_c, engine_h, engine_c]
for i, filename in enumerate(a):
with open(filename, 'w') as file_:
file_.write(b[i])