GObject - GObject

GObjet
Développeur (s) Le projet GNOME
Première version 11 mars 2002 ; Il y a 19 ans  ( 11/03/2002 )
Version stable 2.66.7 (11 février 2021 ; il y a 55 jours ) [±]  ( 11/02/2021 )
Écrit en C
Système opérateur Multiplateforme
Disponible en Multilingue
Taper Bibliothèque de logiciels
Licence GNU LGPL
Site Internet développeur .gnome .org / gobject / stable /
Image
Comme la bibliothèque GNU C sert de wrapper pour les appels système du noyau Linux , les bibliothèques fournies dans GLib (GObject, Glib , GModule , GThread et GIO ) servent de wrappers supplémentaires pour leurs tâches spécifiques.

Le système d'objets GLib , ou GObject , est une bibliothèque de logiciels libres fournissant un système d'objets portable et une interopérabilité transparente entre les langues. GObject est conçu pour être utilisé à la fois directement dans les programmes C pour fournir des API C orientées objet et via des liaisons avec d'autres langages pour fournir une interopérabilité transparente entre les langues, par exemple PyGObject .

Introspection GObject

L'histoire

Dépendant uniquement de GLib et de la libc , GObject est une pierre angulaire de GNOME et est utilisé dans GTK , Pango , ATK et la plupart des bibliothèques GNOME de niveau supérieur comme GStreamer et les applications. Avant GTK + 2.0, un code similaire à GObject faisait partie de la base de code GTK. (Le nom «GObject» n'était pas encore utilisé - la classe de base commune a été appelée GtkObject .)

Lors de la sortie de GTK + 2.0, le système d'objets a été extrait dans une bibliothèque distincte en raison de son utilité générale. Dans le processus, la plupart des parties non spécifiques à l' interface graphique de la GtkObject classe ont été déplacées vers GObject la nouvelle classe de base commune. Ayant existé en tant que bibliothèque séparée depuis le 11 mars 2002 (date de sortie de GTK + 2.0), la bibliothèque GObject est maintenant utilisée par de nombreux programmes non-GUI tels que les applications de ligne de commande et serveur .

Relation avec GLib

Bien que GObject ait son propre ensemble de documentation distinct et soit généralement compilé dans son propre fichier de bibliothèque partagé , le code source de GObject réside dans l' arborescence des sources de GLib et est distribué avec GLib. Pour cette raison, GObject utilise les numéros de version de GLib et est généralement emballé avec GLib (par exemple, Debian place GObject dans sa libglib2.0 famille de paquets).

Le système de typage

Au niveau le plus élémentaire du framework GObject se trouve un système de type générique et dynamique appelé GType. Le système GType contient une description d'exécution de tous les objets permettant au code glue de faciliter les liaisons de plusieurs langues. Le système de types peut gérer toute structure de classe héritée individuellement , en plus des types non classés tels que des pointeurs opaques , des chaînes et des nombres entiers et des nombres à virgule flottante de différentes tailles .

Le système de types sait comment copier, affecter et détruire les valeurs appartenant à l'un des types enregistrés. C'est trivial pour les types comme les entiers, mais de nombreux objets complexes sont comptés par référence , tandis que certains sont complexes mais pas de référence. Lorsque le système de type «copie» un objet compté par référence, il ne fera généralement qu'augmenter son nombre de références, tandis que lors de la copie d'un objet complexe, non compté par référence (tel qu'une chaîne), il créera généralement une copie réelle en allouant mémoire .

Cette fonctionnalité de base est utilisée pour l'implémentation GValue , un type de conteneur générique qui peut contenir des valeurs de tout type connu par le système de types. Ces conteneurs sont particulièrement utiles lors de l'interaction avec des environnements de langage à typage dynamique dans lesquels toutes les valeurs natives résident dans de tels conteneurs étiquetés de type .

Types fondamentaux

Les types qui n'ont aucune classe associée sont appelés non classés . Ces types, ainsi que tous les types qui correspondent à une forme de classe racine , sont appelés types fondamentaux : les types à partir desquels tous les autres types sont dérivés. Celles-ci constituent un ensemble relativement fermé, mais bien que l'utilisateur moyen ne soit pas censé créer ses propres types fondamentaux, la possibilité existe et a été exploitée pour créer des hiérarchies de classes personnalisées - c'est-à-dire des hiérarchies de classes non basées sur la GObject classe.

Depuis GLib 2.9.2, les types fondamentaux intégrés non classés sont:

  • un type vide, correspondant à C's void ( G_TYPE_NONE );
  • correspondant aux types C est signé et non signé char , int , long , et des nombres entiers de 64 bits ( G_TYPE_CHAR , G_TYPE_UCHAR , G_TYPE_INT , G_TYPE_UINT , G_TYPE_LONG , G_TYPE_ULONG , G_TYPE_INT64 , et G_TYPE_UINT64 );
  • un type booléen ( G_TYPE_BOOLEAN );
  • un type d'énumération et un type «flags», tous deux correspondant au enum type de C , mais différant en ce que ce dernier n'est utilisé que pour les champs de bits ( G_TYPE_ENUM et G_TYPE_FLAGS );
  • types pour flotteurs IEEE simple et double précision , correspondant à C float et double ( G_TYPE_FLOAT et G_TYPE_DOUBLE );
  • un type de chaîne, correspondant à C's char * ( G_TYPE_STRING );
  • un type de pointeur opaque, correspondant à C's void * ( G_TYPE_POINTER ).

Les types fondamentaux intégrés classés sont:

  • un type de classe de base pour les instances de GObject , la racine de l'arbre d'héritage de classe standard ( G_TYPE_OBJECT )
  • un type d'interface de base, analogue au type de classe de base mais représentant la racine de l' arbre d'héritage d' interface standard ( G_TYPE_INTERFACE )
  • un type pour les structures en boîte , qui sont utilisées pour envelopper des objets de valeur simples ou des objets étrangers dans des «boîtes» comptées par référence ( G_TYPE_BOXED )
  • un type pour les «objets de spécification de paramètres», qui sont utilisés dans GObject pour décrire les métadonnées des propriétés d'objet ( G_TYPE_PARAM ).

Les types qui peuvent être instanciés automatiquement par le système de types sont appelés instanciables . Une caractéristique importante de ces types est que les premiers octets de toute instance contiennent toujours un pointeur vers la structure de classe (une forme de table virtuelle ) associée au type de l'instance. Pour cette raison, tout type instanciable doit être classé. De manière contraire, tout type non classé (tel qu'un entier ou une chaîne ) doit être non instanciable. D'un autre côté, la plupart des types classés sont instanciables, mais certains, comme les types d'interface, ne le sont pas.

Types dérivés

Les types dérivés des types fondamentaux GObject intégrés se répartissent à peu près en quatre catégories:

Types énumérés et types «indicateurs»
En général, chaque type énuméré et chaque type de champ de bits basé sur un entier (c'est-à-dire chaque enum type) que l'on souhaite utiliser d'une manière liée au système d'objet - par exemple, en tant que type d'une propriété d'objet - doit être enregistré avec le système de typage. En règle générale, le code d'initialisation qui prend en charge l'enregistrement de ces types est généré par un outil automatisé appelé glib-mkenums et stocké dans un fichier séparé.
Types en boîte
Certaines structures de données qui sont trop simples pour être des types de classe à part entière (avec tous les frais généraux encourus) peuvent encore devoir être enregistrées avec le système de types. Par exemple, nous pourrions avoir une classe à laquelle nous voulons ajouter une background-color propriété, dont les valeurs devraient être des instances d'une structure qui ressemble à . Pour éviter d'avoir à sous - classer , nous pouvons créer un type encadré pour représenter cette structure, et fournir des fonctions de copie et de libération. GObject est livré avec une poignée de types encadrés encapsulant des types de données GLib simples. Une autre utilisation des types en boîte est un moyen d'envelopper des objets étrangers dans un conteneur étiqueté que le système de types peut identifier et sait comment copier et libérer. struct color { int r, g, b; }GObject
Types de pointeurs opaques
Parfois, pour les objets qui ne doivent être ni copiés, ni comptés par référence, ni libérés, même un type encadré serait excessif . Bien que de tels objets puissent être utilisés dans GObject en les traitant simplement comme des pointeurs opaques ( G_TYPE_POINTER ), il est souvent judicieux de créer un type de pointeur dérivé, documentant le fait que les pointeurs doivent référencer un type particulier d'objet, même si rien d'autre n'est dit à ce sujet.
Types de classe et d'interface
La plupart des types dans une application GObject seront des classes - dans le sens orienté objet normal du mot - provenant directement ou indirectement de la classe racine, GObject . Il existe également des interfaces qui, contrairement aux interfaces de style Java classiques , peuvent contenir des méthodes implémentées. Les interfaces GObject peuvent donc être décrites comme des mixins .

Système de messagerie

Le système de messagerie GObject se compose de deux parties complémentaires: les fermetures et les signaux .

Fermetures
Une fermeture GObject est une version généralisée d'un callback . Il existe un support pour les fermetures écrites en C et C ++, ainsi que pour les langages arbitraires (lorsque des liaisons sont fournies). Cela permet au code écrit (par exemple) en Python et Java d'être appelé via une fermeture GObject.
Signaux
Les signaux sont le principal mécanisme par lequel les fermetures sont appelées. Les objets enregistrent les écouteurs de signaux avec le système de types, spécifiant un mappage entre un signal donné et une fermeture donnée. Lors de l'émission d'un signal enregistré, la fermeture de ce signal est invoquée. Dans GTK, tous les événements de l'interface graphique native (tels que les mouvements de la souris et les actions du clavier) peuvent générer des signaux GObject sur lesquels les auditeurs peuvent potentiellement agir.

Implémentation de classe

Chaque classe GObject est implémentée par au moins deux structures: la structure de classe et la structure d'instance .

La structure de classe
La structure de classe correspond à la vtable d'une classe C ++. Il doit commencer par la structure de classe de la superclasse. Ensuite, il contiendra un ensemble de pointeurs de fonction - un pour chaque méthode virtuelle de la classe. Des variables spécifiques à la classe peuvent être utilisées pour émuler les membres de la classe.
La structure de l'instance
La structure d'instance, qui existera dans une copie par instance d'objet, doit commencer par la structure d'instance de la superclasse (cela garantit que toutes les instances commencent par un pointeur vers la structure de classe, puisque tous les types instanciables fondamentaux partagent cette propriété). Après les données appartenant à la superclasse, la structure peut contenir toutes les variables spécifiques à l'instance, correspondant aux variables membres C ++.

La définition d'une classe dans le framework GObject est complexe, nécessitant de grandes quantités de code standard , telles que des définitions manuelles de macros de conversion de type et d'incantations d'enregistrement de type obscures. De plus, comme une structure C ne peut pas avoir de modificateurs d'accès tels que «public», «protected» ou «private», des solutions de contournement doivent être utilisées pour fournir l' encapsulation . Une approche consiste à inclure un pointeur vers les données privées - appelées de manière conventionnelle _priv - dans la structure de l'instance. La structure privée peut être déclarée dans le fichier d'en-tête public, mais définie uniquement dans le fichier d'implémentation, avec pour effet que les données privées sont opaques pour les utilisateurs, mais transparentes pour l'implémenteur. Si la structure privée est enregistrée avec GType, elle sera automatiquement allouée par le système d'objets. En effet, il n'est même pas nécessaire d'inclure le _priv pointeur, si l'on est prêt à utiliser l'incantation à G_TYPE_INSTANCE_GET_PRIVATE chaque fois que les données privées sont nécessaires.

Pour résoudre certaines de ces complexités, il existe plusieurs langages de niveau supérieur que la source vers la source compile en GObject en C. Le langage de programmation Vala utilise une syntaxe de style C # et est prétraité en code C vanille . Le GObject Builder, ou GOB2 , propose une syntaxe de modèle rappelant Java .

Usage

La combinaison de C et GObject est utilisée dans de nombreux projets de logiciels libres réussis , tels que le bureau GNOME , la boîte à outils GTK et le programme de manipulation d'images GIMP .

Bien que de nombreuses applications GObject soient entièrement écrites en C, le système GObject s'intègre parfaitement aux systèmes d'objets natifs de nombreux autres langages, tels que C ++ , Java , Ruby , Python , Common Lisp et .NET / Mono . En conséquence, il est généralement relativement simple de créer des liaisons de langage pour des bibliothèques bien écrites qui utilisent le framework GObject.

L'écriture de code GObject en C en premier lieu, cependant, est relativement verbeuse. La bibliothèque prend beaucoup de temps à apprendre, et les programmeurs ayant de l'expérience dans les langages orientés objet de haut niveau trouvent souvent quelque peu fastidieux de travailler avec GObject en C. Par exemple, créer une sous-classe (même juste une sous-classe de GObject ) peut nécessiter écrire et / ou copier de grandes quantités de code standard . Cependant, l'utilisation de Vala , un langage conçu principalement pour fonctionner avec GObject et qui se convertit en C, rendra probablement le travail avec GObject ou l'écriture de bibliothèques basées sur GObject plus agréables.

Bien qu'ils ne soient pas vraiment des objets de première classe (il n'y a pas de métatypes réels dans GType), les métaobjets tels que les classes et les interfaces sont créés par les applications GObject au moment de l'exécution et fournissent un bon support pour l' introspection . Les capacités introspectives sont utilisées par les liaisons de langage et les applications de conception d'interface utilisateur comme Glade pour permettre de faire des choses comme le chargement d'une bibliothèque partagée qui fournit une classe GObject - généralement une sorte de widget , dans le cas de Glade - et ensuite obtenir une liste de toutes les propriétés de la classe, avec les informations de type et les chaînes de documentation.

Comparaisons avec d'autres systèmes d'objets

Puisque GObject fournit un système d'objets essentiellement complet pour C, il peut être considéré comme une alternative aux langages dérivés du C tels que C ++ et Objective-C . (Bien que les deux offrent également de nombreuses autres fonctionnalités au-delà de leurs systèmes d'objets respectifs.) Une différence facilement observée entre C ++ et GObject est que GObject (comme Java) ne prend pas en charge l' héritage multiple .

L'utilisation de GObject de GLib « g_malloc s () fonction d'allocation de mémoire entraînera le programme pour quitter sans condition à l' épuisement de la mémoire, contrairement à la de la bibliothèque C malloc (), C ++ » s nouvelles et autres allocataires de mémoire commun qui permettent à un programme pour faire face à ou même récupérer complètement des situations de manque de mémoire sans simplement planter. Cela a tendance à ne pas inclure GObject dans un logiciel où la résilience face à une mémoire limitée est importante, ou lorsque de très nombreux ou très gros objets sont couramment manipulés. La fonction g_try_new () peut être utilisée lorsqu'une allocation de mémoire est plus susceptible d'échouer (pour un gros objet par exemple), mais cela ne peut pas garantir que l'allocation n'échouera pas ailleurs dans le code.

Une autre différence importante est que si C ++ et Objective-C sont des langages séparés, GObject est strictement une bibliothèque et en tant que tel n'introduit aucune nouvelle syntaxe ou intelligence du compilateur. Par exemple, lors de l'écriture de code C basé sur GObject, il est souvent nécessaire d'effectuer une remontée explicite . Par conséquent, «C with GObject», considéré comme un langage distinct du C brut, est un sur-ensemble strict de C simple - comme Objective C, mais contrairement au C ++.

Sur les plates-formes où il n'y a pas d' ABI standard qui fonctionne sur tous les compilateurs C ++ (ce qui n'est généralement pas le cas, puisque soit l'Itanium ABI soit l'ABI Microsoft sont généralement suivis), une bibliothèque compilée avec un compilateur C ++ n'est pas toujours en mesure d'appeler un bibliothèque compilée avec une autre. Si une telle compatibilité est requise, les méthodes C ++ doivent être exportées en tant que fonctions C simples, ce qui va en partie à l'encontre de l'objectif du système d'objets C ++. Le problème se produit en partie parce que différents compilateurs C ++ utilisent différents types de modification de nom pour garantir l'unicité de tous les symboles exportés. (Ceci est nécessaire car, par exemple, deux classes différentes peuvent avoir des fonctions membres nommées de manière identique, un nom de fonction peut être surchargé plusieurs fois, ou des fonctions nommées de manière identique peuvent apparaître dans différents espaces de noms , mais dans le code objet, ces chevauchements ne sont pas autorisés.) Par contre, puisque C ne prend en charge aucune forme de surcharge ou d'espacement de noms, les auteurs de bibliothèques C utiliseront généralement des préfixes explicites pour garantir l'unicité globale de leurs noms exportés. Par conséquent, bien qu'elle soit orientée objet, une bibliothèque basée sur GObject écrite en C utilisera toujours les mêmes noms de symboles externes quel que soit le compilateur utilisé.

La différence la plus profonde est peut-être l'accent mis par GObject sur les signaux (appelés événements dans d'autres langues). Cette emphase vient du fait que GObject a été spécifiquement conçu pour répondre aux besoins d'une boîte à outils GUI. Bien qu'il existe des bibliothèques de signaux pour la plupart des langages orientés objet, dans le cas de GObject, il est intégré au système d'objets. Pour cette raison, une application GObject typique aura tendance à utiliser des signaux dans une bien plus grande mesure qu'une application non-GObject le ferait, ce qui rend les composants GObject beaucoup plus encapsulés et réutilisables que ceux utilisant du C ++ ou Java. Si vous utilisez glibmm / gtkmm , les wrappers C ++ officiels de Glib / GTK respectivement, le projet frère libsigc ++ permet une utilisation facile des signaux GObject sous-jacents en utilisant le C ++ standard. Bien sûr, d'autres implémentations de signaux sont disponibles sur presque toutes les plates-formes, bien qu'une bibliothèque supplémentaire soit parfois nécessaire, comme Boost.Signals2 pour C ++.

Voir également


Références

Liens externes