J'ai une bibliothèque C ++ qui fournit diverses 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 le code C et le code C ++ en même temps.
J'utilise la chaîne d'outils 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 n'est techniquement pas possible?
Y a-t-il des problèmes auxquels je dois faire attention?
Existe-t-il des ressources, des exemples de code et / ou de la documentation disponibles à ce sujet?
Quelques autres choses que j'ai découvertes:
- 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
- Conservez les "vraies" interfaces C ++ dans des fichiers d'en-tête séparés qui ne sont pas inclus par C. Pensez au principe PIMPL ici. Utiliser des
#ifndef __cplusplus #error
trucs aide ici à détecter toute folie. - Attention aux identifiants C ++ en tant que noms dans le code C
- Enums variant en taille entre les compilateurs C et C ++. Probablement pas un problème si vous utilisez la chaîne d'outils GNU, mais soyez prudent.
Pour les structures, suivez la forme suivante afin que C ne soit pas confus.
typedef struct X { ... } X
Ensuite, utilisez des pointeurs pour faire passer les objets C ++, il suffit de les déclarer en C comme struct X où X est l'objet C ++.
Tout cela est une gracieuseté d'un ami qui est un assistant en C ++.
Réponses:
Oui, c'est certainement possible. Vous devrez écrire une couche d'interface en C ++ qui déclare des fonctions avec
extern "C"
:Ensuite, vous appellerez
foo()
depuis votre module C, qui passera l'appel à larealFoo()
fonction implémentée en C ++.Si vous avez besoin d'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.
la source
extern "C"
être placé uniquement dans les déclarations (et non dans les définitions)? Parce que vous avez mentionné «la couche qui déclare les fonctions», mais votre exemple de code est également une définition. En d'autres termes, devrions-nous le placer dans des fichiers d'en-tête ou des fichiers source? (Ou les deux?)extern "C"
y mettre . Votre compilateur vous dira si vous devez également le mettre sur la définition.FAQ C ++ Lite: "Comment mélanger du code C et C ++" .
Certains pièges sont décrits dans les réponses à ces questions:
la source
Main gotcha: les exceptions ne peuvent pas être interceptées en C. S'il y a la possibilité qu'une exception se produise dans le code C ++, écrivez votre code C ou vos wrappers C ++ très soigneusement. Inversement, des mécanismes de type exception (ie, longjump) dans le code C (comme on le trouve dans divers langages de script) ne sont pas nécessaires pour appeler des destructeurs pour les objets C ++ sur la pile.
la source
vous pouvez mélanger du code C / C ++. Si votre fonction main () est en C ++, il vous suffit de vous assurer que vos fonctions c sont déclarées
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 n'arrivera 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.
la source