Bonjour,
Je développe principalement en C++, mais je dois régulièrement appeler des API C (gstreamer par exemple).
Jusque là, je ne me posais pas trop de question et je faisais toujours attention à ne pas mélanger les allocation mémoires (pour les GstBuffer par exemple).
Là j'ai besoin de dessiner en overlay sur une surface vidéo.
J'ai créé une première version qui wrappe la mémoire d'un GstBuffer vers une QImage Qt, et je dessine facilement à l'aide d'un QPainter. Cette solution convenait bien mais je voudrais supprimer cette dépendance à Qt.
Je choisis donc cairo, qui a de forte chance d'être présent si gstreamer est là. Je vois qu'un binding cairomm existe mais le package de ma distribution a une version de retard (Gentoo). Se pose donc le problème de l'avancé du binding par rapport à la bibliothèque.
Ma question est donc quel intérêt (au delà de la syntaxe) ai-je à favoriser le binding C++ plutôt qu'utiliser directement cairo ?
D'autre part, si vous connaissez une lib C++ à la CImg pour faire ce genre de chose ?
(CImg ne convient pas car la composition nécessite un buffer argb classique entrelacé (A1R1G1B1, A2R2G2B2…) alors que CImg utilise un buffer de pixel par bloc (R1R2R3..,G1G2G3..,B1B2B3..,A1A2A3..) et que je veux dessiner directement sur la composition pour éviter les copies de buffers.
# L'intérêt? Éviter de refaire l'encapsulation, mais...
Posté par freem . Évalué à 3.
Simple: quand on utilise une lib C, il faut se fader l'encapsulation. Alors, quand ce sont des pointeurs, ça va encore, un coup de
et te résigner à ne plus utiliser que make_my_damn_struct_ptr pour initialiser tes données et la méthode get() pour y accéder. Bien sûr, aucun outil pour le garantir. Et, bien sûr, si tu dois instancier beaucoup de pointeurs, tu vas avoir un callback en rab à chaque fois, ce qui va fatalement consommer de la mémoire (mais j'imagine que la variante tableaux de unique_ptr permets d'éviter ça… tant qu'on n'a pas besoin de vector ou de list…).
Mais, ça va encore.
Tu as aussi l'alternative de faire une classe dédiée à chaque structure, mais c'est long, chiant, avec un haut risque d'erreur (comme tout code long et chiant en fait).
Par contre, si la bibliothèque n'utilise PAS des pointeurs (comme OpenGL ou les sockets BSD), la, tu l'as dans le… tu es obligé de faire des classes spécialisées: std::unique_ptr ne sait gérer que de la mémoire (et avec une interface bien lourde à utiliser en code, sans parler du fait d'avoir des callbacks dans chaque instance de pointeur…)
Personnellement, je me suis bricolé un template unique_res pour ça, qui me sert au final aussi pour les pointeurs.
Donc, le voila, l'intérêt d'utiliser des bindings: laisser le boulot chiant aux autres.
Mais, parce que tu auras noté le "mais…" de mon titre, ça veut aussi dire que tu te lies à une bibliothèque précise, de qualité variable, un peu partout dans ton code, que tu ne contrôles que peu ou prou.
Moi, je me suis aperçu qu'au final je finis toujours par encapsuler ce que je récupère de l'«étranger», alors je préfère utiliser les sources C. Les fois ou je me suis laissé aller à utiliser (par flemme) les bindings C++, j'ai finit par le regretter rapidement, pour plusieurs raisons:
Alors que souvent, les libs C, utilisées par plus de monde, souffrent moins (pas: "ne souffrent pas", mais "souffrent moins", j'insiste) de ces problèmes.
Du coup, je préfère utiliser directement les libs C et les encapsuler moi-même. De toute façon, même les objets C++ que j'importe je les encapsule, pour limiter l'impact d'un changement de lib à un nombre de fichiers restreints dans mon code.
Comme ça, le cœur est entièrement «maison» et fait appel à des interface qui elles interagissent avec les choses sur lesquelles je n'ai pas le contrôle direct.
Par contre, mon approche à un inconvénient de taille: plus de lignes de code, maintenance «plus chère» tant que les interfaces bougent (mais une fois stable, c'est le contraire).
[^] # Re: L'intérêt? Éviter de refaire l'encapsulation, mais...
Posté par tmp . Évalué à 1.
Merci,
Je vais donc continuer à utiliser l'api C en gérant l'instance et la destruction à la main. Dans mon cas cairo fait bien le job.
Par contre, je fais ça avec des pointeurs nus, avec tous les pointeur C dans une classe private d-pointer, avec les deleter dans le destructeur de cette classe.
C'est pas tip top C++ mais ça fonctionne. Je vais regarder un peu si il y a une alternative pas trop chiante.
Merci en tout cas de partager ton expérience.
# Mon modèle
Posté par tmp . Évalué à 1.
Pour information, j'encapsule de cette manière :
mais comme j'utilise c++11, j'aimerais bien utiliser une lambda pour le destructeur.
Si quelqu'un sait faire, je gagnerai un peu de temps.
[^] # Re: Mon modèle
Posté par freem . Évalué à 2.
Tu te compliques la vie, la.
Déjà, pas besoin d'écrire un foncteur, une simple fonction suffit:
Et du coup, tu peux utiliser facilement les lambda de cette façon:
Enfin, la syntaxe n'est peut-être pas exactement la bonne…
PS: ça ne te fera pas gagner de temps à l'écriture, surtout si tu ne fais pas de typedef, mais tu pourrais éventuellement en gagner à la maintenance.
# re
Posté par SimonePinneau . Évalué à -1.
Bonjour,
Eh bien, c'est toujours prudent de le réaliser avec C++, parce que c'est plus professionnel. Alors, si tu veux un coup de pouce en ce qui concerne la programmation C++, cette formation va t'aider. voici le lien:http://www.alphorm.com/tutoriel/formation-en-ligne-cplusplus
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.