Différences entre les versions de « Tutoriel de Data Flow Generator V0 »
toross>WikiAdmin |
m (1 version importée : dfg) |
(Aucune différence)
| |
Version actuelle datée du 24 juillet 2026 à 19:08
|
1 Tuto_002 : Développement en c++ sous LINUX
1.1 L'objectif
L'objectif est de montrer comment créer rapidement un driver en c++ pour écrire/lire dans/depuis un fichier au format xml dont les données sont modélisées par le diagramme suivant :

1.2 Pour commencer
Pour commencer créer les répertoires tuto_002/ myXercesTools et utilities dans un répertoire commun dans lesquels nous allons travailler. Pour ceci tapez :
mkdir tuto_002
mkdir myXercesTools
mkdir utilities
mkdir tuto_002/generated
mkdir tuto_002/generated_out
Vous aurez alors :
├── myXercesTools
├── tuto_002
│ ├── generated
│ └── generated_out
└── utilities
1.3 Le modèle
Le modèle utilisé par DataFlowGenerator correspondant au modèle uml précédent est le suivant :
<?xml version="1.0" encoding="UTF-8"?>
<grammar type="xml" version="1.0.0" FileFormatVersion="1.0.0">
<el name="dessin" type="CDessin">
<el name="base" type="CBase" OnlyDefinition="1">
</el>
<el name="point" type="CPoint" heritances="CBase" OnlyDefinition="1">
<el name="x" type="float"/>
<el name="y" type="float"/>
</el>
<el name="segment" type="CSegment" heritances="CBase" OnlyDefinition="1">
<el name="A" type="@CPoint"/>
<el name="B" type="@CPoint"/>
</el>
<el name="cercle" type="CCercle" heritances="CBase" OnlyDefinition="1">
<el name="C" type="@CPoint"/>
<el name="R" type="float"/>
</el>
<el name="compound" type="CCompound" cardinality="*" heritances="CBase">
<el name="elements" type="@CBase" cardinality="*"
accept="CPoint:CSegment:CCercle:CCompound"/>
</el>
</el>
</grammar>
Sur le site http://dfg.bht.fr, copiez ce modèle dans le champ de texte nommé grammar_file_name et dans le champ de texte nommé data_name écrivez "tuto_002_".
Sélectionnez Générer du c++ avec Xerces et puis cliquez sur le bouton Générer pour créer les fichiers suivants :
- Les variables :
- tuto_002_XMLDriver_pkg_version.h
- tuto_002_XMLDriver.h
- tuto_002_XMLDriver.cxx
- Les fixes
- my_xerces_impl.h
- my_xerces_impl.cxx
- utilities.h
- utilities.cxx
Copier ces fichiers dans les répertoires myXercesTools, utilities et tuto_002/generated :
.
├── myXercesTools
│ ├── my_xerces_impl.cxx
│ └── my_xerces_impl.h
├── tuto_002
│ ├── generated
│ │ ├── tuto_002_XMLDriver.cxx
│ │ ├── tuto_002_XMLDriver.h
│ │ └── tuto_002_XMLDriver_pkg_version.h
└── utilities
├── utilities.cxx
└── utilities.h
1.4 Compilation
1.4.1 Si XERCES 2.7 n'est pas installé sur votre système
En notant <install_bin_dir> le répertoire dans lequel sera installée XERCES et <install_src_dir> le répertoire à partir duquel l'installation est réalisée, les opérations suivantes permettent l'installation :
1 mkdir <span style="border-color:#606060;border-radius:0.4em;border-style:solid;border-width:1pt;min-height:1em;padding-left:0.5em;padding-right:0.5em;background:#404060;color:#FFFFFF;"><install_bin_dir></span>/xerces-c-lib_2_7_0
2 export <span style="border-color:#606060;border-radius:0.4em;border-style:solid;border-width:1pt;min-height:1em;padding-left:0.5em;padding-right:0.5em;background:#404060;color:#FFFFFF;">XERCESCROOT</span>=<install_src_dir>
3 cd <span style="border-color:#606060;border-radius:0.4em;border-style:solid;border-width:1pt;min-height:1em;padding-left:0.5em;padding-right:0.5em;background:#404060;color:#FFFFFF;"><install_src_dir></span>/src/xercesc
4 autoconf
5 ./runConfigure -plinux -P <span style="border-color:#606060;border-radius:0.4em;border-style:solid;border-width:1pt;min-height:1em;padding-left:0.5em;padding-right:0.5em;background:#404060;color:#FFFFFF;"><install_bin_dir></span>
6 make
7 make install
1.4.2 Le programme tuto_002
Maintenant la variable XERCESCROOT doit être positionné sur le librairie XERCES installé donc cette fois-ci :
export XERCESCROOT=<install_bin_dir>
par exemple :
export XERCESCROOT=/local01/atoross/exe/xerces-c-lib_2_7_0
Afin de pouvoir exécuter le programme compilé il faut aussi modifier LD_LIBRARY_PATH comme suit :
export LD_LIBRARY_PATH=$XERCESCROOT/lib:$LD_LIBRARY_PATH
Le répertoire XERCESCROOT doit contenir les répertoires :
.
├── include
└── lib
Créer un fichier nommé "Makefile" dans le répertoire tuto_002 et copier le texte suivant dans ce fichier :
proj=tuto_002
all : test
test : ${proj}
${proj} : util.o myxerces.o xmldriver.o main.cpp
g++ -I${XERCESCROOT}/include -I../utilities -Igenerated -I../myXercesTools -L${XERCESCROOT}/lib -lxerces-c main.cpp util.o myxerces.o xmldriver.o -o ${proj}
util.o : ../utilities/utilities.cxx ../utilities/utilities.h
g++ -I../utilities ../utilities/utilities.cxx -c -o util.o
xmldriver.o :generated/$(proj)_XMLDriver.cxx generated/$(proj)_XMLDriver.h generated/$(proj)_XMLDriver_pkg_version.h
echo "g++ -I${XERCESCROOT}/include -I../utilities -I../myXercesTools -Igenerated -L${XERCESCROOT}/lib generated/${proj}_XMLDriver.cxx -c -o xmldriver.o"
g++ -I${XERCESCROOT}/include -I../utilities -I../myXercesTools -Igenerated -L${XERCESCROOT}/lib generated/${proj}_XMLDriver.cxx -c -o xmldriver.o
myxerces.o: ../myXercesTools/my_xerces_impl.cxx ../myXercesTools/my_xerces_impl.h
echo "g++ -I../utilities -I../myXercesTools -I${XERCESCROOT}/include -L${XERCESCROOT}/lib ../myXercesTools/my_xerces_impl.cxx -c -o myxerces.o"
g++ -I../utilities -I../myXercesTools -I${XERCESCROOT}/include -L${XERCESCROOT}/lib ../myXercesTools/my_xerces_impl.cxx -c -o myxerces.o
clean :
-rm *.o *~ ${proj} ./generated_out/*
Les sources du programme doivent être écrite dans le fichier nommé "main.cpp" et créé dans tuto_002, copier ces sources depuis le paragraphe "le programme complet" dans ce fichier. Nous avons maintenant les fichiers suivants :
.
├── myXercesTools
│ ├── my_xerces_impl.cxx
│ └── my_xerces_impl.h
├── tuto_002
│ ├── generated
│ │ ├── tuto_002_XMLDriver.cxx
│ │ ├── tuto_002_XMLDriver.h
│ │ └── tuto_002_XMLDriver_pkg_version.h
│ ├── generated_out
│ ├── main.cpp
│ ├── Makefile
└── utilities
├── utilities.cxx
└── utilities.h
Pour compiler entrer dans le répertoire tuto_002 et tapez :
make
Pour exécuter le programme entrer dans le répertoire tuto_002 et tapez :
./tuto_002
Vous verrez alors aparaître le fichiers :
generated_out/
├── dessin1.xml
└── dessin2.xml
1.5 Explication des sources
1.5.1 Extension, utilisation de la fabrique
Avoir des données sans pouvoir ajouter des traitements ou extensions ce n'est pas très intéressant. Pour étendre les classes générées on utilise l' héritage et le polymorphisme des classes. Afin de pouvoir utiliser les nouveaux types de classe on utilise un fabrique qui est un singleton.
Par exemple si nous voulions ajouter un traitement aux cercle, une translation, on peut écrire le code suivant :
class myCCercle : public CCercle
{
public :
int my_attr ;
myCCercle() : CCercle(), my_attr(0)
{
} ;
void move( double dx, double dy )
{
C->x = C->x+dx ;
C->y = C->y+dy ;
}
};
CDessinBase * myCCercle_factory()
{
return new myCCercle() ;
};
Mais il ne faut pas oublier d'enregistrer cette classe dans la fabrique, voici comment le faire :
CDessinBase_factory::instance()->register_creator( "CCercle", myCCercle_factory ) ;
Pour créer la classe il suffit d'appeler la fabrique :
CCercle * cercle = (CCercle *) factory->create( "CCercle" ) ;
Voici l'exemple qui montre comment appliquer le translation :
myCCercle* mycercle = (myCCercle*) cercle ;
mycercle->move( 10.0, 10.0 ) ;
1.5.2 Construction des données
La construction se fait en appelant la fabrique. Pour les structures ayant une cardinal diffèrent de 1 nous utilisons les vecteur de la librairie STL. Exemple :
CDessinBase_factory * factory =CDessinBase_factory::instance();
...
CDessin * Med = (CDessin *) factory->create( "CDessin" ) ;
CCompound * comp = (CCompound *) factory->create( "CCompound" ) ;
Med->compound.push_back( comp ) ;
| Rq | La mémoire allouée est libérée par le code généré |
1.5.3 Charger et décharger
En utilisant une instance de CFileFormatInfo nous pouvons sauvegarder ou charger tout fichier contenant les données conforme au modèle.
CFileFormatInfo Info ;
Info.Save2XMLFile( Med , "generated_out/dessin1.xml" ) ;
CDessin * Med2 = Info.LoadFromXMLFile( "generated_out/dessin1.xml" ) ;
Info.Save2XMLFile( Med2 , "generated_out/dessin2.xml" ) ;
| Rq | La classe CFileFormatInfo cache bon nombre d'initialisations XERCES. |
1.5.4 Le programme complet
#include "generated/tuto_002_XMLDriver.h"
#include <iostream>
#include <typeinfo>
using namespace tuto_002_XMLDriver_ns ;
class myCCercle : public CCercle
{
public :
int my_attr ;
myCCercle() : CCercle(), my_attr(0)
{
} ;
void move( double dx, double dy )
{
C->x = C->x+dx ;
C->y = C->y+dy ;
}
};
CDessinBase * myCCercle_factory()
{
return new myCCercle() ;
};
int main(int argc, char * argv[ ])
{
std::cout << "start" << std::endl ;
//enregistrement du créateur
CDessinBase_factory::instance()->register_creator( "CCercle", myCCercle_factory ) ;
// Instance sur la fabrique de classe
CDessinBase_factory * factory =CDessinBase_factory::instance();
// Créaton dans la mémoire
CDessin * Med = (CDessin *) factory->create( "CDessin" ) ;
CCompound * comp = (CCompound *) factory->create( "CCompound" ) ;
Med->compound.push_back( comp ) ;
CCercle * cercle = (CCercle *) factory->create( "CCercle" ) ;
cercle->C->x = 12.0 ;
cercle->C->x = 3.0 ;
cercle->R = 40.0 ;
comp->elements.push_back( (CBase *) cercle ) ;
CSegment * segment = (CSegment *) factory->create( "CSegment" ) ;
segment->A->x = 5.0 ;
segment->A->y = 6.0 ;
segment->B->x = 1.0 ;
segment->B->y = -2.0 ;
comp->elements.push_back( (CBase *) segment ) ;
CCompound * comp2 = (CCompound *) factory->create( "CCompound" ) ;
comp->elements.push_back( (CBase *) comp2 ) ;
cercle = (CCercle *) factory->create( "CCercle" ) ;
cercle->C->x = 16.0 ;
cercle->C->x = 7.0 ;
cercle->R = 30.0 ;
comp2->elements.push_back( (CBase *) cercle ) ;
comp = comp2 ;
comp2 = (CCompound *) factory->create( "CCompound" ) ;
comp->elements.push_back( (CBase *) comp2 ) ;
cercle = (CCercle *) factory->create( "CCercle" ) ;
cercle->C->x = 13.0 ;
cercle->C->x = 4.0 ;
cercle->R = 20.0 ;
comp2->elements.push_back( (CBase *) cercle ) ;
comp = (CCompound *) factory->create( "CCompound" ) ;
Med->compound.push_back( comp ) ;
comp->copy( comp2 ) ;
myCCercle* mycercle = (myCCercle*) cercle ;
mycercle->move( 10.0, 10.0 ) ;
try
{
CFileFormatInfo Info ;
Info.Save2XMLFile( Med , "generated_out/dessin1.xml" ) ;
CDessin * Med2 = Info.LoadFromXMLFile( "generated_out/dessin1.xml" ) ;
Info.Save2XMLFile( Med2 , "generated_out/dessin2.xml" ) ;
}
catch (const my_xerces::myXercesError& toCatch)
{
std::cerr << toCatch.what() << std::endl ;
}
Med->clear() ;
delete Med ;
std::cout << "end" << std::endl ;
return 0 ;
}
