OVH Cloud OVH Cloud

Signature de struct

30 réponses
Avatar
Thierry Noc
Bonjour tlm,

Je rapplique avec une question pas très sexy, désolé.


Si j'ai une lib en C que je veux utiliser en C++, et que la lib n'a pas été
conçue pour C++, la solution est de retoucher les headers de la lib et de
rajouter des :
#ifdef __cplusplus
extern "C" {
#endif
dans tous les .h.

Si dans cette lib, y'a une struct avec un membre qui s'appelle operator. ex:

struct st {
int operator;
};

Est-ce que c'est correct de faire:

#ifdef __cplusplus
extern "C" {
#endif

struct st {
#ifdef __cplusplus
int xoperator; // operator est un mot clé réservé en C++
#else
int operator;
#endif
};

#ifdef __cplusplus
}
#endif

Autrement dit, est-ce que une structure n'aurait pas une espèce de signature
(comme une fonction) qui ferait intervenir le nom des membres, et qui
empêcherait de l'utiliser si on la falsifie. (d'après la norme, et d'après
la réalité du terrain).


Autre question:

sur un :
typedef char * charptr;
ou :
typedef struct st *structptr;

est-il nécessaire d'encadrer ces typedefs d'un extern "C" ?

--

10 réponses

1 2 3
Avatar
Gabriel Dos Reis
"Thierry Noc" writes:

| Si dans cette lib, y'a une struct avec un membre qui s'appelle operator. ex:
|
| struct st {
| int operator;

c'est ce qu'on appelle chercher des ennuis.

| Est-ce que c'est correct de faire:

c'est répandu (par exemple dans les en-têtes de la X lib) mais c'est
incorrect -- une violation de l'ODR.


| struct st {
| #ifdef __cplusplus
| int xoperator; // operator est un mot clé réservé en C++
| #else
| int operator;
| #endif
| };

| Autrement dit, est-ce que une structure n'aurait pas une espèce de signature
| (comme une fonction) qui ferait intervenir le nom des membres, et qui
| empêcherait de l'utiliser si on la falsifie. (d'après la norme, et d'après
| la réalité du terrain).

C'est là où intervient l'ODR (One Definition Rule) qui dit que deux
classes sont les mêmes si et seulement si les suites de tokens en
correspondance biunivoque.
3.2/5
[...] Given such an entity named D defined in more than one
translation unit, then
-- each definition of D shall consist of the same sequence of
tokens; and
[...]

Si tu violes cette règle simple, alors...

| Autre question:
|
| sur un :
| typedef char * charptr;
| ou :
| typedef struct st *structptr;
|
| est-il nécessaire d'encadrer ces typedefs d'un extern "C" ?

Yep.

-- Gaby
Avatar
Michaël Monerau
Gabriel Dos Reis wrote:
struct st {
#ifdef __cplusplus
int xoperator; // operator est un mot clé réservé
en C++ #else
int operator;
#endif
};

Autrement dit, est-ce que une structure n'aurait pas une espèce de
signature (comme une fonction) qui ferait intervenir le nom des
membres, et qui empêcherait de l'utiliser si on la falsifie.
(d'après la norme, et d'après la réalité du terrain).


C'est là où intervient l'ODR (One Definition Rule) qui dit que deux
classes sont les mêmes si et seulement si les suites de tokens en
correspondance biunivoque.
3.2/5
[...] Given such an entity named D defined in more than one
translation unit, then
-- each definition of D shall consist of the same sequence of
tokens; and
[...]

Si tu violes cette règle simple, alors...


Je ne comprends pas bien le pourquoi de l'erreur. Je suppose qu'il va
maintenant compiler TOUS le headers modifiés avec un compilateur C++, donc
tout le projet utilisera la définition `__cplusplus', donc toutes les
définitions de la classe auront le même membre, ce qui ne me semble pas
violer l'ODR (le préprocesseur se chargera de virer la partie C).

Merci de m'éclairer !
--
<=- Michaël "Cortex" Monerau -=>


Avatar
Gabriel Dos Reis
"Michaël Monerau" writes:

| > Si tu violes cette règle simple, alors...
|
| Je ne comprends pas bien le pourquoi de l'erreur. Je suppose qu'il va
| maintenant compiler TOUS le headers modifiés avec un compilateur C++, donc
| tout le projet utilisera la définition `__cplusplus', donc toutes les
| définitions de la classe auront le même membre, ce qui ne me semble pas
| violer l'ODR (le préprocesseur se chargera de virer la partie C).

il faut aussi qu'il s'assure qu'aucune fonction "C" définie dans une
unité de traduction compilée par un compilateur C ne fera partie du
programme C++ final. Ce qui est rarement le cas, autrement la
question ne se poserait pas. En tout, si tu prends l'exemple répandu
des en-têtes X Windows, ce n'est clairmeent pas le cas.

-- Gaby
Avatar
Michaël Monerau
Gabriel Dos Reis wrote:
"Michaël Monerau" writes:

Si tu violes cette règle simple, alors...


Je ne comprends pas bien le pourquoi de l'erreur. Je suppose qu'il va
maintenant compiler TOUS le headers modifiés avec un compilateur
C++, donc tout le projet utilisera la définition `__cplusplus', donc
toutes les définitions de la classe auront le même membre, ce qui ne
me semble pas violer l'ODR (le préprocesseur se chargera de virer la
partie C).


il faut aussi qu'il s'assure qu'aucune fonction "C" définie dans une
unité de traduction compilée par un compilateur C ne fera partie du
programme C++ final. Ce qui est rarement le cas, autrement la
question ne se poserait pas. En tout, si tu prends l'exemple répandu
des en-têtes X Windows, ce n'est clairmeent pas le cas.


Ah, je connais pas le code X Windows. Mais je vois pas bien comment un
programme peut être le résultat d'un compilation C et C++ en même temps.
Mais je manque sûrement d'imagination et d'expérience, je te fais confiance
sur ce dernier point ;-)

Merci pour la précision.
--
<=- Michaël "Cortex" Monerau -=>



Avatar
Gabriel Dos Reis
"Michaël Monerau" writes:
| Ah, je connais pas le code X Windows.

ce n'est pas important.

Réfléchis un peu : pour quelles raisons tu voudrais partager un
en-tête entre un programme C et un programme C++ ?

-- Gaby
Avatar
Michaël Monerau
Gabriel Dos Reis wrote:
"Michaël Monerau" writes:
Ah, je connais pas le code X Windows.


ce n'est pas important.

Réfléchis un peu : pour quelles raisons tu voudrais partager un
en-tête entre un programme C et un programme C++ ?


Moi, je ne voudras pas ;-)

Plus sérieusement, on peut le vouloir dans le cas d'une lib qui doit être
accessible pour des programmeurs à la fois C et C++... Mais alors, les
headers seront utilisés pour des programmes différents, qui auront des
instances de compilations différentes, et donc qui n'auront pas de problèmes
d'ODR.

Il y a forcément quelque chose que je n'ai pas compris...
--
<=- Michaël "Cortex" Monerau -=>


Avatar
Michaël Monerau
Gabriel Dos Reis wrote:
"Michaël Monerau" writes:

Plus sérieusement, on peut le vouloir dans le cas d'une lib qui doit
être accessible pour des programmeurs à la fois C et C++... Mais
alors, les headers seront utilisés pour des programmes différents,
qui auront des instances de compilations différentes, et donc qui
n'auront pas de problèmes d'ODR.


sauf que les programmes devront être linkés contre la bibliothèque,
qui en générale est unique. Donc, le programme C++ au final va
comprendre des bouts compilés avec un compilateurs C (la bibliothèque)
qui aura vu une définition différente de celle du programme C++.


D'accord. Je n'avais pas pensé que l'ODR s'appliquait aussi aux libraries
contre lesquelles on linkait... Enfin, c'est logique maintenant que j'y
repense :)

Merci pour cet éclaircissement ;-)
--
<=- Michaël "Cortex" Monerau -=>


Avatar
Thierry Noc
"Gabriel Dos Reis" a écrit dans le message de
news:
"Thierry Noc" writes:


C'est là où intervient l'ODR (One Definition Rule) qui dit que deux
classes sont les mêmes si et seulement si les suites de tokens en
correspondance biunivoque.


et par 'token' on entend le type du membre et le nom du membre ?
c'est a dire 'int' est un token et 'operator' aussi ?

Avatar
Thierry Noc
"Loïc Joly" a écrit dans le message de
news:bk53g3$o3f$
Michaël Monerau wrote:

Pour le posteur initial, une version vraiment propre consisterait à
écrire une couche d'interface pour cette bibliothèque en C compatible
C++, mais ça rajoute un niveau de complexité.


C'est impensable car en fait c'est pas une lib. Je rajoute des modules C++ a
une appli en C dont j'ai pas le source. Ces modules doivent être chacun une
librairie dynamique (instancié explicitement et a la demande si besoin par
l'appli principale), et les modules font beaucoup appel a des fonctions et
des données publiques de l'appli.
L'appli utilise les modules au travers d'une structure de pointeurs de
fonction définie dans chaque module.

C'est donc un peu compliqué, et ce coup de membre genre 'operator' ne fait
qu'accroître le doute.

En plus, mes modules C++ utilisent une lib C++ dynamique commune qui
instancie un objet global (comme cerr par exemple) et je me demande si cet
objet est instancié par module ou qu'une seule fois (je pense que oui mais
j'ose même pas voir).

En fait j'y comprend tellement rien que sais même pas si ce genre de
considération (lib dynamique) relève du C++ ou de l'implémentation /
plate-forme.

Avatar
Gabriel Dos Reis
drkm writes:

| Gabriel Dos Reis writes:
|
| > éviter le nom « operator » est plus simple.
|
| Yep. J'ai été étonné de voir, lors de magouilles avec le code
| source de GCC, qu'il contient une telle déclaration.

le source de GCC est truffé d'abominations sans nom -- et visibelement
certains développeurs se font un point d'honneur d'écrire de telles
choses, puisque de toute façon C++ n'existe pas sur leur planète.

-- Gaby
1 2 3