Accueil
Rechercher:
sur developpez.com sur les forums
Forums | Tutoriels | F.A.Q's | Participez | Hébergement | Contacts
Club Emploi Blogs   TV   Dév. Web PHP XML Python Autres 2D-3D-Jeux Sécurité Windows Linux PC Mac
Accueil Conception Java DotNET Visual Basic  C  C++ Delphi MS-Office SQL & SGBD Oracle  4D  Business Intelligence
FORUMS C FAQs C TUTORIELS C LIVRES C COMPILATEURS C SOURCES GTK+
1
 

 

UTILISATION DE SOURCES EN C++ DANS UN PROGRAMME EN C

 

 

 

 

INTRODUCTION

 

Le présent document explique comment utiliser des classes C++ dans un programme écrit en C et compilé avec gcc sous Linux, Unix etc...

Le cas peut se présenter par exemple lorsque des fonctionnalités ont été écrites en C++ dans le cadre d'un autre projet et seraient réutilisable dans un nouveau projet écrit en C par une tierce personne. plutôt que de réécrire entièrement l'une ou l'autre les parties, il est possible de rassembler toutes les sources C++ dans une librairie spécifique offrant une interface pour les sources de l'application écrite en C.

1.     CREATION DES FICHIERS DE LA LIBRAIRIE C++

Nous allons dans un premier temps créer un répertoire mylib et dans ce répertoire nous allons créer deux fichiers simples que nous nommerons (par exemple) mylibtest.cpp et mylibtest.h

 

mylibtest.cpp contiendra le code suivant :

 

#include "mylibtest.h"

 

#include <iostream>

 

void helloWorld()

{

     std::cout << "hello" << std::endl;

}

 

et mylibtest.h contiendra celui-ci :

 

#ifndef MYLIBTEST_H

#define MYLIBTEST_H

 

void helloWorld();

 

#endif

 

 

donc le répertoire mylib contiendra :

 

mylibtest.cpp

mylibtest.h

2.     COMPILATION DE LA LIBRAIRIE C++

Placons-nous dans le répertoire mylib et compilons sans édition de liens (option –c) le(s) fichier(s) de la librairie

 

g++ -c mylibtest.cpp

 

ou bien

 

find . –name "*.cpp" –exec g++ -c ‘{}’ \;

 

si plusieurs fichiers .cpp sont à compiler.

 

Il doit y avoir maintenant y avoir autant de fichiers objets (avec extension .o) que de fichier .cpp et chacun d’eux doit porter le même nom que le fichier .cpp auquel il se rapporte.

 

Dans notre exemple, le répertoire mylib contiendra :

 

mylibtest.cpp

mylibtest.h

mylibtest.o

3.     CONSTRUCTION DE LA LIBRAIRIE

3.1     Suppression d’une version précédente

Dans un premier temps nous allons supprimer toute éventuelle instance de cette librairie qui aurait été préalablement créée.

 

rm -f libtest.a

 

3.2     Concaténation des fichiers objets

Puis nous allons concaténer les fichiers objets compilés dans un seul fichier

 

ar cr libtest.a fichier_obj1.o fichier_obj2.o etc…

 

dans notre exemple cela sera

 

ar cr libtest.a mylibtest.o

 

3.3     Liaison de la lib

Nous allons enfin finaliser (en liant entre eux les objets de la librairie) avec la commande ranlib

 

/bin/ranlib libtest.a

 

ou bien

 

/usr/bin/ranlib libtest.a

 

suivant la location du fichier ranlib

 

 

A la fin de cette phase, le répertoire mylib doit contenir :

 

mylibtest.cpp

mylibtest.h

mylibtest.o

libtest.a

 

le nom de notre librairie est donc « test ». Dans le cas ou nous aurions choisi de créer avec la command ar un fichier nommé libnomdemalibrairie.a, notre librairie s’appellerait nomdemalibriaire (le préfixe lib et l’extension a sont obligatoire)

4.     UTILISATION DE LA LIBRAIRIE DANS UN PROGRAMME C++

 

4.1     Création du fichier C++ du programme

 

Nous allons créer un fichier exec.cpp qui contiendra le point d’entrée du programme hôte de la librairie.

 

Il contiendra donc :

 

#include "mylibtest.h"

 

int main()

{

     helloWorld();

     return 1;

}

 

4.2     Compilation du programme

Nous le compileront avec la commande :

 

g++ exec.cpp –L. –ltest –o exec_cpp

 

Rq importante : les fichiers utilisant qui en utilisent d’autres doivent etre liés spécifié (dans l’ordre de liaison) avant les fichiers qu’ils utilisent ! Dans notre cas nous devront donc spécifier le fichier exec.cpp (qui utilise la librairie) avant la librairie elle-même.

 

L’option –L spécifie les chemins où se trouvent les librairies à inclure.

L’option –l spécifie les librairies à utiliser, ici test, puisque notre libriairie s’appelle libtest.a

 

Notre répertoire contiendra donc

 

mylibtest.cpp

mylibtest.h

mylibtest.o

exec.cpp

libtest.a

exec_cpp

4.3     Lancement du programme

 

le lancement du fichier exec_cpp doit nous afficher « hello » sur l’écran

5.     MODIFICATION DE LA LIBRIAIRIE C++ POUR ETRE UTILISEE EN C

 

Afin qu’une fonction définie dans un fichier C++ puisse être vue dans un programme compilé en C, il est nécessaire de la déclarer à l’intérieur d’un bloc extern "C" , en revanche, étant donné que ce bloc est défini dans le fichier « .h », il sera utilisé aussi bien lors de la compilation de la librairie que de la compilation du programme C, mais dans le cas de la librairie, la fonction ne doit pas être déclarée dans un bloc extern, pour cela il convient d’utiliser une directive pré-processeur qui inclura ou non un bloc extern suivant si le compilateur a positionné la variable __cplusplus ou non.

Le fichier mylib.h devient donc

 

#ifndef MYLIBTEST_H

#define MYLIBTEST_H

 

#ifdef __cplusplus

extern "C"

{

#endif

 

void helloWorld();

 

#ifdef __cplusplus

}

#endif

 

#endif /* MYLIBTEST_H */

 

Répéter les étapes des chapitres 2 et 3

6.     UTILISATION DE LA LIBRIAIRIE DANS UN PROGRAMME C

6.1     Création du fichier C du programme

Nous allons créer un fichier exec.c qui contiendra le point d’entrée du programme hôte de la librairie.

 

Il contiendra donc :

 

#include "mylibtest.h"

 

int main()

{

     helloWorld();

     return 1;

}

 

6.2     Compilation du programme

Nous le compileront avec la commande :

 

gcc exec.c –L. –ltest –lstdc++ –o exec_c

 

Rq importante : les composants utilisateurs (fichiers, librairies) doivent être spécifiés (dans l’ordre de liaison) avant ceux dont ils ont besoin Dans notre cas nous devront donc spécifier le fichier exec.c (qui utilise la librairie) avant la librairie elle-même.

 

L’option –lstdc++, spécifie au compilateur C qu’il devra devoir lier en plus la librairie standard du C++ (libstdc++.a), puisque nous utilisons dans notre librairie des fonctionnalités de la STL (Standard Type Library), dans notre cas, cette fonctionnalité est le cout.

 

Remarque : si la librairie a été compilée avec le mot clef –static, il ne devrait pas être nécessaire de spécifier l’option –lstdc++, celle-ci devant alors se trouver directement greffée dans la librairie que nous sommes en train de construire

 

Notre répertoire contiendra donc

 

mylibtest.cpp

mylibtest.h

mylibtest.o

exec.cpp

exec.c

libtest.a

exec_cpp

exec_c

6.3     Lancement du programme

Le lancement du fichier exec_c doit nous afficher « hello » sur l’écran

7.     UTILISATION DES CLASSES DANS UN PROGRAMME C, VIA LA BIBLIOTHEQUE C++

Le langage C ne comprenant pas la notion de classes, il est nécessaire d’encapsuler la création des classes et leur utilisation dans autant de fonctions, et de créer des instances globales des classes visibles depuis l’extérieures de la librairie.

 

Ainsi, si nous souhaitons créer un classe HelloWorld charger d’afficher « Hello », nous devrons modifier les fichiers de la façon suivante :

 

§         mylibtest.h

 

#ifndef MYLIBTEST_H

#define MYLIBTEST_H

 

#ifdef __cplusplus

 

class HelloWorld

{

          public:

          void display();

};

 

 

extern "C"

{

#endif

 

void HelloWorldInit();

void HelloWorldDeinit();

void HelloWorldDisplay();

 

 

#ifdef __cplusplus

}

#endif

 

#endif

 

§         mylibtest.cpp

 

 

#include "mylibtest.h"

 

#include <iostream>

 

HelloWorld * g_helloWorld;

 

void HelloWorld::display()

{

     std::cout << "hello" << std::endl;

}

 

void HelloWorldInit()

{

      g_helloWorld = new HelloWorld;

}

 

void HelloWorldDeinit()

{

      if (g_helloWorld)   delete g_helloWorld;

}

 

void HelloWorldDisplay()

{

      g_helloWorld->display();

}

 

§         exec.c

 

#include "mylibtest.h"

 

int main()

{

     HelloWorldInit();

     HelloWorldDisplay();

     HelloWorldDeinit();

 

     return 1;

}

 

8.     UTILISATION DE PLUSIEURS INSTANCES DE CLASSES DANS UN PROGRAMME C, VIA LA BIBLIOTHEQUE C++

Nous venons de voir comment créer et utiliser une instance de la classe HelloWorld dans un fichier C, maintenant voyons comment il est possible de créer et utiliser plusieurs instances de cette classe.

 

Au lieu d'utiliser un pointeur global sur une seule instance de HelloWorld, il faudra créer une map globale qui associera un identifiant à une instance.

Il faudra donc modifier les fonctions HelloWorldInit() et HelloWorldDeinit() qui permettront d'initialiser cette map.

 

Nous créerons les fonctions HelloWorldCreate() et HelloWorldRelease() permettant à partir d'un identifiant de créer des instances de HelloWorld

La fonction HelloWorldDisplay() prendra donc elle aussi un argument qui sera l'identifiant permettant de retrouver l'instance depuis le fichier C.

 

Voici à quoi ressembleront les différents fichiers :

 

 

§         mylibtest.h

 

#ifndef MYLIBTEST_H

#define MYLIBTEST_H

 

#ifdef __cplusplus

 

class HelloWorld

{

          public:

          void display();

};

 

 

extern "C"

{

#endif

 

void HelloWorldInit();

void HelloWorldDeinit();

void HelloWorldCreate(int _num);

void HelloWorldRelease(int _num);

void HelloWorldDisplay(int _num);

 

 

#ifdef __cplusplus

}

#endif

 

#endif

 

§         mylibtest.cpp

 

 

#include "mylibtest.h"

 

#include <iostream>

#include <map>

 

std::map<int, HelloWorld *, std::less<int, HelloWorld *> > * g_helloWorlds;

 

void HelloWorld::display()

{

     std::cout << "hello" << std::endl;

}

 

void HelloWorldInit()

{

      g_helloWorlds = new std::map<int, HelloWorld *, std::less<int, HelloWorld *> >;

}

 

void HelloWorldDeinit()

{

      if (g_helloWorlds)   delete g_helloWorlds;

}

 

void HelloWorldCreate(int _num)

{

      if (!g_helloWorlds)    return;

 

      std::map<int, HelloWorld *, std::less<int, HelloWorld *> >::iterator p = g_helloWorlds->find(_num);


      if (p == datas.end())

            g_helloWorlds->insert(std::pair<int, HelloWorld *>(_num, new HelloWorld))

}

 

void HelloWorldRelease(int _num)

{

      if (!g_helloWorlds)    return;

 

      std::map<int, HelloWorld *, std::less<int, HelloWorld *> >::iterator p = g_helloWorlds->find(_num);
 

      if (p != datas.end())

            delete (*p).second;

}

 

void HelloWorldDisplay(int _num)

{

      if (!g_helloWorlds)    return;

 

      std::map<int, HelloWorld *, std::less<int, HelloWorld *> >::iterator p = g_helloWorlds->find(_num);


      if (p != datas.end())

            (*p).second->display();

}

 

§         exec.c

 

#include "mylibtest.h"

 

int main()

{

     HelloWorldInit();

 

     HelloWorldCreate(12);

     HelloWorldCreate(4);

     HelloWorldCreate(25);

     HelloWorldDisplay(12);

     HelloWorldDisplay(4);

     HelloWorldRelease(12);

     HelloWorldDisplay(25);

     HelloWorldRelease(4);

     HelloWorldRelease(25);

 

     HelloWorldDeinit();

 

     return 1;

}

 

 

 
Responsable bénévole de la rubrique C : Arnaud Feltz (buchs) - Contacter par EMail :
Vos questions techniques : forum d'entraide C - Publiez vos articles, tutoriels et cours
et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones
Nous contacter - Copyright © 2000-2008 www.developpez.com - Legal informations.