GUI - scambio di dati del motore, progettazione con C, getter o passaggi di puntatori di struct?

0

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).

  1. 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.

  2. 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])
    
posta JustMe 12.05.2016 - 23:32
fonte

0 risposte

Leggi altre domande sui tag