El objeto GLib Sistema , o GObject , es una libre biblioteca de software que proporciona un portátil sistema de objetos y transparente interoperabilidad entre lenguajes. GObject está diseñado para usarse directamente en programas C para proporcionar API basadas en C orientadas a objetos y mediante enlaces a otros lenguajes para proporcionar interoperabilidad transparente entre lenguajes, por ejemplo, PyGObject .
Desarrollador (es) | El proyecto GNOME |
---|---|
Versión inicial | 11 de marzo de 2002 |
Lanzamiento estable | 2.66.7 (11 de febrero de 2021 [±] [1] | )
Escrito en | C |
Sistema operativo | Multiplataforma |
Disponible en | Multilingüe [ ¿cuál? ] |
Tipo | Biblioteca de software |
Licencia | GNU LGPL |
Sitio web | desarrollador |
![](http://wikiimg.tojsiabtv.com/wikipedia/commons/thumb/4/45/Linux_kernel_System_Call_Interface_and_glibc.svg/300px-Linux_kernel_System_Call_Interface_and_glibc.svg.png)
Introspección de GObject
- La introspección de GObject (abreviado GIR [2] ) es una capa de middleware entre las bibliotecas C (usando GObject) y los enlaces de lenguaje, cf. Lista de enlaces de idioma para GTK .
Historia
Dependiendo solo de GLib y libc , GObject es una piedra angular de GNOME y se usa en GTK , Pango , ATK y la mayoría de las bibliotecas GNOME de nivel superior como GStreamer y aplicaciones. Antes de GTK + 2.0, un código similar a GObject formaba parte de la base de código GTK. (El nombre "GObject" aún no estaba en uso; se llamó a la clase base común GtkObject
).
En el lanzamiento de GTK + 2.0, el sistema de objetos se extrajo en una biblioteca separada debido a su utilidad general. En el proceso, la mayoría de las partes de la clase no específicas de GUIGtkObject
se trasladaron a GObject
la nueva clase base común. Habiendo existido como una biblioteca separada desde el 11 de marzo de 2002 (la fecha de lanzamiento de GTK + 2.0), la biblioteca GObject ahora es utilizada por muchos programas que no son GUI, como la línea de comandos y las aplicaciones de servidor .
Relación con GLib
Aunque GObject tiene su propio conjunto de documentación [3] y normalmente se compila en su propio archivo de biblioteca compartida , el código fuente de GObject reside en el árbol de fuentes de GLib y se distribuye junto con GLib. Por esta razón, GObject usa los números de versión GLib y normalmente se empaqueta junto con GLib (por ejemplo, Debian incluye GObject en su libglib2.0
familia de paquetes).
El sistema de tipos
En el nivel más básico del marco GObject se encuentra un sistema de tipos genérico y dinámico llamado GType. El sistema GType contiene una descripción en tiempo de ejecución de todos los objetos, lo que permite que el código adhesivo facilite enlaces de múltiples idiomas. El sistema de tipos puede manejar cualquier estructura de clases heredada individualmente , además de tipos no clasificados como punteros opacos , cadenas y números enteros y de coma flotante de varios tamaños .
El sistema de tipos sabe cómo copiar, asignar y destruir valores pertenecientes a cualquiera de los tipos registrados. Esto es trivial para tipos como enteros, pero muchos objetos complejos se cuentan por referencias , mientras que algunos son complejos pero no cuentan por referencias. Cuando el sistema de tipos "copia" un objeto con recuento de referencias, normalmente solo aumentará su recuento de referencias, mientras que al copiar un objeto complejo, sin recuento de referencias (como una cadena), normalmente creará una copia real asignando la memoria .
Esta funcionalidad básica se utiliza para implementar GValue
, un tipo de contenedor genérico que puede contener valores de cualquier tipo conocido por el sistema de tipos. Dichos contenedores son particularmente útiles cuando se interactúa con entornos de lenguaje de tipo dinámico en los que todos los valores nativos residen en dichos contenedores con etiquetas de tipo .
Tipos fundamentales
Los tipos que no tienen clases asociadas se denominan no clasificados . Estos tipos, junto con todos los tipos que corresponden a alguna forma de clase raíz , se conocen como tipos fundamentales : los tipos de los que se derivan todos los demás tipos. Estos forman un conjunto relativamente cerrado, pero aunque no se espera que el usuario promedio cree sus propios tipos fundamentales, existe la posibilidad y se ha aprovechado para crear jerarquías de clases personalizadas , es decir, jerarquías de clases que no se basan en la GObject
clase.
A partir de GLib 2.9.2, [4] los tipos fundamentales incorporados no clasificados son:
- un tipo vacío, correspondiente a C's
void
(G_TYPE_NONE
); - tipos correspondientes a C está firmado y sin signo
char
,int
,long
, y enteros de 64 bits (G_TYPE_CHAR
,G_TYPE_UCHAR
,G_TYPE_INT
,G_TYPE_UINT
,G_TYPE_LONG
,G_TYPE_ULONG
,G_TYPE_INT64
, yG_TYPE_UINT64
); - un tipo booleano (
G_TYPE_BOOLEAN
); - un tipo de enumeración y un tipo de “banderas”, ambos correspondientes al
enum
tipo de C , pero que se diferencian en que este último solo se usa para campos de bits (G_TYPE_ENUM
yG_TYPE_FLAGS
); - tipos para flotadores IEEE de precisión simple y doble , correspondientes a C
float
ydouble
(G_TYPE_FLOAT
yG_TYPE_DOUBLE
); - un tipo de cadena, correspondiente a C's
char *
(G_TYPE_STRING
); - un tipo de puntero opaco, correspondiente a C's
void *
(G_TYPE_POINTER
).
Los tipos fundamentales incorporados clasificados son:
- un tipo de clase base para instancias de
GObject
, la raíz del árbol de herencia de clases estándar (G_TYPE_OBJECT
) - un tipo de interfaz base, análogo al tipo de clase base pero que representa la raíz del árbol de herencia de la interfaz estándar (
G_TYPE_INTERFACE
) - un tipo para estructuras en caja , que se utilizan para envolver objetos de valor simple u objetos extraños en "cajas" contadas por referencia (
G_TYPE_BOXED
) - un tipo para "objetos de especificación de parámetros", que se utilizan en GObject para describir metadatos para propiedades de objeto (
G_TYPE_PARAM
).
Los tipos que pueden ser instanciados automáticamente por el sistema de tipos se denominan instanciables . Una característica importante de estos tipos es que los primeros bytes de cualquier instancia siempre contienen un puntero a la estructura de clases (una forma de tabla virtual ) asociada al tipo de instancia. Por esta razón, se debe clasificar cualquier tipo instanciable. Por el contrario, cualquier tipo no clasificado (como entero o cadena ) no debe ser instanciable. Por otro lado, la mayoría de los tipos clasificados son instanciables, pero algunos, como los tipos de interfaz, no lo son.
Tipos derivados
Los tipos que se derivan de los tipos fundamentales integrados de GObject se dividen aproximadamente en cuatro categorías:
- Tipos enumerados y tipos de "banderas"
- En general, cada tipo enumerado y cada tipo de campo de bits basado en números enteros (es decir, cada
enum
tipo) que uno desee usar de alguna manera que esté relacionada con el sistema de objetos, por ejemplo, como el tipo de una propiedad de objeto, debe registrarse con el sistema de tipos. Normalmente, el código de inicialización que se encarga de registrar estos tipos se genera mediante una herramienta automatizada llamadaglib-mkenums
[5] y se almacena en un archivo separado. - Tipos en caja
- Es posible que algunas estructuras de datos que son demasiado simples para convertirse en tipos de clase completos (con todos los gastos generales incurridos) deban registrarse con el sistema de tipos. Por ejemplo, podríamos tener una clase a la que queramos agregar una
background-color
propiedad, cuyos valores deberían ser instancias de una estructura similar a . Para evitar tener que crear una subclase , podemos crear un tipo en caja para representar esta estructura y proporcionar funciones para copiar y liberar. GObject se envía con un puñado de tipos en caja que envuelven tipos de datos GLib simples. Otro uso para los tipos en caja es como una forma de envolver objetos extraños en un contenedor etiquetado que el sistema de tipos puede identificar y sabrá cómo copiar y liberar.struct color { int r, g, b; }
GObject
- Tipos de puntero opaco
- A veces, para los objetos que no necesitan ser copiados, contados por referencias ni liberados, incluso un tipo en caja sería excesivo . Si bien dichos objetos se pueden usar en GObject simplemente tratándolos como punteros opacos (
G_TYPE_POINTER
), a menudo es una buena idea crear un tipo de puntero derivado, documentando el hecho de que los punteros deben hacer referencia a un tipo particular de objeto, aunque nada más es dicho al respecto. - Tipos de clase e interfaz
- La mayoría de los tipos en una aplicación GObject serán clases - en el sentido normal orientado a objetos de la palabra - derivados directa o indirectamente de la clase raíz,
GObject
. También hay interfaces que, a diferencia de las interfaces clásicas de estilo Java , pueden contener métodos implementados. Por tanto, las interfaces de GObject pueden describirse como mixins .
Sistema de mensajería
El sistema de mensajería GObject consta de dos partes complementarias: cierres y señales .
- Cierres
- Un cierre de GObject es una versión generalizada de una devolución de llamada . Existe soporte para cierres escritos en C y C ++, así como también para lenguajes arbitrarios (cuando se proporcionan enlaces). Esto permite que el código escrito en (por ejemplo) Python y Java se invoque a través de un cierre de GObject.
- Señales
- Las señales son el mecanismo principal mediante el cual se invocan los cierres. Los objetos registran a los oyentes de señales con el sistema de tipos, especificando un mapeo entre una señal dada y un cierre dado. Tras la emisión de una señal registrada, se invoca el cierre de esa señal. En GTK, todos los eventos de GUI nativos (como el movimiento del mouse y las acciones del teclado) pueden generar señales de GObject para que los oyentes puedan actuar.
Implementación de clases
Cada clase de GObject se implementa mediante al menos dos estructuras: la estructura de clases y la estructura de instancias .
- La estructura de clases
- La estructura de la clase corresponde a la vtable de una clase C ++. Debe comenzar con la estructura de clases de la superclase. Después de eso, contendrá un conjunto de punteros de función, uno para cada método virtual de la clase. Las variables específicas de la clase se pueden utilizar para emular a los miembros de la clase.
- La estructura de la instancia
- La estructura de instancia, que existirá en una copia por instancia de objeto, debe comenzar con la estructura de instancia de la superclase (esto asegura que todas las instancias comiencen con un puntero a la estructura de clase, ya que todos los tipos fundamentales instanciables comparten esta propiedad). Después de los datos que pertenecen a la superclase, la estructura puede contener cualquier variable específica de instancia, correspondiente a las variables miembro de C ++.
Definir una clase en el marco de GObject es complejo y requiere grandes cantidades de código repetitivo , como definiciones manuales de macros de conversión de tipos y encantamientos de registro de tipos oscuros. Además, dado que una estructura C no puede tener modificadores de acceso como "público", "protegido" o "privado", se deben utilizar soluciones para proporcionar encapsulación . Un enfoque consiste en incluir un puntero a los datos privados, llamados convencionalmente _priv
, en la estructura de la instancia. La estructura privada se puede declarar en el archivo de encabezado público, pero se puede definir solo en el archivo de implementación, con el efecto de que los datos privados son opacos para los usuarios, pero transparentes para el implementador. Si la estructura privada está registrada con GType, el sistema de objetos la asignará automáticamente. De hecho, ni siquiera es necesario incluir el _priv
puntero, si uno está dispuesto a usar el encantamiento G_TYPE_INSTANCE_GET_PRIVATE
cada vez que se necesitan datos privados.
Para abordar algunas de estas complejidades, existen varios lenguajes de nivel superior que de fuente a fuente compila en GObject en C. El lenguaje de programación Vala usa una sintaxis de estilo C # y está preprocesado en código C vanilla . GObject Builder, o GOB2 , ofrece una sintaxis de plantilla que recuerda a Java .
Uso
La combinación de C y GObject se utiliza en muchos proyectos de software libre exitosos , como el escritorio GNOME , el kit de herramientas GTK y el programa de manipulación de imágenes GIMP .
Aunque muchas aplicaciones de GObject están escritas completamente en C, el sistema de GObject se correlaciona bien con los sistemas de objetos nativos de muchos otros lenguajes, como C ++ , Java , Ruby , Python , Common Lisp y .NET / Mono . Como resultado, generalmente es relativamente sencillo crear enlaces de lenguaje para bibliotecas bien escritas que usan el marco GObject.
Escribir código GObject en C en primer lugar, sin embargo, es relativamente detallado. La biblioteca requiere mucho tiempo para aprender, y los programadores con experiencia en lenguajes orientados a objetos de alto nivel a menudo encuentran algo tedioso trabajar con GObject en C. Por ejemplo, crear una subclase (incluso solo una subclase de GObject
) puede requerir escribir y / o copiar grandes cantidades de código repetitivo . [6] Sin embargo, usar Vala , un lenguaje que está diseñado principalmente para trabajar con GObject y que se convierte a C, probablemente hará que trabajar con GObject o escribir bibliotecas basadas en GObject sea más agradable.
Aunque no son realmente objetos de primera clase (no hay metatipos reales en GType), los metaobjetos como clases e interfaces son creados por aplicaciones GObject en tiempo de ejecución y brindan un buen soporte para la introspección . Las capacidades introspectivas son utilizadas por enlaces de idioma y aplicaciones de diseño de interfaz de usuario como Glade para permitir hacer cosas como cargar una biblioteca compartida que proporciona una clase GObject, generalmente algún tipo de widget , en el caso de Glade, y luego obtener una lista de todas las propiedades. de la clase, completo con información de tipo y cadenas de documentación.
Comparaciones con otros sistemas de objetos
Dado que GObject proporciona un sistema de objetos en su mayoría completo para C [ cita requerida ] , puede verse como una alternativa a los lenguajes derivados de C como C ++ y Objective-C . (Aunque ambos también ofrecen muchas otras características más allá de sus respectivos sistemas de objetos). Una diferencia fácilmente observable entre C ++ y GObject es que GObject (como Java) no admite herencia múltiple . [7]
El uso de GObject de GLib 'función g_malloc () la asignación de memoria s hará que el programa para salir sin condiciones tras el agotamiento de la memoria, a diferencia de la biblioteca de C malloc (), C ++' s nuevos , y otros asignadores de memoria común que permiten a un programa para hacer frente a, o incluso recuperar plenamente de situaciones de falta de memoria sin simplemente fallar. [8] Esto tiende a ir en contra de la inclusión de GObject en el software donde la resiliencia frente a la memoria limitada es importante, o donde comúnmente se manipulan muchos o muy grandes objetos. El g_try_new () se puede usar cuando es más probable que falle una asignación de memoria (para un objeto grande, por ejemplo), pero esto no puede garantizar que la asignación no fallará en ninguna otra parte del código. [9]
Otra diferencia importante es que mientras C ++ y Objective-C son lenguajes separados, GObject es estrictamente una biblioteca y, como tal, no introduce ninguna nueva sintaxis o inteligencia de compilación. Por ejemplo, al escribir código C basado en GObject, con frecuencia es necesario realizar una conversión ascendente explícita . [ cita requerida ] Por lo tanto, "C con GObject", considerado como un lenguaje separado de C simple, es un superconjunto estricto de C simple, como Objective C, pero a diferencia de C ++.
En plataformas donde no existe una ABI estándar que funcione en todos los compiladores de C ++ (lo que no suele ser el caso, ya que generalmente se siguen la ABI de Itanium o la ABI de Microsoft), una biblioteca compilada con un compilador de C ++ no siempre puede llamar a un biblioteca compilada con una diferente. [ cita requerida ] Si se requiere tal compatibilidad, los métodos de C ++ deben exportarse como funciones simples de C, frustrando en parte el propósito del sistema de objetos de C ++. [ cita requerida ] El problema ocurre en parte porque diferentes compiladores de C ++ usan diferentes tipos de alteración de nombres para asegurar la unicidad de todos los símbolos exportados. (Esto es necesario porque, por ejemplo, dos clases diferentes pueden tener funciones miembro con nombres idénticos, un nombre de función puede estar sobrecargado varias veces o pueden aparecer funciones con nombres idénticos en diferentes espacios de nombres , pero en el código de objeto estas superposiciones no están permitidas). [ [cita requerida ] Por el contrario, dado que C no admite ninguna forma de sobrecarga o espacio de nombres, los autores de las bibliotecas de C normalmente utilizarán prefijos explícitos para garantizar la unicidad global de sus nombres exportados. [ cita requerida ] Por lo tanto, a pesar de estar orientada a objetos, una biblioteca basada en GObject escrita en C siempre usará los mismos nombres de símbolos externos independientemente del compilador que se use.
Quizás la diferencia más profunda es el énfasis de GObject en las señales (llamadas eventos en otros idiomas). [ cita requerida ] Este énfasis se deriva del hecho de que GObject fue diseñado específicamente para satisfacer las necesidades de un conjunto de herramientas GUI. Si bien existen bibliotecas de señales para la mayoría de los lenguajes orientados a objetos, en el caso de GObject está integrado en el sistema de objetos. Debido a esto, una aplicación GObject típica tenderá a usar señales en un grado mucho mayor que una aplicación que no sea GObject, lo que hará que los componentes de GObject sean mucho más encapsulados y reutilizables que los que usan C ++ o Java simple. [ cita requerida ] [ según quién? ] Si usa glibmm / gtkmm , los envoltorios oficiales de C ++ para Glib / GTK respectivamente, el proyecto hermano libsigc ++ permite un uso fácil de las señales subyacentes de GObject usando C ++ estándar. Por supuesto, hay otras implementaciones de señales disponibles en casi todas las plataformas, aunque a veces se necesita una biblioteca adicional, como Boost.Signals2 para C ++.
Ver también
- Vala : un lenguaje de programación basado en GObject con sintaxis C # . Una fuente a otra compilador de C .
- Genie - analizador sintáctico alternativo para el compilador Vala estilo Python
Referencias
- ↑ Withnall, Philip (11 de febrero de 2021). "simplista 2,66,7" . GNOME ftp-release (lista de correo) . Consultado el 12 de febrero de 2021 .
- ^ "Introspección, Resumen" . Desarrollador Gnome, Pautas de programación: procedimientos específicos . Consultado el 9 de agosto de 2020 .
- ^ "Manual de referencia de GObject" .
- ^ "Manual de referencia de GObject - Estable" .
- ^ "glib-mkenums, GObject Reference Manual" .
- ^ "Cómo definir e implementar un nuevo GObject" . gnome.org . Consultado el 27 de julio de 2013 .
- ^ "c ++ - ¿Por qué se creó el sistema GObject?" . Desbordamiento de pila . Consultado el 16 de noviembre de 2019 .
- ^ "Asignación de memoria: Manual de referencia de GLib" . developer.gnome.org . Consultado el 16 de noviembre de 2019 .
- ^ "Asignación de memoria: Manual de referencia de GLib" . developer.gnome.org . Consultado el 17 de noviembre de 2019 .
enlaces externos
- El manual de referencia de GObject (y tutorial)
- Tutorial de GObject, agosto de 2004
- GOB2 - el constructor de GObject
- Página de inicio de Vala