stringtranslate.com

GObjeto

Así como la biblioteca GNU C sirve como contenedor para las llamadas al sistema del kernel de Linux , las bibliotecas incluidas en GLib (GObject, Glib , GModule, GThread y GIO ) sirven como contenedores adicionales para sus tareas específicas.

El sistema de objetos GLib , o GObject , es una biblioteca de software libre que proporciona un sistema de objetos portátil e interoperabilidad transparente entre lenguajes. GObject está diseñado para usarse tanto directamente en programas C para proporcionar APIs basadas en C orientadas a objetos como a través de enlaces a otros lenguajes para proporcionar interoperabilidad transparente entre lenguajes, por ejemplo, PyGObject .

Historia

GObject, que depende únicamente de GLib y libc , es una piedra angular de GNOME y se utiliza en GTK , Pango , ATK y la mayoría de las bibliotecas de GNOME de nivel superior, como GStreamer y otras aplicaciones. Antes de GTK+ 2.0, el código similar a GObject formaba parte del código base de GTK. (El nombre “GObject” aún no se utilizaba; la clase base común se llamaba GtkObject).

En el lanzamiento de GTK+ 2.0, el sistema de objetos se extrajo en una biblioteca independiente debido a su utilidad general. En el proceso, la mayoría de las partes no específicas de la GUI de la GtkObjectclase se trasladaron a GObject, la nueva clase base común. Habiendo existido como una biblioteca independiente desde el 11 de marzo de 2002 (la fecha de lanzamiento de GTK+ 2.0), la biblioteca GObject ahora es utilizada por muchos programas no GUI, como aplicaciones de línea de comandos y de servidor .

Relación con GLib

Aunque GObject tiene su propio conjunto de documentación [1] 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 este motivo, GObject utiliza los números de versión de GLib y normalmente se empaqueta junto con GLib (por ejemplo, Debian incluye a GObject en su libglib2.0familia de paquetes).

El sistema de tipos

En el nivel más básico del marco de 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 de unión facilite la vinculación de múltiples lenguajes. El sistema de tipos puede manejar cualquier estructura de clase heredada individualmente , además de tipos no clasificados como punteros opacos , cadenas y números enteros y de punto flotante de diversos tamaños .

El sistema de tipos sabe cómo copiar, asignar y destruir valores que pertenecen a cualquiera de los tipos registrados. Esto es trivial para tipos como los enteros, pero muchos objetos complejos se cuentan por referencia , mientras que algunos son complejos pero no se cuentan por referencia. Cuando el sistema de tipos "copia" un objeto con recuento de referencia, normalmente solo aumentará su recuento de referencia, mientras que cuando copia un objeto complejo que no se cuenta por referencia (como una cadena), normalmente creará una copia real mediante la asignación de 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 tipado dinámico en los que todos los valores nativos residen en dichos contenedores etiquetados con tipos .

Tipos fundamentales

Los tipos que no tienen ninguna clase asociada se denominan tipos 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 medio cree sus propios tipos fundamentales, existe la posibilidad y se ha explotado para crear jerarquías de clases personalizadas , es decir, jerarquías de clases que no se basan en la GObjectclase.

A partir de GLib 2.9.2, [2] los tipos fundamentales integrados no clasificados son:

Los tipos fundamentales integrados clasificados son:

Los tipos que pueden ser instanciados automáticamente por el sistema de tipos se denominan "instantables" . Una característica importante de estos tipos es que los primeros bytes de cualquier instancia siempre contienen un puntero a la estructura de clase (una forma de tabla virtual ) asociada al tipo de la instancia. Por esta razón, cualquier tipo instanciable debe ser clasificado. Por el contrario, cualquier tipo no clasificado (como entero o cadena ) debe ser no 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 incorporados de GObject se dividen aproximadamente en cuatro categorías:

Tipos enumerados y tipos “flags”
En general, cada tipo enumerado y cada tipo de campo de bits basado en números enteros (es decir, cada enumtipo) que se desee utilizar de alguna manera relacionada con el sistema de objetos (por ejemplo, como el tipo de una propiedad de objeto) debe registrarse en el sistema de tipos. Normalmente, el código de inicialización que se encarga de registrar estos tipos se genera mediante una herramienta automatizada denominada glib-mkenums[3] y se almacena en un archivo independiente.
Tipos en caja
Algunas estructuras de datos que son demasiado simples para convertirse en tipos de clase completos (con toda la sobrecarga que esto implica) pueden necesitar ser registradas en el sistema de tipos. Por ejemplo, podríamos tener una clase a la que queremos agregar una background-colorpropiedad, cuyos valores deberían ser instancias de una estructura que se parece a . Para evitar tener que crear una subclase de , podemos crear un tipo encajonado para representar esta estructura y proporcionar funciones para copiar y liberar. GObject se entrega con un puñado de tipos encajonados que envuelven tipos de datos GLib simples. Otro uso para los tipos encajonados es como una forma de envolver objetos externos 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 punteros opacos
A veces, para objetos que no necesitan copiarse, contarse por referencias ni liberarse, incluso un tipo en caja sería excesivo . Si bien estos 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 no se diga nada más 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 de la palabra en el ámbito de la orientación a objetos) derivadas directa o indirectamente de la clase raíz, GObject. También existen interfaces que, a diferencia de las interfaces clásicas de estilo Java , pueden contener métodos implementados. Por lo 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 un callback . Existe soporte para cierres escritos en C y C++, así como 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 por el cual se invocan los cierres. Los objetos registran a los oyentes de señales con el sistema de tipos, especificando una asignación 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 nativos de la GUI (como el movimiento del mouse y las acciones del teclado) pueden generar señales GObject para que los oyentes puedan actuar en consecuencia.

Implementación de clase

Cada clase GObject se implementa mediante al menos dos estructuras: la estructura de clase y la estructura de instancia .

La estructura de clases
La estructura de clase corresponde a la tabla virtual de una clase C++. Debe comenzar con la estructura de clase de la superclase. A continuación, contendrá un conjunto de punteros de función, uno para cada método virtual de la clase. Se pueden utilizar variables específicas de la clase para emular a los miembros de la clase.
La estructura de la instancia
La estructura de instancia, que existirá en una copia por cada instancia de objeto, debe comenzar con la estructura de instancia de la superclase (esto garantiza que todas las instancias comiencen con un puntero a la estructura de clase, ya que todos los tipos instanciables fundamentales comparten esta propiedad). Después de los datos que pertenecen a la superclase, la estructura puede contener cualquier variable específica de la 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 poco claros. Además, dado que una estructura de C no puede tener modificadores de acceso como “público”, “protegido” o “privado”, se deben utilizar soluciones alternativas para proporcionar encapsulación . Un enfoque es incluir un puntero a los datos privados (llamados convencionalmente _priv) en la estructura de instancia. La estructura privada se puede declarar en el archivo de encabezado público, pero 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 se registra con GType, el sistema de objetos la asignará automáticamente. De hecho, ni siquiera es necesario incluir el _privpuntero, si uno está dispuesto a usar el encantamiento G_TYPE_INSTANCE_GET_PRIVATEcada vez que se necesitan los datos privados.

Para abordar algunas de estas complejidades, existen varios lenguajes de alto nivel que compilan de fuente a fuente en GObject en C. El lenguaje de programación Vala utiliza una sintaxis de estilo C# y se preprocesa en código C básico . GObject Builder, o GOB2, ofrece una sintaxis de plantilla que recuerda a Java .

Introspección de objetos

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 GObject están escritas completamente en C, el sistema GObject se integra bien con los sistemas de objetos nativos de muchos otros lenguajes, como C++ , Java , Ruby , Python , Common Lisp y .NET / Mono . Como resultado, suele ser relativamente sencillo crear enlaces de lenguaje para bibliotecas bien escritas que utilizan el marco GObject.

Sin embargo, escribir código GObject en C es relativamente complejo. La biblioteca requiere mucho tiempo para aprenderse 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 . [5] Sin embargo, es probable que usar Vala , un lenguaje que está diseñado principalmente para trabajar con GObject y que convierte a C, haga 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 las clases y las interfaces son creados por las aplicaciones GObject en tiempo de ejecución y proporcionan un buen soporte para la introspección . Las capacidades introspectivas son utilizadas por las vinculaciones de lenguaje y las aplicaciones de diseño de interfaz de usuario como Glade para permitir hacer cosas como cargar una biblioteca compartida que proporciona una clase GObject (normalmente algún tipo de widget , en el caso de Glade) y luego obtener una lista de todas las propiedades de la clase, completa con información de tipo y cadenas de documentación.

Comparaciones con otros sistemas de objetos

Dado que GObject proporciona un sistema de objetos casi 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 la herencia múltiple . [6]

El uso de la función de asignación de memoria g_malloc() de GLib por parte de GObject hará que el programa salga incondicionalmente cuando se agote la memoria, a diferencia de malloc () de la biblioteca C, new de C++ y otros asignadores de memoria comunes que permiten que un programa se enfrente o incluso se recupere por completo de situaciones de falta de memoria sin simplemente bloquearse. [7] Esto tiende a funcionar en contra de la inclusión de GObject en software donde la resiliencia frente a una memoria limitada es importante, o donde se manejan comúnmente muchos objetos o muy grandes. g_try_new() se puede utilizar 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 falle en otra parte del código. [8]

Otra diferencia importante es que, mientras que C++ y Objective-C son lenguajes separados, GObject es estrictamente una biblioteca y, como tal, no introduce ninguna sintaxis nueva ni 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”, también llamado “C con sabor simplista”, considerado como un lenguaje separado de C simple, es un superconjunto estricto de C simple, como Objective C, pero diferente de C++.

En plataformas donde no hay una ABI estándar que funcione en todos los compiladores de C++ (lo que no suele ser el caso, ya que normalmente se sigue la ABI de Itanium o la ABI de Microsoft), una biblioteca compilada con un compilador de C++ no siempre puede llamar a una biblioteca compilada con uno diferente. [ cita requerida ] Si se requiere dicha compatibilidad, los métodos de C++ deben exportarse como funciones de C simples, lo que frustra en parte el propósito del sistema de objetos de C++. [ cita requerida ] El problema ocurre en parte porque los diferentes compiladores de C++ usan diferentes tipos de manipulación de nombres para garantizar 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 sobrecargarse varias veces o funciones con nombres idénticos pueden aparecer en diferentes espacios de nombres , pero en el código 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 bibliotecas de C normalmente usará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.

Tal vez la diferencia más profunda es el énfasis de GObject en las señales (llamadas eventos en otros lenguajes). [ 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 una medida mucho mayor que una aplicación que no sea GObject, lo que hace que los componentes GObject sean mucho más encapsulados y reutilizables que los que usan C++ o Java simples. [ cita requerida ] [ ¿según quién? ] Si se 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 GObject subyacentes 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++.

Véase también

Referencias

  1. ^ "Manual de referencia de GObject".
  2. ^ "Manual de referencia de GObject - Estable".
  3. ^ "glib-mkenums, Manual de referencia de GObject".
  4. ^ "Introspección, resumen". Gnome Developer, Pautas de programación: procedimientos específicos . Consultado el 9 de agosto de 2020 .
  5. ^ "Cómo definir e implementar un nuevo GObject". gnome.org . Consultado el 27 de julio de 2013 .
  6. ^ "c++ - ¿Por qué se creó el sistema GObject?". Desbordamiento de pila . Consultado el 16 de noviembre de 2019 .
  7. ^ "Asignación de memoria: Manual de referencia de GLib". developer.gnome.org . Consultado el 16 de noviembre de 2019 .
  8. ^ "Asignación de memoria: Manual de referencia de GLib". developer.gnome.org . Consultado el 17 de noviembre de 2019 .

Enlaces externos