2010-05-03 3 views
9

J'ai une bibliothèque C héritée, écrite sous une forme de type OO. Les fonctions typiques sont comme:Ecriture d'un wrapper C++ pour une bibliothèque C

LIB *lib_new(); 
void lib_free(LIB *lib); 
int lib_add_option(LIB *lib, int flags); 
void lib_change_name(LIB *lib, char *name); 

Je voudrais utiliser cette bibliothèque dans mon programme C++, donc je pense un C++ emballage est nécessaire. ci-dessus sembleraient tout à la carte quelque chose comme:

class LIB 
{ 
    public: 
     LIB(); 
     ~LIB(); 
     int add_option(int flags); 
     void change_name(char *name); 
... 
}; 

Je ne l'ai jamais écrit un C++ autour wrapper C avant, et ne peut pas trouver beaucoup de conseils à ce sujet. Est-ce une bonne/typique/sensible à la création d'un wrapper C++/C?

Répondre

8

Un wrapper C++ n'est pas requis - vous pouvez simplement appeler les fonctions C à partir de votre code C++. À mon humble avis, il est préférable de ne pas envelopper le code C - si vous voulez le transformer en code C++ - très bien, mais faites une réécriture complète.

Pratiquement, en supposant que vos fonctions C sont déclarées dans un fichier appelé myfuncs.h puis dans votre code C++ vous voulez les inclure comme ceci:

extern "C" { 
    #include "myfuncs.h" 
} 

afin de leur donner la liaison C lorsqu'il est compilé avec le compilateur C++.

+0

Ne vous répétez pas? –

+0

@Neil: Ne pas être combatif? –

+6

Je ne suis pas d'accord (mais pas de downvote). Pour les librairies C simples, un wrapper est souvent inutile. Cependant, pour les librairies C plus compliquées, un wrapper C léger peut être inestimable. Un exemple me vient à l'esprit: Tibco a un emballage très léger autour de Tibrv, ce qui est extrêmement utile. –

2

Je pense qu'il est logique d'écrire un wrapper si cela rend l'utilisation de la bibliothèque plus simple. Dans votre cas, il est inutile de passer un LIB *, et il est probable qu'il sera possible de créer des objets LIB sur la pile, donc je dirais que c'est une amélioration.

+0

Il est toujours nécessaire de passer des objets LIB :: LIB autour. Et l'allocation d'objets LIB :: LIB sur la pile ne vous donnera qu'une sémantique automatique, car probablement un nouvel objet C LIB sera alloué sur le tas dans la construction. Mais malgré cela, le wrapper C++ est toujours pratique. –

2

C'est généralement comme ça que je l'aborderais. Je n'utiliserais pas non plus char * mais j'utiliserais std :: string.

1

Une enveloppe C++ n'est pas nécessaire en soi. Rien ne vous empêche d'appeler les fonctions C dans votre code.

1

Je regarde aussi renommer LIB quelque chose d'un peu mieux, si rien d'autre « Lib »

Changer le nom est susceptible d'être un poseur getter ...

si GetName (char *) SetName (char *)

puis de le remplacer par std :: string au lieu de char *, si son nom SetName (const std :: string name) accepte un caractère * comme paramètre.

-à-dire, lentement passer à C++ ismes

5

D'habitude, je ne gravez qu'une simple enveloppe RAII au lieu d'envelopper chaque fonction de membre:

class Database: boost::noncopyable { 
    public: 
    Database(): handle(db_construct()) { 
     if (!handle) throw std::runtime_error("..."); 
    } 
    ~Database() { db_destruct(handle); } 
    operator db_t*() { return handle; } 
    private: 
    db_t* handle; 
}; 

Avec l'opérateur de conversion de type, cela peut être utilisé avec le C fonctions:

Database db; 
db_access(db, ...); // Calling a C function with db's type conversion operator