[débutante] Interfaçage C++/C

Interfaçage C++/C [débutante] - C++ - Programmation

Marsh Posté le 29-05-2006 à 10:40:13    

Bonjour,
 
je n'ai jamais fait de C++. Pour mon stage, je programme sous Visual C++ 2005, ce qui est tout nouveau pour moi. En fait, j'ai écrit des fonctions en C, un programme principal en C, et je possède deux fonctions de lecture et de sauvegarde d'image en C++ que je souhaite appeler dans mon programme principal en C:
[#0000ff size=2]  

Code :
  1. int imageBMP::lectureImage(Image &image, [/#0000ff size=2]const char* name, BITMAPFILEHEADER *header, BITMAPINFOHEADER *infoHeader)
  2. int imageBMP::sauvegardeImage(Image image, const char* name, BITMAPFILEHEADER header, BITMAPINFOHEADER infoHeader)

 

[size=1] [/size]
Comment dois je m'y prendre ? J'ai tenté de les déclarer en " extern "C" " mais ceci n'a pas marché ?
Quels sont les points importants lorsque l'on veut appeler des fonctions en C++ dans un programme en C ?
 
Merci pour votre aide.


---------------
amelie
Reply

Marsh Posté le 29-05-2006 à 10:40:13   

Reply

Marsh Posté le 29-05-2006 à 10:48:28    

En général Il faut instancier l'objet , et ensuite en appeler ses méthodes.

Reply

Marsh Posté le 29-05-2006 à 10:53:53    

_darkalt3_ a écrit :

En général Il faut instancier l'objet , et ensuite en appeler ses méthodes.


 
Ha ok, c'est du chinois pour moi qui ne fait pas de programmation objet ... mais bon je vais tenter de me renseigner là dessus. Merci.


---------------
amelie
Reply

Marsh Posté le 29-05-2006 à 19:43:26    

ce que dark a voulu dire cest que tu dois avoir qq part, avant d'apeller les methodes lectureImage et /ou sauvegareImage qq chose du genre
imageBMP *pIm = new imageBMP();// constructeur par def
...bla bla...
pIm->lectureImage(image, path, header, infoheader);
...
 
 
autre tite remarque, suis p't'etre un maniaque, mais les noms de classes, essaie de faire qq chose du genre CNomDeMaClasse plutot que nomdemaclasse.
 
le 'C' qui manque m'arrache toujours les yeux.
voilo
 
@pluche
 
 

Reply

Marsh Posté le 29-05-2006 à 20:46:24    

pfuitt a écrit :

autre tite remarque, suis p't'etre un maniaque, mais les noms de classes, essaie de faire qq chose du genre CNomDeMaClasse plutot que nomdemaclasse.
 
le 'C' qui manque m'arrache toujours les yeux.


 
nomdemaclasse, c'est illisible.
NomDeMaClasse, nomDeMaClasse, nom_de_ma_classe, Nom_De_Ma_Classe,  c'est lisible de mon point de vue.
Je crois que c'est surtout contre productif de vouloir imposer une convention de nommage à quelqu'un, hors projet commun.
 
Quand à préfixer par C, je pense à chaque fois que la class est un POD, une sorte de C-classe quoi. Mais apparemment non. En plus ça ne facilite pas la lisibilité du nom de la classe ...  

Reply

Marsh Posté le 29-05-2006 à 22:31:50    

je pense que le prefixe C va à l'encontre du principe d'opacité des objets, l'utilisateur n'a pas besoin de savoir que tel type est un alias d'une classe
 
imaginez cvector, clist, ... qu'est-ce qu'on en a a foutre que cvector est le nom d'une classe ? ce qui compte c'est la sémantique de cvector (le fond)

Reply

Marsh Posté le 29-05-2006 à 22:35:11    

+1


---------------
Töp of the plöp
Reply

Marsh Posté le 29-05-2006 à 22:37:18    

pour repondre a la question initiale, interfacer le C avec le C++ est loin d'etre evident, il faudra ecrire (pour utiliser les classes C++ ou des fonction dans du code C) des modules wrapper en C++ avec extern "C" pour les symboles à utiliser dans le code C.
 
il y a aussi d'autres choses à savoir qui sont detaillées dans cette faq
http://jlecomte.ifrance.com/c++/c+ [...] pp-fr.html

Reply

Marsh Posté le 29-05-2006 à 22:54:46    

skelter a écrit :

je pense que le prefixe C va à l'encontre du principe d'opacité des objets, l'utilisateur n'a pas besoin de savoir que tel type est un alias d'une classe
 
imaginez cvector, clist, ... qu'est-ce qu'on en a a foutre que cvector est le nom d'une classe ? ce qui compte c'est la sémantique de cvector (le fond)


 
Allez, un argument pour la défense (parce qu'il faut savoir être objectif) : My::String par exemple. on ne sait pas à prori si c'est un nom de classe, ou un nom de typedef. Autrement dit, peut-on déclaré ce nom ?  
namespace My { class String; } // oui si String est un nom de class, non si c'est un nom de typedef.

Reply

Marsh Posté le 29-05-2006 à 23:09:04    

pfuitt a écrit :


le 'C' qui manque m'arrache toujours les yeux.


t'as qu'a arréter de coder avec les MFC, ça ira beaucoup mieux :D


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 29-05-2006 à 23:09:04   

Reply

Marsh Posté le 29-05-2006 à 23:15:53    

++fab a écrit :

Allez, un argument pour la défense (parce qu'il faut savoir être objectif) : My::String par exemple. on ne sait pas à prori si c'est un nom de classe, ou un nom de typedef. Autrement dit, peut-on déclaré ce nom ?  
namespace My { class String; } // oui si String est un nom de class, non si c'est un nom de typedef.


 
 
j'ai pas trop compris, que String soit un nom de classe ou un typedef c'est la meme chose, non ? je veux dire que My::String est à partir de la un nom réservé et on ne peut plus déclaré de classe My::String ou de typedef My::String
 
d'ailleur ce code ne compile pas
 
 

Code :
  1. namespace My
  2. {
  3.     typedef int String;
  4.     class String;
  5. }


 

Citation :


in.cpp:5: error: conflicting declaration 'struct My::String'
in.cpp:4: error: 'My::String' has a previous declaration as `typedef int My::String'


 
ou alors je sui à coté  :??:  

Reply

Marsh Posté le 29-05-2006 à 23:58:14    

skelter a écrit :

j'ai pas trop compris, que String soit un nom de classe ou un typedef c'est la meme chose, non ? je veux dire que My::String est à partir de la un nom réservé et on ne peut plus déclaré de classe My::String ou de typedef My::String


 
C'est pas exactement ce dont je parle.
 

Citation :

d'ailleur ce code ne compile pas
 

Code :
  1. namespace My
  2. {
  3.     typedef int String;
  4.     class String;
  5. }


 

Citation :


in.cpp:5: error: conflicting declaration 'struct My::String'
in.cpp:4: error: 'My::String' has a previous declaration as `typedef int My::String'




 
L'exemple qui illustre ce que je disais :
 

Code :
  1. //OK
  2. namespace My
  3. {
  4.     class String; // déclaration d'un nom de class qui est bien un nom de class.
  5.     class String {};
  6. }
  7. //pas OK
  8. namespace My2
  9. {
  10.     class String; // declaration d'un nom de class qui s'avère être un nom de typedef.
  11.     typedef int String;
  12. }


 
ça me gène souvent, et je ne sais pas pourquoi il était nécessaire de contraindre cette utilisation de typedef.

Reply

Marsh Posté le 30-05-2006 à 00:19:33    

ok, mais je vois rien de choquant, ca me parait logique qu'on puisse faire l'un et pas l'autre, et dans le premier c'est juste une déclaration anticipée et la déclaration complete qui suit ?
 
tu voudrais que ce soit comment ? parce que faut bien que la resolution des noms se fasse

Reply

Marsh Posté le 30-05-2006 à 00:26:49    

skelter a écrit :

ok, mais je vois rien de choquant, ca me parait logique qu'on puisse faire l'un et pas l'autre, et dans le premier c'est juste une déclaration anticipée et la déclaration complete qui suit ?


Rien de choquant, et c'est bien une déclaration suivie d'une définition.
 

Citation :

tu voudrais que ce soit comment ?


qu'un typedef-name soit un class-name (je rêve)
 

Citation :

parce que faut bien que la resolution des noms se fasse


Si tu as une explication sur le pourquoi du comment, n'hésites pas :)

Reply

Marsh Posté le 30-05-2006 à 01:02:06    

Citation :

Rien de choquant, et c'est bien une déclaration suivie d'une définition.


 
ouai, tu m'aivais deja fais la remarque, mais il semble que dans le standard ce sont bien ces termes (forward declaration & declaration) qui sont employés
 

Citation :

qu'un typedef-name soit un class-name (je rêve)


 
ouai, d'apres le code qe tu as montrés tu voudrais pouvoir faire
 

Code :
  1. class String;
  2. ...
  3. typedef ... String;


 
mais class String; c'est une forward declaration, et String est incomplet jusqu'a class String {}; pour moi c'est un point de syntaxe lié aux  mots cles class, struct et union qui permet de déclaré l'existance d'un nom de classe avant sa déclaration complete (ou sa definition si tu preferes)
 
 

Citation :

Si tu as une explication sur le pourquoi du comment, n'hésites pas :)


 
j'avais pas compris ce que tu voulais faire, mais si ce code compilais
 
 

Code :
  1. namespace My2
  2. {
  3.    class String; // declaration d'un nom de class qui s'avère être un nom de typedef.
  4.    typedef int String;
  5. }


 
ca ferait 2 types pour un nom
 
l'explication que je vois d'apres le standard (§9.1) c'est que 'class machin' (independament de ce qui suit) insert machin dans le namesapce de la portée courante, et
class machin; // forward déclaration, le nom machin existe
typedef int machin; // impossible car machin existe
class machin {}; // declaration, ou definition (en fait les 2 termes sont employés), si machin n'existe pas il est inseré (pas de conflit), machin est un type complet
 
enfin personnelement je vois pas ou est le probleme et ou est la limitation  :??:

Reply

Marsh Posté le 30-05-2006 à 20:12:20    

Citation :

ouai, tu m'aivais deja fais la remarque, mais il semble que dans le standard ce sont bien ces termes (forward declaration & declaration) qui sont employés


Dans le lexique, mais ailleurs ?
 
 

Citation :

ouai, d'apres le code qe tu as montrés tu voudrais pouvoir faire
 

Code :
  1. class String;
  2. ...
  3. typedef ... String;


 
mais class String; c'est une forward declaration, et String est incomplet jusqu'a class String {}; pour moi c'est un point de syntaxe lié aux  mots cles class, struct et union qui permet de déclaré l'existance d'un nom de classe avant sa definition


Je crois que c'est ça.
 
 

Citation :

l'explication que je vois d'apres le standard (§9.1) c'est que 'class machin' (independament de ce qui suit) insert machin dans le namesapce de la portée courante, et
class machin; // forward déclaration, le nom machin existe
typedef int machin; // impossible car machin existe
class machin {}; // declaration, ou definition (en fait les 2 termes sont employés), si machin n'existe pas il est inseré (pas de conflit), machin est un type complet


 
Mon explication, c'est que "class machin;" déclare le class-name : "machin".
"typedef int machin;" déclare le typedef-name : "machin".
Un nom du même nom est déjà déclaré, et n'est pas un typedef-name (...?), donc pas glop. Mais je ne vois pas le paragraphe qui spécifie cela.
7.1.3.3 est intéressant :
 

Code :
  1. class complex { /* ... */ };
  2. typedef int complex; // error : redefinition


 
A noter que la première ligne est une définition contrairement à mon exemple.
A noter aussi que le diagnostic de la deuxième ligne est une redéfinition, alors que typedef int complex; est une déclaration :/
 

Citation :

enfin personnelement je vois pas ou est le probleme et ou est la limitation  :??:


Il n'y a pas de problème, juste que ce serait agréable de pouvoir faire des déclarations "anticipées" sur des typedef-name (qui ne représente pas des class-name), afin de limiter les dépendances et les temps de compilation.

Reply

Marsh Posté le 30-05-2006 à 20:47:27    

ce qui est sur c'est qu'on ne peut pas avoir de typedef-name et de class-name equivalent puisque la syntaxe ne permet pas de lever ce genre d'ambiguité, c'est ce qui est détaillé dans 7.1.3.3 dans un sens et dans l'autre
 

Citation :


A noter que la première ligne est une définition contrairement à mon exemple.


 
je pense que c'est pareil, definition ou declaration le nom est inseré
 

Citation :


Il n'y a pas de problème, juste que ce serait agréable de pouvoir faire des déclarations "anticipées" sur des typedef-name (qui ne représente pas des class-name), afin de limiter les dépendances et les temps de compilation.  


 
tu aurais un exemple ? parce que pour les classes ok mais c'est deja le cas

Reply

Marsh Posté le 30-05-2006 à 21:17:18    

skelter a écrit :

ce qui est sur c'est qu'on ne peut pas avoir de typedef-name et de class-name equivalent puisque la syntaxe ne permet pas de lever ce genre d'ambiguité, c'est ce qui est détaillé dans 7.1.3.3 dans un sens et dans l'autre


Je ne sais pas s'il est difficile pour un compilateur de lever l'ambiguité. Instinctivement, je dirais que non. Mais bon ...
 

Citation :

je pense que c'est pareil, definition ou declaration le nom est inseré


Effectivement, c'est marqué *déclaré* dans le texte de 7.1.3.3  [:petrus75]  
 

Citation :

Citation :


Il n'y a pas de problème, juste que ce serait agréable de pouvoir faire des déclarations "anticipées" sur des typedef-name (qui ne représente pas des class-name), afin de limiter les dépendances et les temps de compilation.  


 
tu aurais un exemple ? parce que pour les classes ok mais c'est deja le cas


 
$ cat file.hpp
#ifndef FILE_HPP
#define FILE_HPP
class Foo;
void func( Foo const& );
#endif
 
$ cat file.cpp
#include "file.hpp"
#include "foo.hpp"
void func( Foo const& foo ) { /* utilise foo */ }
 
$ cat foo.hpp
#ifndef FOO_HPP
#define FOO_HPP
//typedef int Foo; // défendu !
struct Foo {}; // OK
#endif

Reply

Marsh Posté le 30-05-2006 à 21:39:28    

Citation :

Je ne sais pas s'il est difficile pour un compilateur de lever l'ambiguité. Instinctivement, je dirais que non. Mais bon ...


 
si on pouvais faire

Code :
  1. class foo;
  2. typedef ... foo;
  3. foo f; // quel est le type de f ?


 
c'est mieux comme ca, niveau abstraction vaut mieux considerer autant les class-name que les typedef-name comme des noms de type
 

Code :
  1. $ cat file.hpp
  2. #ifndef FILE_HPP
  3. #define FILE_HPP
  4. class Foo;
  5. void func( Foo const& );
  6. #endif
  7. $ cat file.cpp
  8. #include "file.hpp"
  9. #include "foo.hpp"
  10. void func( Foo const& foo ) { /* utilise foo */ }
  11. $ cat foo.hpp
  12. #ifndef FOO_HPP
  13. #define FOO_HPP
  14. //typedef int Foo; // défendu !
  15. struct Foo {}; // OK
  16. #endif


 
je m'attendais a ca :), dans ce cas autant faire ditectement
 

Code :
  1. void func( int const& );


 
pour les classe ok et on peut le faire, mais pour le reste je vois toujours pas l'interet  :??:


Message édité par skelter le 30-05-2006 à 21:40:06
Reply

Marsh Posté le 30-05-2006 à 21:52:37    

Citation :

si on pouvais faire


Code :
  1. class foo;
  2. typedef int foo;
  3. foo f; // quel est le type de f ?


j'aurais pas trouvé débile que ce soit int.
 

Citation :

c'est mieux comme ca, niveau abstraction vaut mieux considerer autant les class-name que les typedef-name comme des noms de type

C'est bien comme cela que je les considèrent. Je veux qu'un typedef-name soit considéré comme un class-name (même si le typedef-name ne représente pas un class-name. cf §7.1.3.4)
 

Citation :

je m'attendais a ca :), dans ce cas autant faire ditectement
 

Code :
  1. void func( int const& );


 
pour les classe ok et on peut le faire, mais pour le reste je vois toujours pas l'interet  :??:


 
des fois, j'aime bien avoir un fichier qui met des typedef sur les grandeurs que j'utilise dans un projet.
typedef  double profondeur;
typedef unsigned short idCount ;  
histoire de garantir que le type est bien le même dans toute les TU, et par souci de clarté.
Malheureusement, ça a un cout au niveau dépendance, et temps de compilation.


Message édité par ++fab le 30-05-2006 à 21:55:57
Reply

Marsh Posté le 30-05-2006 à 22:17:56    

Citation :

j'aurais pas trouvé débile que ce soit int.


 
ouai dans ce cas pourquoi pas mais en general quand foo designe un class-name et un typedef name, la syntaxe pour instancier un objet (ou on ne precise que le nom du type) ne permet pas au compilateur de determiner le distinguer l'un des 2 type.
 

Citation :

Malheureusement, ça a un cout au niveau dépendance, et temps de compilation.


 
je savais pas que ca avais un cout, pour quel raison ? (j'aurais pensé le contraire)
 
et sinon c'est en effet ce qu'on fait dans tout les projets et les bibliotheques, et meme de maniere indirect tu trouve ca dans tout les programme, et meme en pagaille dans boost ou la lib c++ (j'imagine)
 
en parlant de limitation, il y en a une qui est frustrante c'est le fait de ne pas pouvoir faire de typedef template car coté implementation ca semble ne posée aucun probleme (meme au niveau de la syntaxe)
 
j'avais deja eu ce probleme en cherchant a faire

Code :
  1. template <typename T>
  2. typedef boost::array<T, 20> array20; // pas standard
  3. array20<int> foo;


 
et un site parlait effectivement de ce probleme, qui serait certainement "corrigé" dans un prochain standard

Reply

Marsh Posté le 30-05-2006 à 22:57:39    


Citation :

ouai dans ce cas pourquoi pas mais en general quand foo designe un class-name et un typedef name, la syntaxe pour instancier un objet (ou on ne precise que le nom du type) ne permet pas au compilateur de determiner le distinguer l'un des 2 type.


Mon idée est que foo ne désigne alors que le typedef-name.
 

Citation :

Citation :

Malheureusement, ça a un cout au niveau dépendance, et temps de compilation.


je savais pas que ca avais un cout, pour quel raison ? (j'aurais pensé le contraire)


Tu inclus ce fichier partout, tout simplement. Une modification dans ce fichier entraine la recompilation de tout le projet.
Et lorsque tu es sur un réseau (très) lent, et que tu passes 75% du temps de compilation en préprocessing, tu te poses la question de savoir s'il est bien nécessaire d'inclure autant de monde. ça devient problématique lorsque ce fichier de typedef inclu lui aussi pas mal de monde; et tu tires la pelote ...
Si l'environnement de compilation est bien fait (préprocessing en local notamment), ça réduit les problèmes.
 

Citation :

en parlant de limitation, il y en a une qui est frustrante c'est le fait de ne pas pouvoir faire de typedef template car coté implementation ca semble ne posée aucun probleme (meme au niveau de la syntaxe)


C'est beaucoup moins simple que tu ne le crois :) Je me rappelle d'en avoir lu quelques détails, et c'est tellement problématique que le mot clé typedef a été abandonné au profit de "using". Je crois que ça a été discuté à Lillhammer.

Reply

Marsh Posté le 30-05-2006 à 23:08:20    

a ok, si c'est pas si simple que ca  :D
 

Citation :


Tu inclus ce fichier partout, tout simplement. Une modification dans ce fichier entraine la recompilation de tout le projet.
Et lorsque tu es sur un réseau (très) lent, et que tu passes 75% du temps de compilation en préprocessing, tu te poses la question de savoir s'il est bien nécessaire d'inclure autant de monde. ça devient problématique lorsque ce fichier de typedef inclu lui aussi pas mal de monde; et tu tires la pelote ...
Si l'environnement de compilation est bien fait (préprocessing en local notamment), ça réduit les problèmes.


 
en effet, personnelement je n'ai jamais eu de projet de cette ampleur, les plus gros c'etait 4-5min pour tout recompiler, du moment que ce genre de modif sont rares et à titre exceptionnelles (ce qui est en général le cas) ca me pose pas de probleme mais effectivement dans l'absolu ca peut en etre un.

Reply

Marsh Posté le 30-05-2006 à 23:56:08    

skelter a écrit :

a ok, si c'est pas si simple que ca  :D


Quelle est la sémantique que l'on veut donner à typedef template ? C'est cette question qui a fait débat notamment.  
 

Citation :

en effet, personnelement je n'ai jamais eu de projet de cette ampleur, les plus gros c'etait 4-5min pour tout recompiler, du moment que ce genre de modif sont rares et à titre exceptionnelles (ce qui est en général le cas) ca me pose pas de probleme mais effectivement dans l'absolu ca peut en etre un.


En fait, je ne trouve pas qu'un recompilation du projet soit un coût, si c'est en modifiant le fichier de typedef -- c'est exceptionnel on est d'accord. Le projet sur lequel je travaille actuellement met bien 1h30 à se compiler, et la lenteur de la compilation provient du preprocessing. La, je considère comme un coût prohibitif l'inclusion d'un fichier de typedef qui me fait tirer toute une purée de bibliothèques -- dont je n'ai pas le contrôle.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed