J'ai déjà une base de code contenant du code répétitif, avec seulement des différences mineures, des identifiants sérialisables, des index, des tableaux variables.Utilisation de listes X et de directives de préprocesseur pour générer le code C configurable Au moment de la compilation
La base de code est énorme, et certains composants sont activés/désactivés sur la base de simples directives et constantes du préprocesseur (par exemple: #define CFG_PROJECT cfgAutobot
, #define CFG_PROJECT cfgUltron
, ..etc).
La fonctionnalité est effectivement la même, mais avec des composants et des conditions variables. Exemple:
int somedata;
int somecounter;
void main_loop(){
#if(CFG_PROJECT == cfgAutobot)
if(someInterface() == 1){
somedata = some_other_interface();
}
#endif
#if(CFG_PROJECT == cfgUltron)
if(third_if() > 0){
someCounter++;
}
else
{
someCounter = 0;
}
#endif
}
void query_data(int selector){
if(False){
/* Dummy block */
}
#if(CFG_PROJECT == cfgUltron)
else if(selector == 1){
return somedata;
}
#endif
#if(CFG_PROJECT == cfgAutobot)
else if(selector == 2){
return someCounter;
}
#endif
else{
return Err_code;
}
}
Parce que les données de ce code fonctionne avec est beaucoup plus compliqué, qu'un simple compteur et entier, implique plusieurs composants de différentes tailles, ces parties de code sont beaucoup plus compliquées. Cependant, ils peuvent être rattachés à une structure commune.
j'ai pu appliquer la technique de la liste X comme suit:
#define Ultron_implementation X(var_ultron, (someInterface() == 1), update_function_1, selector_id_1)
#define Autobot_implementation X(var_autobot, (third_if() > 0), update_function_2, selector_id_2)
/* (Please note, that this is a simplified example, in the actual
code there are much more components, but the `main_loop`
implementation can be traced back to a few update functions) */
void update_function_1(int var, int selector) {
if(selector == 1){
var++;
}else{
var = 0;
}
}
void update_function_2(int var, int selector) {
if(selector == 1){
var = some_other_interface();
}else{
/* Nothing to do */
}
}
#define X(var_name,condition,func_name,sel_id) int var_name;
Ultron_implementation
Autobot_implementation
#undef X
void main_loop(){
#define X(var_name,condition,func_name,sel_id) \
if(condition){ \
func_name(var_name, true);\
}else{ \
func_name(var_name, false);\
}
Ultron_implementation
Autobot_implementation
#undef X
}
void query_data(int selector){
if(False){
/* Dummy block */
}
#define X(var_name,condition,func_name,sel_id) \
else if(selector == sel_id){ \
return var_name;\
}
Ultron_implementation
Autobot_implementation
#undef X
else{
return Err_code;
}
}
Le problème avec cette est que malgré qu'il soit maintenant une mise en œuvre unifiée, l'introduction de nouveaux composants doit toujours copier -paste, et le filtrage via les constantes précédemment définies (c'est-à-dire: CFG_PROJECT
) est maintenant exclu de la logique.
est-il un moyen de minimiser le besoin de copier-coller dans divers endroits dans le code et filtrer en fonction des constantes définies (à savoir CFG_PROJECT
)?
Ce code n'est tout simplement pas bien conçu. L'utilisation de 'ifdef's partout est un signe que la fonctionnalité supplémentaire a été verrouillée comme une pensée après coup. Vous devriez regarder le noyau Linux qui réalise une quantité de configuration irréelle entre les fonctionnalités permettant de sélectionner différentes architectures. Oui, il y a 'ifdef's, mais pas autant qu'on pourrait s'y attendre, et pas souvent dans les fichiers C. –
La #define - configuration est en fait quelque chose qui ne pouvait pas être évité, c'est ce dont dépend une plus grande base de code. Il y a eu des demandes fonctionnelles supplémentaires qui ne sont pas mentionnées ici, bien sûr. Pour un exemple simple comme celui-ci, quelque chose de beaucoup plus simple est suggéré. –
Qu'est-ce que cela a à voir avec MISRA? Si vous avez besoin que le code soit conforme à MISRA, vous pouvez oublier tout ce désordre de macro laid. En outre, les commutateurs du compilateur '# ifdef' sont de loin beaucoup plus lisibles que les" x macros "et autres non-sens de méta-programmation. – Lundin