SDL_BlitSurface, dit "le fourbe".

C'est trop demandé de ne pas modifier un truc qu'on colle ?

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

(Précision : ce message est aussi présent sur le forum C d'OC, ne faites pas les étonnés).

Salut!

A force de voir les débutants manipuler SDL en C++ comme on le ferait en C (alors que ce n'est pas safe dans le premier). Leur conseiller d'écrire un wrapper (ce qu'ils ne font pas bien entendu). Je me suis dit que coder moi-même le wrapper et le proposer en DL libre sur le forum, ça pourrait être une bonne idée (et un bon moyen de faire remarquer aux méchants débutants qu'ils sont inexcusables et voués à l'enfer, bref passons).

Il m'a semblé cohérent de décréter que ma classe SDL::Surface avait une sémantique d'entité (si vous ne savez pas ce qu'est une classe, vous pouvez passer au paragraphe suivant, ce n'est pas le coeur du problème, juste une discussion possible pour ceux qui verraient un problème côté conception). Et donc, qu'elle aurait un constructeur de copie / opérateur d'affectation par copie (elle possède également la move-semantic).

Or qui dit constructeur de copie, dit copie de la SDL::Surface, qui se doit d'être "const" en C++. Et c'est là que les problèmes arrivent.

Le moyen le plus simple de faire une copie d'une SDL_Surface (la structure C SDL), c'est de faire "création de la bonne taille + SDL_BlitSurface". Or, cette fonction prend en paramètre la surface source comme "non-const". Après quelques recherches, il s'avère que du point de vue de l'implémentation de SDL, c'est un choix voulu et assumé (on pourrait parler de sa justification d'un point de vue conception, m'enfin …).

Je me pose donc la question de ce qui serait le moins moche :

  • supprimer le "const" de la surface à coup de cast : cette méthode me plaît moyen, en particulier parce que le non-const est justifié, la structure interne de la surface source est réellement modifiée.
  • tempérer la solution précédente en utilisant un wrapping de la fonction de blit pour isoler au maximum de downcast, mais c'eest toujours pas très joli.
  • faire une deep-copy de la structure SDL_Surface : cette méthode me conviendrait mais les chances de faire une connerie sont monumentales, manipulation d'un void* + dimensions + pitch(?) + BytePerPixel, obligé de faire également une deep-copy du pixel format, etc …
  • une autre solution qui existe et que je n'ai pas vu ?*

(*) j'ai déjà regardé du côté de CreateRGBSurfaceFrom mais la lib ne fait pas de copie du pixel data donc ça veut dire une étape de manipulation supplémentaire et une implémentation différente au sein d'une même classe, cette solution est vraiment celle que je veux éviter à tout prix.

Bref. Des idées ?

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+0 -0
Staff

Cette réponse a aidé l'auteur du sujet

Perso je ferais un downcast. SDL ne met pas de const, tu n'y peut rien. Profite en pour faire du propre. C'est ta lib qui assure ce passage là en te basant sur les infos que tu as de la SDL. Je vois pas trop ce que tu peux faire de mieux.

+0 -0
Auteur du sujet

Justement c'est plus fort que ça, SDL ne met pas de const parce qu'il modifie effectivement la structure de la surface que l'on colle. La seule solution pour moi est de décréter que la partie modifiée (clip_rect si j'ai bien compris) ne fait pas partie de l'invariant de la classe.

Donc en gros, ça veut dire une très grosse phase de documentation histoire de savoir si c'est valide, tout ça pour l'encapsulation d'une seule fonction. Je dois admettre que ça m'enchante pas des masses ^^' , mais bon à la guerre comme à la guerre hein.

Je laisse encore le post ouvert quelque temps au cas où d'autres idées traîneraient.

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+0 -0
Staff

Ha alors ça dépend de ton courage effectivement. En gros, si j'ai bien compris, il faut que tu arrive à savoir si ces champs auraient mérité un mutable ? Bonne chance ! Après si le but est d'aidé des débutant, je ne sais pas si ça vaut le coup d'aller jusque là, à toi de voir…

+1 -0
Auteur du sujet

Le but n'est pas tant de fournir une aide que de fournir le wrapper déjà réalisé et quitte à faire un wrapper pour SDL, autant en faire un qui tienne la route (oui j'ai regardé les wrappers déjà existants).

Le mutable sauverait effectivement les meubles mais j'ai peur de désactiver beaucoup d'optis, du coup je vais me documenter plus ^^ .

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+0 -0
Auteur du sujet

Alors ça c'est généralement le premier conseil que je donne : utilisez SFML, c'est du C++. Mais généralement la réponse c'est "je connais mieux SDL", donc du coup il faut faire un wrapper pour l'utiliser en C++ :-° .

Édité par Ksass`Peuk

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+0 -0

Hum… sémantique d'entité copiable… tu cherches les ennuis ?

(pas vu ta discussion sur OCR)

Pa compris ta phrase de SDL::Surface qui doit être const. Dans quel contexte ? De quel const tu parles ? (ou alors, dans la phrase "Or qui dit constructeur de copie, dit copie de la SDL::Surface, qui se doit d'être "const" en C++. Et c'est là que les problèmes arrivent.", il fallait lire "SDL_Surface" ?) Tu as quelque chose comme ça ?

1
2
3
class Surface {
    SDL_Surface s;
};

Édité par gbdivers

+0 -0
Auteur du sujet

Hum… sémantique d'entité copiable… tu cherches les ennuis ? ```

gbdivers

Faut que j'apprenne à relire mes posts plus consciencieusement, je voulais dire valeur bien sûr …

Pa compris ta phrase de SDL::Surface qui doit être const. Dans quel contexte ? De quel const tu parles ? (ou alors, dans la phrase "Or qui dit constructeur de copie, dit copie de la SDL::Surface, qui se doit d'être "const" en C++. Et c'est là que les problèmes arrivent.", il fallait lire "SDL_Surface" ?) Tu as quelque chose comme ça ?

1
2
3
class Surface {
    SDL_Surface s;
};

gbdivers

Plutôt comme ça :

1
2
3
4
5
6
7
namespace SDL{
class Surface{
private:
  SDL_Surface* sdl_s;

public:
  Surface(Surface const& s); //et c'est lui qui m'ennuie.

EDIT: Autant pour moi, j'avais oublié le truc pourri de la propagation de const avec les pointeurs … J'arrive pas à me l'ancrer ce truc, il est vraiment trop faible à mon goût. J'ai une autre erreur mais du coup c'est juste de l'utilisation.

C'est où le bouton pour "sujet résolu" ? O.o. Trouvé.

Édité par Ksass`Peuk

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+0 -0
Auteur du sujet

(pointeur nu ? bouhhh…)

gbdivers

Allocation par SDL, c'est précisément pour ça que j'encapsule tout (et concrètement c'est tout ce que fera le wrapper). J'aurais aussi pu créer une classe deleter faisant le SDL_FreeSurface, mais je trouvais que c'était plus lourd que juste implémenter le destructeur de Surface.

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+0 -0

Je viens de lire le topique et quand j'ai lu :

Autant pour moi, j'avais oublié le truc pourri de la propagation de const avec les pointeurs

Je me suis dit "ah finalement il a fini par se rendre compte que son problème n'en est pas un" ^^

Sinon, tu peux toujours aller regarder la fonction SDL_ConvertSurface(). C'est ce que j'utilisais pour ma sur-couche de SDL_Surface dans mon Snake en C++ (je ne connaissais pas SFML et j'avais pas envie d'en prendre le temps).

Édité par louk

+0 -0
Auteur du sujet

A mes yeux, c'est un problème. Quand on met const à une fonction, on est assez content que le compilateur assure pour nous que l'invariant de la classe ne sera pas brisé, le problème c'est du coup sa sémantique dans C++ est trop faible pour exprimer ça, ici l'invariant qui nous intéresse c'est le contenu de la mémoire pointée, pas le pointeur. Du coup, il va falloir que je rajoute des checks d'invariant à la main (et ça me gonfle un peu).

J'ai fini par faire un blit en mode sale bourrin mais ça ne me plaît pas de masse, je vais jeter un oeil à convert.

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte