2010-05-09 13 views
6

J'ai un projet C++ qui utilise un analyseur C bison. L'analyseur C utilise une struct de pointeurs de fonction pour appeler des fonctions qui créent propres nœuds AST lorsque les productions sont réduites de bison:C fonctions de rappel définies dans un espace de noms sans nom?

typedef void Node; 
struct Actions { 
    Node *(*newIntLit)(int val); 
    Node *(*newAsgnExpr)(Node *left, Node *right); 
    /* ... */ 
}; 

Maintenant, dans la partie C++ du projet, je remplis ces pointeurs

class AstNode { 
    /* ... */ 
}; 
class IntLit : public AstNode { 
    /* ... */ 
}; 

extern "C" { 
    Node *newIntLit(int val) { 
    return (Node*)new IntLit(val); 
    } 

    /* ... */ 
} 

Actions createActions() { 
    Actions a; 
    a.newIntLit = &newIntLit; 
    /* ... */ 
    return a; 
} 

Maintenant, la seule raison pour laquelle je les mets dans extern "C" est parce que je veux qu'ils aient des conventions d'appel C. Mais de manière optimale, je voudrais que leurs noms soient encore mutilés. Ils ne sont jamais appelés par le nom du code C, ainsi le mangling de nom n'est pas un problème. Les avoir écrasés évitera les conflits de noms, puisque certaines actions sont appelées comme error, et la fonction de rappel C++ a des noms laids comme suit juste pour éviter les conflits de noms avec d'autres modules.

extern "C" { 
    void uglyNameError(char const *str) { 
    /* ... */ 
    } 

    /* ... */ 
} 

a.error = &uglyNameError; 

je me suis demandé si cela pourrait être possible en donnant simplement la liaison de type fonction C

extern "C" void fty(char const *str); 
namespace { 
    fty error; /* Declared! But i can i define it with that type!? */ 
} 

Toutes les idées? Je suis à la recherche de solutions Standard-C++.

+0

Vous ne pouvez pas compiler la sortie Bison en tant que code C++, évitant ainsi le problème tout à fait? –

+0

@Konrad mon collègue a dit que le mode Bison C++ n'est pas agréable à travailler, et donc nous faisons cette partie avec du C pur et l'avons abstrait, de sorte que le scanner constitue une bibliothèque C pure. –

Répondre

3

Je ne comprends pas le problème. Le mot-clé extern n'affecte pas la convention d'appel, simplement le nom présenté à l'éditeur de liens. Une fonction écrite en C++ qui n'est pas une méthode d'instance est toujours __cdecl, avec ou sans extern "C". De plus, tant que vous gardez createActions() dans le même fichier de code source, ces fonctions n'ont pas besoin de liaison externe. Vous pouvez les déclarer statiques ou les placer dans un espace de noms sans nom pour éviter les collisions.

+2

Ah, je pourrais faire alors «statique». Bonne idée, pourquoi n'y ai-je pas pensé :) Je ne pensais qu'aux espaces de noms sans nom, mais cela ne ferait rien à leur lien et n'empêcherait pas les conflits pour les fonctions C "' extern ". Mais 'static' pourrait réellement fonctionner! Pour les parties restantes de votre réponse: Cela peut faire la différence d'appeler convention si la mise en œuvre le souhaite. Je ne voulais pas dépendre d'une implémentation particulière, donc je les ai fait 'extern 'C" '. –