Mon projet actuel est une bibliothèque de taille moyenne qui doit avoir une interface C et C++ en même temps. Il est centré sur un seul type de données que je veux être accessible depuis les fonctions C et C++, parce que je veux encourager les tiers à étendre la bibliothèque en écrivant des fonctions dans les deux langues.Comment concevoir une bibliothèque avec des interfaces parallèles en C et C++
Je sais sur les bases de C/C++ mélange (comparer par exemple http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html) et ont mis au point la solution suivante:
Mes centres de conception de base autour de la création d'une struct en C avec toutes les données exposées (ce qui est ce que mes programmeurs en C attendent) et en dériver une classe qui cache l'accès des membres, ce qui, espérons-le, conduira à un accès plus sûr à la structure pour les programmeurs C++. Le problème vient avec la dérivation: Je veux utiliser les espaces de noms en C++ et cacher l'interface C. Bien sûr, la structure C elle-même ne peut pas être cachée (sans recourir à l'idiome PIMPL), mais ça me convient. L'exemple de code suivant compile et s'exécute sans erreurs apparentes avec les programmes "client" C et C++. Cependant, je me demande si cette solution est valide ou s'il existe de meilleures solutions.
code Exemple:
#ifdef __cplusplus__
extern "C" {
#endif
struct base
{
char * data;
}
#ifdef __cplusplus__
} // extern "C"
namespace {
extern "C" {
#endif
/* cleanly initialize struct */
struct base * new_base (struct base *);
/* cleanly destroy struct */
void del_base (struct base *);
#ifdef __cplusplus__
} } // namespace, extern "C"
#include<new>
namespace safe {
class base_plus : private base
{
public:
base_plus()
{
if (! new_base(this))
throw std::bad_alloc();
}
~base_plus()
{
del_base (this);
}
};
} // namespace safe
#endif
Merci beaucoup @ matthieu-m. C'est une approche très sensée et vous avez raison sur ses avantages. Malheureusement, il faut que le côté C utilise des méthodes accesseur pour obtenir/définir les données de la propriété - ce que mes utilisateurs n'accepteront pas: -/ –
@MarkAsbach: Eh bien, au lieu d'un 'void *' vous pouvez remplir un 'struct' si vous le souhaitez ... mais vous ne pouvez pas appliquer d'invariants avec une structure' '' 'et la compatibilité binaire sort de la fenêtre. –