Blame docs/reference/gobject/html/gtype-non-instantiable-classed.html

Packit ae235b
Packit ae235b
<html>
Packit ae235b
<head>
Packit ae235b
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
Packit ae235b
<title>Non-instantiable classed types: interfaces: GObject Reference Manual</title>
Packit ae235b
<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
Packit ae235b
<link rel="home" href="index.html" title="GObject Reference Manual">
Packit ae235b
<link rel="up" href="chapter-gtype.html" title="The GLib Dynamic Type System">
Packit ae235b
<link rel="prev" href="gtype-instantiable-classed.html" title="Instantiable classed types: objects">
Packit ae235b
<link rel="next" href="chapter-gobject.html" title="The GObject base class">
Packit ae235b
<meta name="generator" content="GTK-Doc V1.27 (XML mode)">
Packit ae235b
<link rel="stylesheet" href="style.css" type="text/css">
Packit ae235b
</head>
Packit ae235b
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
Packit ae235b
Packit ae235b
Packit ae235b
Home
Packit ae235b
Up
Packit ae235b
Prev
Packit ae235b
Next
Packit ae235b
Packit ae235b
Packit ae235b

Packit ae235b
Non-instantiable classed types: interfaces
Packit ae235b

Packit ae235b
          This section covers the theory behind interfaces. See
Packit ae235b
          How to define and implement interfaces for the recommended way to define an
Packit ae235b
          interface.
Packit ae235b
        

Packit ae235b

Packit ae235b
          GType's interfaces are very similar to Java's interfaces. They allow
Packit ae235b
          to describe a common API that several classes will adhere to.
Packit ae235b
          Imagine the play, pause and stop buttons on hi-fi equipment — those can
Packit ae235b
          be seen as a playback interface. Once you know what they do, you can
Packit ae235b
          control your CD player, MP3 player or anything that uses these symbols.
Packit ae235b
          To declare an interface you have to register a non-instantiable
Packit ae235b
          classed type which derives from 
Packit ae235b
          GTypeInterface. The following piece of code declares such an interface.
Packit ae235b

Packit ae235b
Packit ae235b
  
Packit ae235b
    
Packit ae235b
      
Packit ae235b
        
1
Packit ae235b
2
Packit ae235b
3
Packit ae235b
4
Packit ae235b
5
Packit ae235b
6
Packit ae235b
7
Packit ae235b
8
Packit ae235b
9
Packit ae235b
10
Packit ae235b
11
Packit ae235b
12
Packit ae235b
        
#define VIEWER_TYPE_EDITABLE viewer_editable_get_type ()
Packit ae235b
G_DECLARE_INTERFACE (ViewerEditable, viewer_editable, VIEWER, EDITABLE, GObject)
Packit ae235b
Packit ae235b
struct _ViewerEditableInterface {
Packit ae235b
  GTypeInterface parent;
Packit ae235b
Packit ae235b
  void (*save) (ViewerEditable  *self,
Packit ae235b
                GError         **error);
Packit ae235b
};
Packit ae235b
Packit ae235b
void viewer_editable_save (ViewerEditable  *self,
Packit ae235b
                           GError         **error);
Packit ae235b
      
Packit ae235b
    
Packit ae235b
  
Packit ae235b
Packit ae235b
Packit ae235b

Packit ae235b
          The interface function, viewer_editable_save is implemented
Packit ae235b
          in a pretty simple way:
Packit ae235b

Packit ae235b
Packit ae235b
  
Packit ae235b
    
Packit ae235b
      
Packit ae235b
        
1
Packit ae235b
2
Packit ae235b
3
Packit ae235b
4
Packit ae235b
5
Packit ae235b
6
Packit ae235b
7
Packit ae235b
8
Packit ae235b
9
Packit ae235b
10
Packit ae235b
11
Packit ae235b
12
Packit ae235b
13
Packit ae235b
        
void
Packit ae235b
viewer_editable_save (ViewerEditable  *self,
Packit ae235b
                      GError         **error)
Packit ae235b
{
Packit ae235b
  ViewerEditableinterface *iface;
Packit ae235b
Packit ae235b
  g_return_if_fail (VIEWER_IS_EDITABLE (self));
Packit ae235b
  g_return_if_fail (error == NULL || *error == NULL);
Packit ae235b
Packit ae235b
  iface = VIEWER_EDITABLE_GET_IFACE (self);
Packit ae235b
  g_return_if_fail (iface->save != NULL);
Packit ae235b
  iface->save (self);
Packit ae235b
}
Packit ae235b
      
Packit ae235b
    
Packit ae235b
  
Packit ae235b
Packit ae235b
Packit ae235b

Packit ae235b
         viewer_editable_get_type registers a type named ViewerEditable
Packit ae235b
         which inherits from G_TYPE_INTERFACE. All interfaces must
Packit ae235b
         be children of G_TYPE_INTERFACE in the  inheritance tree.
Packit ae235b
        

Packit ae235b

Packit ae235b
          An interface is defined by only one structure which must contain as first member
Packit ae235b
          a GTypeInterface structure. The interface structure is expected to
Packit ae235b
          contain the function pointers of the interface methods. It is good style to 
Packit ae235b
          define helper functions for each of the interface methods which simply call
Packit ae235b
          the interface's method directly: viewer_editable_save
Packit ae235b
          is one of these.
Packit ae235b
        

Packit ae235b

Packit ae235b
        If you have no special requirements you can use the
Packit ae235b
        G_IMPLEMENT_INTERFACE macro
Packit ae235b
        to implement an interface:
Packit ae235b

Packit ae235b
Packit ae235b
  
Packit ae235b
    
Packit ae235b
      
Packit ae235b
        
1
Packit ae235b
2
Packit ae235b
3
Packit ae235b
4
Packit ae235b
5
Packit ae235b
6
Packit ae235b
7
Packit ae235b
8
Packit ae235b
9
Packit ae235b
10
Packit ae235b
11
Packit ae235b
12
Packit ae235b
13
Packit ae235b
14
Packit ae235b
15
Packit ae235b
        
static void
Packit ae235b
viewer_file_save (ViewerEditable *self)
Packit ae235b
{
Packit ae235b
  g_print ("File implementation of editable interface save method.\n");
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
viewer_file_editable_interface_init (ViewerEditableInterface *iface)
Packit ae235b
{
Packit ae235b
  iface->save = viewer_file_save;
Packit ae235b
}
Packit ae235b
Packit ae235b
G_DEFINE_TYPE_WITH_CODE (ViewerFile, viewer_file, VIEWER_TYPE_FILE,
Packit ae235b
                         G_IMPLEMENT_INTERFACE (VIEWER_TYPE_EDITABLE,
Packit ae235b
                                                viewer_file_editable_interface_init))
Packit ae235b
      
Packit ae235b
    
Packit ae235b
  
Packit ae235b
Packit ae235b
Packit ae235b

Packit ae235b
        

Packit ae235b

Packit ae235b
          If your code does have special requirements, you must write a custom
Packit ae235b
          get_type function to register your GType which
Packit ae235b
          inherits from some GObject
Packit ae235b
          and which implements the interface ViewerEditable. For
Packit ae235b
          example, this code registers a new ViewerFile class which
Packit ae235b
          implements ViewerEditable:
Packit ae235b

Packit ae235b
Packit ae235b
  
Packit ae235b
    
Packit ae235b
      
Packit ae235b
        
1
Packit ae235b
2
Packit ae235b
3
Packit ae235b
4
Packit ae235b
5
Packit ae235b
6
Packit ae235b
7
Packit ae235b
8
Packit ae235b
9
Packit ae235b
10
Packit ae235b
11
Packit ae235b
12
Packit ae235b
13
Packit ae235b
14
Packit ae235b
15
Packit ae235b
16
Packit ae235b
17
Packit ae235b
18
Packit ae235b
19
Packit ae235b
20
Packit ae235b
21
Packit ae235b
22
Packit ae235b
23
Packit ae235b
24
Packit ae235b
25
Packit ae235b
26
Packit ae235b
27
Packit ae235b
28
Packit ae235b
29
Packit ae235b
30
Packit ae235b
31
Packit ae235b
32
Packit ae235b
33
Packit ae235b
34
Packit ae235b
35
Packit ae235b
36
Packit ae235b
37
Packit ae235b
38
Packit ae235b
39
Packit ae235b
40
Packit ae235b
41
Packit ae235b
42
Packit ae235b
43
Packit ae235b
44
Packit ae235b
45
Packit ae235b
        
static void
Packit ae235b
viewer_file_save (ViewerEditable *editable)
Packit ae235b
{
Packit ae235b
  g_print ("File implementation of editable interface save method.\n");
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
viewer_file_editable_interface_init (gpointer g_iface,
Packit ae235b
                                     gpointer iface_data)
Packit ae235b
{
Packit ae235b
  ViewerEditableInterface *iface = g_iface;
Packit ae235b
Packit ae235b
  iface->save = viewer_file_save;
Packit ae235b
}
Packit ae235b
Packit ae235b
GType 
Packit ae235b
viewer_file_get_type (void)
Packit ae235b
{
Packit ae235b
  static GType type = 0;
Packit ae235b
  if (type == 0) {
Packit ae235b
    const GTypeInfo info = {
Packit ae235b
      sizeof (ViewerFileClass),
Packit ae235b
      NULL,   /* base_init */
Packit ae235b
      NULL,   /* base_finalize */
Packit ae235b
      NULL,   /* class_init */
Packit ae235b
      NULL,   /* class_finalize */
Packit ae235b
      NULL,   /* class_data */
Packit ae235b
      sizeof (ViewerFile),
Packit ae235b
      0,      /* n_preallocs */
Packit ae235b
      NULL    /* instance_init */
Packit ae235b
    };
Packit ae235b
    const GInterfaceInfo editable_info = {
Packit ae235b
      (GInterfaceInitFunc) viewer_file_editable_interface_init,  /* interface_init */
Packit ae235b
      NULL,   /* interface_finalize */
Packit ae235b
      NULL    /* interface_data */
Packit ae235b
    };
Packit ae235b
    type = g_type_register_static (VIEWER_TYPE_FILE,
Packit ae235b
                                   "ViewerFile",
Packit ae235b
                                   &info, 0);
Packit ae235b
    g_type_add_interface_static (type,
Packit ae235b
                                 VIEWER_TYPE_EDITABLE,
Packit ae235b
                                 &editable_info);
Packit ae235b
  }
Packit ae235b
  return type;
Packit ae235b
}
Packit ae235b
      
Packit ae235b
    
Packit ae235b
  
Packit ae235b
Packit ae235b
Packit ae235b

Packit ae235b
        

Packit ae235b

Packit ae235b
          g_type_add_interface_static records in the type system that
Packit ae235b
          a given type implements also FooInterface 
Packit ae235b
          (foo_interface_get_type returns the type of 
Packit ae235b
          FooInterface).
Packit ae235b
                The GInterfaceInfo structure holds
Packit ae235b
          information about the implementation of the interface:
Packit ae235b

Packit ae235b
Packit ae235b
  
Packit ae235b
    
Packit ae235b
      
Packit ae235b
        
1
Packit ae235b
2
Packit ae235b
3
Packit ae235b
4
Packit ae235b
5
Packit ae235b
6
Packit ae235b
        
struct _GInterfaceInfo
Packit ae235b
{
Packit ae235b
  GInterfaceInitFunc     interface_init;
Packit ae235b
  GInterfaceFinalizeFunc interface_finalize;
Packit ae235b
  gpointer               interface_data;
Packit ae235b
};
Packit ae235b
      
Packit ae235b
    
Packit ae235b
  
Packit ae235b
Packit ae235b
Packit ae235b

Packit ae235b
        

Packit ae235b
Packit ae235b

Packit ae235b
Interface Initialization
Packit ae235b

Packit ae235b
            When an instantiable classed type which implements an interface
Packit ae235b
            (either directly or by inheriting an implementation from a superclass)
Packit ae235b
            is created for the first time, its class structure is initialized
Packit ae235b
            following the process described in the section called “Instantiable classed types: objects”.
Packit ae235b
            After that, the interface implementations associated with
Packit ae235b
            the type are initialized.
Packit ae235b
          

Packit ae235b

Packit ae235b
            First a memory buffer is allocated to hold the interface structure. The parent's
Packit ae235b
            interface structure is then copied over to the new interface structure (the parent
Packit ae235b
            interface is already initialized at that point). If there is no parent interface,
Packit ae235b
            the interface structure is initialized with zeros. The
Packit ae235b
            g_type and the
Packit ae235b
            g_instance_type fields are then
Packit ae235b
            initialized: g_type is set to the type of
Packit ae235b
            the most-derived interface and
Packit ae235b
            g_instance_type is set to the type of the
Packit ae235b
            most derived type which implements  this interface.
Packit ae235b
          

Packit ae235b

Packit ae235b
            The interface's base_init function is called,
Packit ae235b
            and then the interface's default_init is invoked.
Packit ae235b
            Finally if the type has registered an implementation of the interface,
Packit ae235b
            the implementation's interface_init
Packit ae235b
            function is invoked. If there are multiple implementations of an
Packit ae235b
            interface the base_init and
Packit ae235b
            interface_init functions will be invoked once
Packit ae235b
            for each implementation initialized.
Packit ae235b
          

Packit ae235b

Packit ae235b
            It is thus recommended to use a default_init function to
Packit ae235b
            initialize an interface. This function is called only once for the interface no
Packit ae235b
            matter how many implementations there are. The
Packit ae235b
            default_init function is declared by
Packit ae235b
            G_DEFINE_INTERFACE
Packit ae235b
            which can be used to define the interface:
Packit ae235b

Packit ae235b
Packit ae235b
  
Packit ae235b
    
Packit ae235b
      
Packit ae235b
        
1
Packit ae235b
2
Packit ae235b
3
Packit ae235b
4
Packit ae235b
5
Packit ae235b
6
Packit ae235b
7
Packit ae235b
        
G_DEFINE_INTERFACE (ViewerEditable, viewer_editable, G_TYPE_OBJECT)
Packit ae235b
Packit ae235b
static void
Packit ae235b
viewer_editable_default_init (ViewerEditableInterface *iface)
Packit ae235b
{
Packit ae235b
  /* add properties and signals here, will only be called once */
Packit ae235b
}
Packit ae235b
      
Packit ae235b
    
Packit ae235b
  
Packit ae235b
Packit ae235b
Packit ae235b

Packit ae235b
          

Packit ae235b

Packit ae235b
            Or you can do that yourself in a GType function for your interface:
Packit ae235b

Packit ae235b
Packit ae235b
  
Packit ae235b
    
Packit ae235b
      
Packit ae235b
        
1
Packit ae235b
2
Packit ae235b
3
Packit ae235b
4
Packit ae235b
5
Packit ae235b
6
Packit ae235b
7
Packit ae235b
8
Packit ae235b
9
Packit ae235b
10
Packit ae235b
11
Packit ae235b
12
Packit ae235b
13
Packit ae235b
14
Packit ae235b
15
Packit ae235b
16
Packit ae235b
17
Packit ae235b
18
Packit ae235b
19
Packit ae235b
20
Packit ae235b
21
Packit ae235b
22
Packit ae235b
23
Packit ae235b
24
Packit ae235b
25
Packit ae235b
26
Packit ae235b
27
Packit ae235b
28
Packit ae235b
29
Packit ae235b
        
GType
Packit ae235b
viewer_editable_get_type (void)
Packit ae235b
{
Packit ae235b
  static volatile gsize type_id = 0;
Packit ae235b
  if (g_once_init_enter (&type_id)) {
Packit ae235b
    const GTypeInfo info = {
Packit ae235b
      sizeof (ViewerEditableInterface),
Packit ae235b
      NULL,   /* base_init */
Packit ae235b
      NULL,   /* base_finalize */
Packit ae235b
      viewer_editable_default_init, /* class_init */
Packit ae235b
      NULL,   /* class_finalize */
Packit ae235b
      NULL,   /* class_data */
Packit ae235b
      0,      /* instance_size */
Packit ae235b
      0,      /* n_preallocs */
Packit ae235b
      NULL    /* instance_init */
Packit ae235b
    };
Packit ae235b
    GType type = g_type_register_static (G_TYPE_INTERFACE,
Packit ae235b
                                         "ViewerEditable",
Packit ae235b
                                         &info, 0);
Packit ae235b
    g_once_init_leave (&type_id, type);
Packit ae235b
  }
Packit ae235b
  return type_id;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
viewer_editable_default_init (ViewerEditableInterface *iface)
Packit ae235b
{
Packit ae235b
  /* add properties and signals here, will only called once */
Packit ae235b
}
Packit ae235b
      
Packit ae235b
    
Packit ae235b
  
Packit ae235b
Packit ae235b
Packit ae235b

Packit ae235b
          

Packit ae235b

Packit ae235b
          In summary, interface initialization uses the following functions:
Packit ae235b
        

Packit ae235b

Packit ae235b
          

Packit ae235b
Packit ae235b

Table 2. Interface Initialization

Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b
Invocation time
Packit ae235b
Function Invoked
Packit ae235b
Function's parameters
Packit ae235b
Remark
Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b
First call to g_type_create_instance
Packit ae235b
                    for any type implementing interface
Packit ae235b
                   
Packit ae235b
interface's base_init function
Packit ae235b
On interface's vtable
Packit ae235b
Rarely necessary to use this. Called once per instantiated classed type implementing the interface.
Packit ae235b
Packit ae235b
Packit ae235b
First call to g_type_create_instance
Packit ae235b
                    for each type implementing interface
Packit ae235b
                   
Packit ae235b
interface's default_init function
Packit ae235b
On interface's vtable
Packit ae235b
Register interface's signals, properties, etc. here. Will be called once.
Packit ae235b
Packit ae235b
Packit ae235b
First call to g_type_create_instance
Packit ae235b
                    for any type implementing interface
Packit ae235b
                   
Packit ae235b
implementation's interface_init function
Packit ae235b
On interface's vtable
Packit ae235b
Packit ae235b
                    Initialize interface implementation. Called for each class that that
Packit ae235b
                    implements the interface. Initialize the interface method pointers
Packit ae235b
                    in the interface structure to the implementing class's implementation.
Packit ae235b
                  
Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b


Packit ae235b
        

Packit ae235b
Packit ae235b
Packit ae235b

Packit ae235b
Interface Destruction
Packit ae235b

Packit ae235b
            When the last instance of an instantiable type which registered 
Packit ae235b
            an interface implementation is destroyed, the interface's 
Packit ae235b
            implementations associated to the type are destroyed.
Packit ae235b
          

Packit ae235b

Packit ae235b
            To destroy an interface implementation, GType first calls the 
Packit ae235b
            implementation's interface_finalize function 
Packit ae235b
            and then the interface's most-derived 
Packit ae235b
            base_finalize function.
Packit ae235b
          

Packit ae235b

Packit ae235b
            Again, it is important to understand, as in 
Packit ae235b
            the section called “Interface Initialization”,
Packit ae235b
              that both interface_finalize and base_finalize
Packit ae235b
              are invoked exactly once for the destruction of each implementation of an interface. Thus,
Packit ae235b
              if you were to use one of these functions, you would need to use a static integer variable
Packit ae235b
              which would hold the number of instances of implementations of an interface such that
Packit ae235b
              the interface's class is destroyed only once (when the integer variable reaches zero).
Packit ae235b
          

Packit ae235b

Packit ae235b
          The above process can be summarized as follows:
Packit ae235b
          

Packit ae235b
Packit ae235b

Table 3. Interface Finalization

Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b
Invocation time
Packit ae235b
Function Invoked
Packit ae235b
Function's parameters
Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b
Last call to g_type_free_instance for type
Packit ae235b
                    implementing interface
Packit ae235b
                   
Packit ae235b
interface's interface_finalize function
Packit ae235b
On interface's vtable
Packit ae235b
Packit ae235b
Packit ae235b
interface's base_finalize function
Packit ae235b
On interface's vtable
Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b


Packit ae235b
        

Packit ae235b
Packit ae235b
Packit ae235b
Packit ae235b

Generated by GTK-Doc V1.27
Packit ae235b
</body>
Packit ae235b
</html>