2009-07-24 9 views
2

J'essaye de changer le comportement de certaines fonctions dans C avec l'aide du préprocesseur; et également ajouter des paramètres facultatifs qui peuvent être activées ou désactivées ...C décorateurs de fonction (wrappers) à la compilation

Le modèle de base pour les paramètres facultatifs est facile:

#ifdef OPT_PARAM 
    #define my_func(a, b, opt) _my_func(a, b, opt) 
#else 
    #define my_func(a, b, opt) _my_func(a, b) 
#endif 

/*the rest of the code always calls "my_func" with all the params 
and not the underscored version...*/ 

#ifdef OPT_PARAM 
void _my_func(int a, int b, int opt) 
#else 
void _my_func(int a, int b) 
#endif 
{ 
    /*... more #ifdefs surrounding opt uses */ 
} 

le motif pour envelopper une fonction est conditionnelle similaire, mais le problème est que les traits de soulignement commencent à s'accumuler (un supplémentaire pour chaque niveau d'imbrication, qui peut être une fonction différente ou juste une # définition pour le niveau suivant au cas où il n'est pas encapsulé).

Donc, des idées sur la façon de réduire la complexité du code ici?

P.S. Je serais prêt à utiliser Python ... mais c'est pour un pilote :-(

+0

Vous êtes sûr de ne pas vouloir de fonctions variées? http://en.wikipedia.org/wiki/Varargs#Variadic_functions_in_C.2C_Objective-C.2C_C.2B.2B.2C_and_D – Inshallah

+0

À peu près sûr que je ne les veux pas!^_^Je les ai déjà utilisés et je suis très préoccupé par la perte de contrôle de type statique. – fortran

+1

Peut-être qu'il me manque quelque chose, mais cela me semble bien. Où est la complexité supplémentaire? Et qu'est-ce qui est imbriqué? –

Répondre

0

En fin de compte, je viens d'ajouter un nouveau décorateur qui a traité de façon uniforme les paramètres supplémentaires et a changé les underscores obscurs par des noms plus descriptifs.

Maintenant, c'est un design plus orthogonal dans lequel je peux brancher et débrancher le comportement au moment de la compilation sans temps d'exécution.

2

On dirait que vous voulez utiliser des arguments par défaut ou quelque chose qui n'est pas disponible en C. Cela semble être une mauvaise idée. pas gérer les choses d'une façon plus C, où si vous ne voulez pas spécifier un argument que vous venez de passer NULL ou -1 (standard).

void function (int a, int b, int c) { 
    if (c != -1) { 
    // something 
    } 
} 

function(a,b,-1); 
function(a,b,c); 
+0

C'est à des fins de débogage; Je dois me débarrasser des paramètres supplémentaires dans la construction finale ... et de toute façon, cela ne résout pas le problème des wrappers d'imbrication: -s – fortran

+0

Je pense qu'il essaie d'utiliser des paramètres optionnels. Si c'est le cas, appelez my_func (a, b, opt) sinon appelez my_func (a, b). – Gert

+0

@fortran: Pourquoi avez-vous besoin d'un nid? Avez-vous plus de deux versions (débogage et final) de chaque fonction? – Christoph

1

Je pense que cela peut être plus proche de ce que vous voulez, mais D'après ce que je comprends, l'idée est d'autoriser les fonctions c avec des nombres arbitraires d'arguments, qui sont vérifiés par type et qui peuvent être éliminés au moment de la compilation

Permettez-moi de vous avertir de l'utilisation de scores dans les identifiants, en citant la norme. Vous pouvez rencontrer un identifiant réservé. Cependant, la probabilité de ceci est inconnue à moi.

ISO/IEC 9899: 1999 (E) 7.1.3

- Tous les identifiants qui commencent par un trait de soulignement et soit une lettre majuscule ou un autre trait de soulignement sont toujours réservé pour toute utilisation.

Cette solution nécessite GCC. La version de GCC doit également prendre en charge les symboles faibles. L'idée est de permettre au compilateur de rechercher la bonne définition de fonction en utilisant des symboles faibles. De plus le contenu de la fonction sont simplifiées en utilisant les connaissances que le compilateur doit élaguer les branches mortes, à savoir:

if (0) { ... } 

au moment de la compilation sans autre analyse (GCC 4.x fait sans doute). En définissant les paramètres facultatifs inexistants comme des symboles de c pré-processeur (cpp), vous pouvez éviter d'avoir des conditions cpp dans le corps de la fonction (si vous le souhaitez). Voyez comment opt1 et opt2 sont définis pour f_opt0 ci-dessous.

#include <assert.h> 
#include <stdio.h> 

extern void f_opt0(int a, int b) __attribute__((weak)); 
extern void f_opt1(int a, int b, int opt1) __attribute__((weak)); 
extern void f_opt2(int a, int b, int opt1, int opt2) __attribute__((weak)); 

#ifdef OPT0 
void f_opt0(int a, int b) { 
#define opt1 0 
#define opt2 0 
#endif 
#ifdef OPT1 
void f_opt1(int a, int b, int opt1) { 
#define opt2 0 
#endif 
#ifdef OPT2 
void f_opt2(int a, int b, int opt1, int opt2) { 
#endif 
    if (opt1) printf("opt1=%d\n", opt1); 
    if (opt2) printf("opt2=%d\n", opt2); 
    printf("a+b=%d\n", a+b); 
    #undef opt1 
    #undef opt2 
} 

#define f(a, b, o1, o2) \ 
    if (f_opt2) f_opt2(a, b, o1, o2); \ 
    else if (f_opt1) f_opt1(a, b, o1); \ 
    else if (f_opt0) f_opt0(a, b); \ 
    else { assert(0 && "no f() defined!"); } 

int main(void) { 
    f(1, 2, 1, 1); 
    return 0; 
} 

Mon test était très limité, et je ne préconise pas cela comme une bonne conception en C. Il semble sujette à des problèmes et est gênant pour comprendre. Cependant, j'espère que cela répond à vos objectifs.

2

Pouvez-vous utiliser un compilateur C++? Vous pouvez utiliser (des fonctionnalités C++) juste surcharge.

Une autre option est

#ifdef OPT_PARAM 
# define OPT(X) , X 
#else 
# define OPT(X) 
#endif 

int my_func(int a, int b OPT(int opt)) { 
#ifndef OPT_PARAM 
    int opt = default_value; 
#endif 
    ... // Rest of code 
} 


... 
// calling it 
my_func(2, 4 OPT(42)); 
Questions connexes