2009-02-17 2 views
4

Je dois importer/traduire le code d'une classe C++ pour pouvoir l'utiliser dans un programme C.Meilleure façon d'utiliser une seule classe C++ dans un programme C

Le programme C est volumineux et possède de nombreuses dépendances sur les bibliothèques C ouvertes et fermées.

Le fichier de classe Cpp C++ est de 650 lignes

Je n'ai pas l'expérience de mélange C et C++ de sorte que même si je l'ai regardé un guide sur la façon de le faire, je ne suis pas convaincu quel chemin à parcourir.

Je ne dois utiliser le code C++ dans quelques endroits (assez de useage isolé

J'utilise gcc (gcc/g ++)

Il est un environnement linux

Alors, que dois-je doivent faire pour l'importer? et il moins de temps que la traduction?

Merci,

Mike

Répondre

6

Vous devez créer des fonctions en C++ qui sont « extern « C » », donc ils sont appelables de C.

Vous pouvez obtenir OO en faisant le ce pointeur explicite (et de type void *), la implémentation de la conversion du pointeur et transfert vers la fonction membre réelle.

5

Dans votre code C++, vous devez utiliser la extern « C » construire pour charger le compilateur/éditeur de liens pour générer la liaison compatible afin que le code C peut appeler votre code C++.

extern "C" 
{ 
    void my_function_that_can_be_called_from_c() 
    { 
     // ... 
    } 
} 

code C ne sait rien sur les objets, de sorte que vous ne pouvez pas utiliser facilement des objets C++ de C. Une technique courante consiste à manipuler des objets C++ dans la fonction « externed ».

11

Hmm, 650 lignes n'est pas trop long - je le réécrirais. Vous allez probablement passer au moins autant de temps à essayer de l'envelopper, et vous pouvez trouver difficile de maintenir le résultat.

1

Si vous voulez transformer la classe C++ en une bibliothèque partagée Linux accessible à vos programmes C, this answer à une question précédente vous montre comment avec un petit exemple de classe.

5

Supposons que vous avez la classe C++ suivante:

#if __cplusplus // only C++ programs see this part of foo.h 

class foo { 
public: 
    // a couple constructors 
    foo(); 

    foo(int); 

    // and a couple methods 
    bool dosomething(); 
    bool doSomethingElse(std::string const&); 

private: 
    // a bunch of private stuff which is immaterial to the C interface 
} 

#endif 

Ce que vous pouvez faire est d'avoir un ensemble de fonctions C-appelable qui enveloppent l'interface C++:

// both C and C++ programs can see this part of foo.h 

#if __cplusplus // but C++ programs need to know that no name mangling should occur 
extern "C" { 
#endif 

struct CFoo_struct; 
typedef struct CFoo_struct foo_t; // used as a handle to a foo class pointer 

// constructors 

foo_t* CreateFoo(void); 
foo_t* CreateFoo_int(int); 

int CFooDoSomething(foo_t*); 
int CFooDoSomethingElse(foo_t*, char const*); 

#if __cplusplus 
}    // end the extern "C" block 
#endif 

Ensuite, la mise en œuvre foo .cpp pourrait ressembler à quelque chose comme:

// in foo.cpp 
extern "C" { 

    struct CFoo_struct { 
    }; 


    // constructors 

    foo_t* CreateFoo(void) 
    { 
     foo* pFoo = new Foo; 

     // a bit of ugliness - the need for this cast could be 
     // avoided with some overhead by having the foo_t 
     // struct contain a foo* pointer, and putting a foo_t 
     // structure inside the foo class initialized with 
     // the this pointer. 

     return reinterpret_cast<foo_t*>(pFoo); 
    } 

    // something similar for CreateFoo_int()... 



    // method wrappers 

    int CFooDoSomethingElse(foo_t* pHandle, char const* s) 
    { 
     foo* pFoo = reinterpret_cast<foo*>(pHandle); 

     std::string str(s); 

     return pFoo->doSomethingElse(str); 
    } 

    // something similar for CFooDoSomething() 

} // end extern "C" block 
1

Il y a plusieurs choses que vous pouvez faire.

Vous pouvez le réécrire en C. Sans réellement voir le code, je ne sais pas combien de problèmes ce serait.Beaucoup de code C++ est simplement C avec quelques addons, et certains font un usage intensif des templates et des fonctions surchargées et autres. Si vous ne faites pas cela, vous devez le faire communiquer avec C. Cela signifie fournir une interface pour C, et l'entourer de extern "C"{ ... } afin que le compilateur C++ sache rendre l'interface compatible C. Encore une fois, sans savoir quelque chose du code C++, je ne peux pas dire combien de travail ce serait. Vous aurez besoin de l'encapsuleur pour l'une des solutions suivantes.

Vous pouvez en faire un projet C++, entourer chaque fichier C avec extern"C" { ... }, et le lier simplement. Si vous avez des fichiers C++, la compilation entière doit être C++.

Vous pouvez faire une bibliothèque séparée pour être liée à.

Ce que vous ne pouvez pas faire est de compiler C et C++ avec une fonction principale de C(), ou avec un compilateur C. C++ est plus exigeant, et nécessite plus de la fonction main().

Vous pouvez toujours essayer de recompiler les fichiers C que vous utilisez en C++ et d'envelopper les fichiers .h pour les bibliothèques dans extern "C" { ... }. Le C90 bien écrit n'est pas si loin d'être un C++ légal (bien que le standard C99 s'en soit éloigné), et le compilateur signale tout problème de conversion que vous trouvez.

Laquelle de ces propositions est la meilleure pour vous? Des questions telles que: Quelle est la facilité de conversion du code C++? Est-ce facile d'écrire un wrapper C pour la fonctionnalité C++ que vous voulez? Combien de modifications voulez-vous apporter au code C? À quel point êtes-vous familier avec la création d'une bibliothèque Linux?

Questions connexes