Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Encapsulation de données en C

7 réponses
Avatar
Florent
Bonjour,

Je suis actuellement en train d'écrire un petit moteur de rendu 3D (F3D).
Pour cela, j'ai une structure F3D_mesh dans laquelle l'utilisateur fournit
la description de l'objet à afficher, puis la passe aux fonctions du
module F3D_render.

Seulement voilà, il y a certains champs de F3D_mesh que je voudrais
publiques, comme la liste de vertex, de couleurs, etc., que l'utilisateur
va remplir, et d'autres champs dont je voudrais que seules les fonctions
du module F3D_render puisse accéder, comme l'identifiant de display list
(affichage en OpenGL), les "vertex arrays" etc.

Donc j'ai créé, en plus de la structure F3D_mesh, une structure
F3D_mesh_private, et les données sont organisées comme suit :

typedef struct f3d_mesh {
/* les données publiques */
...
F3D_mesh_private* private_data; /* données privées */
} F3D_mesh;

Comment puis-je faire pour que l'utilisateur n'ait pas la définition de
la structure F3D_mesh_private ? J'ai essayé en mettant void*
private_data, avec la structure F3D_mesh_private définie dans F3D_mesh.c
au et F3D_mesh dans F3D_mesh.h.
Mais si je fais cela :
mesh->private_data = (F3D_mesh_private*) malloc( sizeof(F3D_mesh_private) );
le compilateur refuse évidemment.
Et si je fais cela :
mesh->private_data = (void*) malloc( sizeof(F3D_mesh_private) );
ça ne marche pas non plus, puisque je ne peux plus accéder aux champs de
la structure, même en y accédant avec un cast :
(F3D_mesh_private*)(mesh->private_data)->display_list = ...
Le compilateur me donne un warning "dereferencing 'void*' pointer" et une
erreur "request for member 'display_list' in something not a structure or
union".

Je vois que j'en ai écrit déjà beaucoup pour mon problème, mais
c'était pour bien poser mes contraintes et ce que j'avais déjà tenté.
Quelqu'un a-t-il une solution pour implémenter cette encapsulation de
données privées ?

Merci,

Florent.

PS : Je sais qu'en C++ ce serait plus facile, mais j'ai décidé de faire
ce projet en C, et je compte bien m'y tenir :)

7 réponses

Avatar
K. Ahausse
"Florent" a écrit dans le message de
news:
Bonjour,

Je suis actuellement en train d'écrire un petit moteur de rendu 3D (F3D).
Pour cela, j'ai une structure F3D_mesh dans laquelle l'utilisateur fournit
la description de l'objet à afficher, puis la passe aux fonctions du
module F3D_render.

Seulement voilà, il y a certains champs de F3D_mesh que je voudrais
publiques, comme la liste de vertex, de couleurs, etc., que l'utilisateur
va remplir, et d'autres champs dont je voudrais que seules les fonctions
du module F3D_render puisse accéder, comme l'identifiant de display list
(affichage en OpenGL), les "vertex arrays" etc.

Donc j'ai créé, en plus de la structure F3D_mesh, une structure
F3D_mesh_private, et les données sont organisées comme suit :

typedef struct f3d_mesh {
/* les données publiques */
...
F3D_mesh_private* private_data; /* données privées */
} F3D_mesh;

Comment puis-je faire pour que l'utilisateur n'ait pas la définition de


De quel utilisateur s'agit-il ?

S'il s'agit de l'utilisateur au sens C++, il te faudra deux fichiers
headers, un complet, un masquant les données.

la structure F3D_mesh_private ? J'ai essayé en mettant void*
private_data, avec la structure F3D_mesh_private définie dans F3D_mesh.c
au et F3D_mesh dans F3D_mesh.h.
Mais si je fais cela :
mesh->private_data = (F3D_mesh_private*) malloc(
sizeof(F3D_mesh_private) );

le compilateur refuse évidemment.
Et si je fais cela :
mesh->private_data = (void*) malloc( sizeof(F3D_mesh_private) );
ça ne marche pas non plus, puisque je ne peux plus accéder aux champs de
la structure, même en y accédant avec un cast :
(F3D_mesh_private*)(mesh->private_data)->display_list = ...
Le compilateur me donne un warning "dereferencing 'void*' pointer" et une
erreur "request for member 'display_list' in something not a structure or
union".

Je vois que j'en ai écrit déjà beaucoup pour mon problème, mais
c'était pour bien poser mes contraintes et ce que j'avais déjà tenté.
Quelqu'un a-t-il une solution pour implémenter cette encapsulation de
données privées ?

Merci,

Florent.

PS : Je sais qu'en C++ ce serait plus facile, mais j'ai décidé de faire
ce projet en C, et je compte bien m'y tenir :)


Avatar
Yves ROMAN

Bonjour,

Je suis actuellement en train d'écrire un petit moteur de rendu 3D (F3D).
Pour cela, j'ai une structure F3D_mesh dans laquelle l'utilisateur fournit
la description de l'objet à afficher, puis la passe aux fonctions du
module F3D_render.

Seulement voilà, il y a certains champs de F3D_mesh que je voudrais
publiques, comme la liste de vertex, de couleurs, etc., que l'utilisateur
va remplir, et d'autres champs dont je voudrais que seules les fonctions
du module F3D_render puisse accéder, comme l'identifiant de display list
(affichage en OpenGL), les "vertex arrays" etc.

Donc j'ai créé, en plus de la structure F3D_mesh, une structure
F3D_mesh_private, et les données sont organisées comme suit :

typedef struct f3d_mesh {
/* les données publiques */
...
F3D_mesh_private* private_data; /* données privées */
} F3D_mesh;

Comment puis-je faire pour que l'utilisateur n'ait pas la définition de
la structure F3D_mesh_private ? J'ai essayé en mettant void*
private_data, avec la structure F3D_mesh_private définie dans F3D_mesh.c
au et F3D_mesh dans F3D_mesh.h.
Mais si je fais cela :
mesh->private_data = (F3D_mesh_private*) malloc( sizeof(F3D_mesh_private) );
le compilateur refuse évidemment.
Et si je fais cela :
mesh->private_data = (void*) malloc( sizeof(F3D_mesh_private) );
ça ne marche pas non plus, puisque je ne peux plus accéder aux champs de
la structure, même en y accédant avec un cast :
(F3D_mesh_private*)(mesh->private_data)->display_list = ...
Le compilateur me donne un warning "dereferencing 'void*' pointer" et une
erreur "request for member 'display_list' in something not a structure or
union".

Le warning est normal. Tu peux peut-être l'éviter en passant par une variable

intermédiaire de type F3D_mesh_private *
F3D_mesh_private * prv = malloc( sizeof(*prv) );
...
mesh->private_data = prv ;
...
prv->diplay_list = ...

ou

F3D_mesh_private * prv = mesh->private_data ;
...
prv->diplay_list = ...


L'erreur est curieuse : peut-être un problème de priorité d'opérateurs.
Dans le doute je mets :
((F3D_mesh_private*)(mesh->private_data))->display_list = ...
au cas ou le -> serait prioritaire sur le cast , ce qui me semble bien etre le
cas maintenant que je l'écris

Avatar
Florent
Le Thu, 08 Apr 2004 16:52:26 +0200, Yves ROMAN a écrit :
L'erreur est curieuse : peut-être un problème de priorité d'opérateurs.
Dans le doute je mets :
((F3D_mesh_private*)(mesh->private_data))->display_list = ...
au cas ou le -> serait prioritaire sur le cast , ce qui me semble bien etre le
cas maintenant que je l'écris


Je suis un idiot !
Non seulement c'était bien un manque de parenthèses, mais en plus ma
conception est mauvaise : en effet, le module F3D_render doit avoir accès
à la structure F3D_mesh_private, donc je ne peux pas la déclarer dans
F3D_mesh.c ...

On ne peut pas déclarer une structure sans la définir en C, un peu comme
en C++ quand on met simplement class Toto; pour éviter d'inclure toto.h ?

J'ai essayé en ajoutant
typedef struct f3d_mesh_private F3D_mesh_private;
au début de F3D_render.c mais un peu plus loin, sur cette ligne :
((F3D_mesh_private*)(mesh->private_data))->display_list = glGenLists(1);
j'ai une erreur "dereferencing pointer to incomplete type" ...

Florent.

Avatar
Florent
Le Thu, 08 Apr 2004 17:59:38 +0200, Florent a écrit :
J'ai essayé en ajoutant
typedef struct f3d_mesh_private F3D_mesh_private;
au début de F3D_render.c mais un peu plus loin, sur cette ligne :
((F3D_mesh_private*)(mesh->private_data))->display_list = glGenLists(1);
j'ai une erreur "dereferencing pointer to incomplete type" ...

Florent.


Finalement j'ai opté pour ajouter un F3D_mesh_private.h qui est inclus
dans F3D_mesh.c et F3D_render.c, et qui contient uniquement la définition
de la structure F3D_mesh_private. Mais je suis avide de vos suggestions
quant à une méthode plus simple/élégante. Je n'aime que moyennement
l'idée de multiplier les headers pour un même module :(

Florent.

Avatar
Florent
Le Thu, 08 Apr 2004 16:27:15 +0200, K. Ahausse a écrit :
De quel utilisateur s'agit-il ?


Il s'agit du programmeur qui va utiliser la librairie de mon moteur 3D (en
premier, moi ;)

S'il s'agit de l'utilisateur au sens C++, il te faudra deux fichiers
headers, un complet, un masquant les données.


C'est la solution que j'ai utilisée, mais ça ne me convient que
moyennement de devoir doubler les headers de mes modules dès que j'aurai
des donnés privées :(

Florent

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', Florent wrote:

Donc j'ai créé, en plus de la structure F3D_mesh, une structure
F3D_mesh_private, et les données sont organisées comme suit :

typedef struct f3d_mesh {
/* les données publiques */
...
F3D_mesh_private* private_data; /* données privées */
} F3D_mesh;


Ca me va. Pour être opaque, il faut définir (publiquement)

typedef struct F3D_mesh_private F3D_mesh_private;

et dans la zone privée:

struct F3D_mesh_private
{
...
};

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=cpp
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', Florent wrote:

Finalement j'ai opté pour ajouter un F3D_mesh_private.h qui est inclus
dans F3D_mesh.c et F3D_render.c, et qui contient uniquement la définition
de la structure F3D_mesh_private. Mais je suis avide de vos suggestions
quant à une méthode plus simple/élégante. Je n'aime que moyennement
l'idée de multiplier les headers pour un même module :(


Si une partie doit être 'public' et l'autre 'public restrint', il n'y a pas
d'autre solution. Cette solution est tout à fait courante et acceptée.
L'utilisateur ne s'en rend évidemment pas compte.

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=cpp
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/