|
Server : Apache/2.2.17 (Unix) mod_ssl/2.2.17 OpenSSL/0.9.8e-fips-rhel5 DAV/2 PHP/5.2.17 System : Linux localhost 2.6.18-419.el5 #1 SMP Fri Feb 24 22:47:42 UTC 2017 x86_64 User : nobody ( 99) PHP Version : 5.2.17 Disable Function : NONE Directory : /usr/share/gtk-doc/html/gobject/ |
Upload File : |
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>How To define and implement a new GObject?</title>
<meta name="generator" content="DocBook XSL Stylesheets V1.69.1">
<link rel="start" href="index.html" title="GObject Reference Manual">
<link rel="up" href="pt02.html" title="Part IV. Tutorial">
<link rel="prev" href="pt02.html" title="Part IV. Tutorial">
<link rel="next" href="howto-gobject-code.html" title="Boilerplate code">
<meta name="generator" content="GTK-Doc V1.6 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="preface" href="pr01.html" title="Introduction">
<link rel="part" href="pt01.html" title="Part I. Concepts">
<link rel="chapter" href="ch01.html" title="Background">
<link rel="chapter" href="ch02.html" title="The Glib Dynamic Type System">
<link rel="chapter" href="chapter-gobject.html" title="The GObject base class">
<link rel="chapter" href="chapter-signal.html" title="The GObject messaging system">
<link rel="reference" href="rn01.html" title="API Reference">
<link rel="reference" href="rn02.html" title="Tools Reference">
<link rel="part" href="pt02.html" title="Part IV. Tutorial">
<link rel="chapter" href="howto-gobject.html" title="How To define and implement a new GObject?">
<link rel="chapter" href="howto-interface.html" title="How To define and implement Interfaces?">
<link rel="chapter" href="howto-signals.html" title="Howto create and use signals">
<link rel="part" href="pt03.html" title="Part V. Related Tools">
<link rel="chapter" href="tools-gob.html" title="GObject builder">
<link rel="chapter" href="tools-ginspector.html" title="Graphical inspection of Gobjects">
<link rel="chapter" href="tools-refdb.html" title="Debugging reference count problems">
<link rel="chapter" href="tools-gtkdoc.html" title="Writing API docs">
<link rel="index" href="ix01.html" title="Index">
<link rel="index" href="ix02.html" title="Index of deprecated symbols">
<link rel="index" href="ix03.html" title="Index of new symbols in 2.2">
<link rel="index" href="ix04.html" title="Index of new symbols in 2.4">
<link rel="index" href="ix05.html" title="Index of new symbols in 2.6">
<link rel="index" href="ix06.html" title="Index of new symbols in 2.8">
<link rel="index" href="ix07.html" title="Index of new symbols in 2.10">
<link rel="index" href="ix08.html" title="Index of new symbols in 2.12">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2"><tr valign="middle">
<td><a accesskey="p" href="pt02.html"><img src="left.png" width="24" height="24" border="0" alt="Prev"></a></td>
<td><a accesskey="u" href="pt02.html"><img src="up.png" width="24" height="24" border="0" alt="Up"></a></td>
<td><a accesskey="h" href="index.html"><img src="home.png" width="24" height="24" border="0" alt="Home"></a></td>
<th width="100%" align="center">GObject Reference Manual</th>
<td><a accesskey="n" href="howto-gobject-code.html"><img src="right.png" width="24" height="24" border="0" alt="Next"></a></td>
</tr></table>
<div class="chapter" lang="en">
<div class="titlepage"><div><div><h2 class="title">
<a name="howto-gobject"></a>How To define and implement a new GObject?</h2></div></div></div>
<div class="toc"><dl>
<dt><span class="sect1"><a href="howto-gobject.html#howto-gobject-header">Boilerplate header code</a></span></dt>
<dt><span class="sect1"><a href="howto-gobject-code.html">Boilerplate code</a></span></dt>
<dt><span class="sect1"><a href="howto-gobject-construction.html">Object Construction</a></span></dt>
<dt><span class="sect1"><a href="howto-gobject-destruction.html">Object Destruction</a></span></dt>
<dt><span class="sect1"><a href="howto-gobject-methods.html">Object methods</a></span></dt>
<dd><dl>
<dt><span class="sect2"><a href="howto-gobject-methods.html#id2805468">Non-virtual public methods</a></span></dt>
<dt><span class="sect2"><a href="howto-gobject-methods.html#id2805496">Virtual public methods</a></span></dt>
<dt><span class="sect2"><a href="howto-gobject-methods.html#id2805605">Virtual private Methods</a></span></dt>
</dl></dd>
<dt><span class="sect1"><a href="howto-gobject-chainup.html">Chaining up</a></span></dt>
</dl></div>
<p>
Clearly, this is one of the most common question people ask: they just want to crank code and
implement a subclass of a GObject. Sometimes because they want to create their own class hierarchy,
sometimes because they want to subclass one of GTK+'s widget. This chapter will focus on the
implementation of a subtype of GObject. The sample source code
associated to this section can be found in the documentation's source tarball, in the
<code class="filename">sample/gobject</code> directory:
</p>
<div class="itemizedlist"><ul type="disc">
<li><p><code class="filename">maman-bar.{h|c}</code>: this is the source for a object which derives from
<span class="type"><a href="gobject-The-Base-Object-Type.html#GObject">GObject</a></span> and which shows how to declare different types of methods on the object.
</p></li>
<li><p><code class="filename">maman-subbar.{h|c}</code>: this is the source for a object which derives from
<span class="type">MamanBar</span> and which shows how to override some of its parent's methods.
</p></li>
<li><p><code class="filename">maman-foo.{h|c}</code>: this is the source for an object which derives from
<span class="type"><a href="gobject-The-Base-Object-Type.html#GObject">GObject</a></span> and which declares a signal.
</p></li>
<li><p><code class="filename">test.c</code>: this is the main source which instantiates an instance of
type and exercises their API.
</p></li>
</ul></div>
<p>
</p>
<div class="sect1" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="howto-gobject-header"></a>Boilerplate header code</h2></div></div></div>
<p>
The first step before writing the code for your GObject is to write the type's header which contains
the needed type, function and macro definitions. Each of these elements is nothing but a convention
which is followed not only by GTK+'s code but also by most users of GObject. If you feel the need
not to obey the rules stated below, think about it twice:
</p>
<div class="itemizedlist"><ul type="disc">
<li><p>If your users are a bit accustomed to GTK+ code or any Glib code, they will
be a bit surprised and getting used to the conventions you decided upon will take time (money) and
will make them grumpy (not a good thing)
</p></li>
<li><p>
You must assess the fact that these conventions might have been designed by both smart
and experienced people: maybe they were at least partly right. Try to put your ego aside.
</p></li>
</ul></div>
<p>
</p>
<p>
Pick a name convention for your headers and source code and stick to it:
</p>
<div class="itemizedlist"><ul type="disc">
<li><p>
use a dash to separate the prefix from the typename: <code class="filename">maman-bar.h</code> and
<code class="filename">maman-bar.c</code> (this is the convention used by Nautilus and most Gnome libraries).
</p></li>
<li><p>
use an underscore to separate the prefix from the typename: <code class="filename">maman_bar.h</code> and
<code class="filename">maman_bar.c</code>.
</p></li>
<li><p>
Do not separate the prefix from the typename: <code class="filename">mamanbar.h</code> and
<code class="filename">mamanbar.c</code>. (this is the convention used by GTK+)
</p></li>
</ul></div>
<p>
I personally like the first solution better: it makes reading file names easier for those with poor
eyesight like me.
</p>
<p>
When you need some private (internal) declarations in several (sub)classes,
you can define them in a private header file which is often named by
appending the <span class="emphasis"><em>private</em></span> keyword to the public header name.
For example, one could use <code class="filename">maman-bar-private.h</code>,
<code class="filename">maman_bar_private.h</code> or <code class="filename">mamanbarprivate.h</code>.
Typically, such private header files are not installed.
</p>
<p>
The basic conventions for any header which exposes a GType are described in
<a href="gtype-conventions.html" title="Conventions">the section called “Conventions”</a>. Most GObject-based code also obeys onf of the following
conventions: pick one and stick to it.
</p>
<div class="itemizedlist"><ul type="disc">
<li>
<p>
If you want to declare a type named bar with prefix maman, name the type instance
<code class="function">MamanBar</code> and its class <code class="function">MamanBarClass</code>
(name is case-sensitive). It is customary to declare them with code similar to the
following:
</p>
<pre class="programlisting">
/*
* Copyright/Licensing information.
*/
#ifndef MAMAN_BAR_H
#define MAMAN_BAR_H
/*
* Potentially, include other headers on which this header depends.
*/
/*
* Type macros.
*/
typedef struct _MamanBar MamanBar;
typedef struct _MamanBarClass MamanBarClass;
struct _MamanBar {
GObject parent;
/* instance members */
};
struct _MamanBarClass {
GObjectClass parent;
/* class members */
};
/* used by MAMAN_BAR_TYPE */
GType maman_bar_get_type (void);
/*
* Method definitions.
*/
#endif
</pre>
<p>
</p>
</li>
<li>
<p>
Most GTK+ types declare their private fields in the public header with a /* private */ comment,
relying on their user's intelligence not to try to play with these fields. Fields not marked private
are considered public by default. The /* protected */ comment (same semantics as those of C++)
is also used, mainly in the GType library, in code written by Tim Janik.
</p>
<pre class="programlisting">
struct _MamanBar {
GObject parent;
/* private */
int hsize;
};
</pre>
<p>
</p>
</li>
<li>
<p>
All of Nautilus code and a lot of Gnome libraries use private indirection members, as described
by Herb Sutter in his Pimpl articles
(see <a href="http://www.gotw.ca/gotw/024.htm" target="_top">Compilation Firewalls</a>
and <a href="http://www.gotw.ca/gotw/028.htm" target="_top">The Fast Pimpl Idiom</a>
: he summarizes the different issues better than I will).
</p>
<pre class="programlisting">
typedef struct _MamanBarPrivate MamanBarPrivate;
struct _MamanBar {
GObject parent;
/* private */
MamanBarPrivate *priv;
};
</pre>
<p>
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<h3 class="title">Note</h3>
<p>Do not call this <code class="varname">private</code>, as that is a registered c++ keyword.</p>
</div>
<p>
The private structure is then defined in the .c file, instantiated in the object's
<code class="function">init</code> function and destroyed in the object's <code class="function">finalize</code> function.
</p>
<pre class="programlisting">
static void
maman_bar_finalize (GObject *object) {
MamanBar *self = MAMAN_BAR (object);
/* do stuff */
g_free (self->priv);
}
static void
maman_bar_init (GTypeInstance *instance, gpointer g_class) {
MamanBar *self = MAMAN_BAR (instance);
self->priv = g_new0 (MamanBarPrivate,1);
/* do stuff */
}
</pre>
<p>
</p>
</li>
<li>
<p>
A similar alternative, available since Glib version 2.4, is to define a private structure in the .c file,
declare it as a private structure in <code class="function">maman_bar_class_init</code> using
<code class="function"><a href="gobject-Type-Information.html#g-type-class-add-private">g_type_class_add_private</a></code>.
Instead of allocating memory in <code class="function">maman_bar_init</code> a pointer to the private memory area is
stored in the instance to allow convenient access to this structure.
A private structure will then be attached to each newly created object by the GObject system.
You dont need to free or allocate the private structure, only the objects or pointers that it may contain.
Another advantage of this to the previous version is that is lessens memory fragmentation,
as the public and private parts of the instance memory are allocated at once.
</p>
<pre class="programlisting">
typedef struct _MamanBarPrivate MamanBarPrivate;
struct _MamanBarPrivate {
int private_field;
};
static void
maman_bar_class_init (MamanBarClass *klass)
{
...
g_type_class_add_private (klass, sizeof (MamanBarPrivate));
...
}
static void
maman_bar_init (GTypeInstance *instance, gpointer g_class) {
MamanBar *self = MAMAN_BAR (instance);
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MAMAN_BAR_TYPE, MamanBarPrivate);
/* do stuff */
}
</pre>
<p>
</p>
</li>
</ul></div>
<p>
</p>
<p>
Finally, there are different header include conventions. Again, pick one and stick to it. I personally
use indifferently any of the two, depending on the codebase I work on: the rule is consistency.
</p>
<div class="itemizedlist"><ul type="disc">
<li><p>
Some people add at the top of their headers a number of #include directives to pull in
all the headers needed to compile client code. This allows client code to simply
#include "maman-bar.h".
</p></li>
<li><p>
Other do not #include anything and expect the client to #include themselves the headers
they need before including your header. This speeds up compilation because it minimizes the
amount of pre-processor work. This can be used in conjunction with the re-declaration of certain
unused types in the client code to minimize compile-time dependencies and thus speed up
compilation.
</p></li>
</ul></div>
<p>
</p>
</div>
</div>
</body>
</html>