web-dev-qa-db-fra.com

Utilisation de la bibliothèque C ++ dans le code C

J'ai une bibliothèque C++ qui fournit différentes classes pour gérer les données. J'ai le code source de la bibliothèque.

Je souhaite étendre l'API C++ pour prendre en charge les appels de fonction C afin que la bibliothèque puisse être utilisée avec du code C et du code C++ en même temps.

J'utilise GNU (gcc, glibc, etc.), donc la prise en charge du langage et de l'architecture n'est pas un problème.

Y a-t-il des raisons pour lesquelles cela techniquement n'est pas possible?

Existe-t-il des gotcha's que je dois surveiller?

Existe-t-il des ressources, des exemples de code et/ou de la documentation à ce sujet?


Quelques autres choses que j'ai découvertes:

  1. Utilisez ce qui suit pour encapsuler vos en-têtes C++ qui doivent être utilisés par le code C.
#ifdef __cplusplus
extern "C" {  
#endif  
//  
// Code goes here ...  
//  
#ifdef __cplusplus  
} // extern "C"  
#endif
  1. Conservez les "vraies" interfaces C++ dans des fichiers d'en-tête séparés qui ne sont pas inclus par C. Pensez principe PIMPL ici. En utilisant #ifndef __cplusplus #error stuff aide ici à détecter toute folie.
  2. Attention aux identifiants C++ en tant que noms dans le code C
  3. Enums de taille variable entre les compilateurs C et C++. Ce n'est probablement pas un problème si vous utilisez la chaîne d'outils GNU, mais tout de même, soyez prudent.
  4. Pour les structures, suivez le formulaire suivant afin que C ne soit pas confondu.

    typedef struct X { ... } X
    
  5. Ensuite, utilisez des pointeurs pour faire circuler les objets C++, ils doivent simplement être déclarés en C comme struct X où X est l'objet C++.

Tout cela est gracieuseté d'un ami qui est un assistant de C++.

96
Misha M

Oui, c'est certainement possible. Vous devrez écrire une couche d'interface en C++ qui déclare des fonctions avec extern "C":

extern "C" int foo(char *bar)
{
    return realFoo(std::string(bar));
}

Ensuite, vous appellerez foo() depuis votre module C, qui passera l'appel à la fonction realFoo() qui est implémentée en C++.

Si vous devez exposer une classe C++ complète avec des membres de données et des méthodes, vous devrez peut-être faire plus de travail que cet exemple de fonction simple.

66
Greg Hewgill

C++ FAQ Lite: "Comment mélanger le code C et C++" .

Certains pièges sont décrits dans les réponses à ces questions:

  • [32.8] Comment puis-je passer un objet d'une classe C++ vers/depuis une fonction C?
  • [32.9] Ma fonction C peut-elle accéder directement aux données d'un objet d'une classe C++?
22
Alex B

Gotcha principal: les exceptions ne peuvent pas être interceptées en C. S'il y a la possibilité d'une exception dans le code C++, écrivez votre code C ou vos wrappers C++ très soigneusement. Inversement, les mécanismes de type exception (c'est-à-dire, longjump) dans le code C (comme on le trouve dans divers langages de script) ne sont pas requis pour appeler des destructeurs pour les objets C++ sur la pile.

11
ejgottl

vous pouvez mélanger du code C/C++. Si votre fonction main () en C++, il vous suffit de vous assurer que vos fonctions c sont déclarées

extern "C"

Si votre principal est C, alors vous êtes probablement OK sauf pour les variables statiques. Tous les constructeurs avec vos variables statiques sont censés être appelés avant le démarrage de main (). Cela ne se produira pas si C est votre principal. Si vous avez beaucoup de variables statiques, la meilleure chose à faire est de remplacer les variables statiques par des singletons.

3
David Nehme