Import Upstream version 2.72.4

This commit is contained in:
evinadmin 2023-07-04 11:23:22 +02:00
commit 4ef3ff9793
2003 changed files with 1332420 additions and 0 deletions

View file

@ -0,0 +1,579 @@
<refentry id="glib-genmarshal" lang="en">
<refentryinfo>
<title>glib-genmarshal</title>
<productname>GObject</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Emmanuele</firstname>
<surname>Bassi</surname>
</author>
<author>
<contrib>Original developer</contrib>
<firstname>Tim</firstname>
<surname>Janik</surname>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>glib-genmarshal</refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class="manual">User Commands</refmiscinfo>
</refmeta>
<refnamediv>
<refname>glib-genmarshal</refname>
<refpurpose>C code marshaller generation utility for GLib closures</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>glib-genmarshal</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="opt" rep="repeat">FILE</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1><title>Description</title>
<para><command>glib-genmarshal</command> is a small utility that generates C code
marshallers for callback functions of the GClosure mechanism in the GObject
sublibrary of GLib. The marshaller functions have a standard signature,
they get passed in the invoking closure, an array of value structures holding
the callback function parameters and a value structure for the return value
of the callback. The marshaller is then responsible to call the respective C
code function of the closure with all the parameters on the stack and to
collect its return value.
</para>
<para><command>glib-genmarshal</command> takes a list of marshallers to generate as
input. The marshaller list is either read from files passed as additional arguments
on the command line; or from standard input, by using <literal>-</literal> as the
input file.
</para>
<refsect2><title>Marshaller list format</title>
<para>
The marshaller lists are processed line by line, a line can contain a
comment in the form of
<informalexample><programlisting>
# this is a comment
</programlisting></informalexample>
or a marshaller specification of the form
<programlisting>
<replaceable>RTYPE</replaceable>:<replaceable>PTYPE</replaceable>
<replaceable>RTYPE</replaceable>:<replaceable>PTYPE</replaceable>,<replaceable>PTYPE</replaceable>
<replaceable>RTYPE</replaceable>:<replaceable>PTYPE</replaceable>,<replaceable>PTYPE</replaceable>,<replaceable>PTYPE</replaceable>
</programlisting>
</para>
<para>
The <replaceable>RTYPE</replaceable> part specifies the callback's return
type and the <replaceable>PTYPE</replaceable>s right to the colon specify
the callback's parameter list, except for the first and the last arguments
which are always pointers.
</para>
</refsect2>
<refsect2><title>Parameter types</title>
<para>
Currently, the following types are supported:
<variablelist>
<varlistentry>
<term><replaceable>VOID</replaceable></term>
<listitem><para>
indicates no return type, or no extra parameters.
If <replaceable>VOID</replaceable> is used as the parameter list, no
additional parameters may be present.
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>BOOLEAN</replaceable></term>
<listitem><para>
for boolean types (gboolean)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>CHAR</replaceable></term>
<listitem><para>
for signed char types (gchar)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>UCHAR</replaceable></term>
<listitem><para>
for unsigned char types (guchar)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>INT</replaceable></term>
<listitem><para>
for signed integer types (gint)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>UINT</replaceable></term>
<listitem><para>
for unsigned integer types (guint)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>LONG</replaceable></term>
<listitem><para>
for signed long integer types (glong)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>ULONG</replaceable></term>
<listitem><para>
for unsigned long integer types (gulong)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>INT64</replaceable></term>
<listitem><para>
for signed 64bit integer types (gint64)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>UINT64</replaceable></term>
<listitem><para>
for unsigned 64bit integer types (guint64)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>ENUM</replaceable></term>
<listitem><para>
for enumeration types (gint)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>FLAGS</replaceable></term>
<listitem><para>
for flag enumeration types (guint)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>FLOAT</replaceable></term>
<listitem><para>
for single-precision float types (gfloat)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>DOUBLE</replaceable></term>
<listitem><para>
for double-precision float types (gdouble)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>STRING</replaceable></term>
<listitem><para>
for string types (gchar*)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>BOXED</replaceable></term>
<listitem><para>
for boxed (anonymous but reference counted) types (GBoxed*)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>PARAM</replaceable></term>
<listitem><para>
for GParamSpec or derived types (GParamSpec*)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>POINTER</replaceable></term>
<listitem><para>
for anonymous pointer types (gpointer)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>OBJECT</replaceable></term>
<listitem><para>
for GObject or derived types (GObject*)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>VARIANT</replaceable></term>
<listitem><para>
for GVariant types (GVariant*)
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>NONE</replaceable></term>
<listitem><para>
deprecated alias for <replaceable>VOID</replaceable>
</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>BOOL</replaceable></term>
<listitem><para>
deprecated alias for <replaceable>BOOLEAN</replaceable>
</para></listitem>
</varlistentry>
</variablelist>
</para>
</refsect2>
</refsect1>
<refsect1><title>Options</title>
<variablelist>
<varlistentry>
<term><option>--header</option></term>
<listitem><para>
Generate header file contents of the marshallers. This option is mutually
exclusive with the <option>--body</option> option.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--body</option></term>
<listitem><para>
Generate C code file contents of the marshallers. This option is mutually
exclusive with the <option>--header</option> option.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--prefix=<replaceable>PREFIX</replaceable></option></term>
<listitem><para>
Specify marshaller prefix. The default prefix is <literal>`g_cclosure_user_marshal'</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--skip-source</option></term>
<listitem><para>
Skip source location remarks in generated comments.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--stdinc</option></term>
<listitem><para>
Use the standard marshallers of the GObject library, and include
<filename>glib-object.h</filename> in generated header files. This
option is mutually exclusive with the <option>--nostdinc</option>
option.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--nostdinc</option></term>
<listitem><para>
Do not use the standard marshallers of the GObject library, and skip
<filename>glib-object.h</filename> include directive in generated header files.
This option is mutually exclusive with the <option>--stdinc</option> option.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--internal</option></term>
<listitem><para>
Mark generated functions as internal, using <literal>G_GNUC_INTERNAL</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--valist-marshallers</option></term>
<listitem><para>
Generate valist marshallers, for use with <function>g_signal_set_va_marshaller()</function>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option>, <option>--version</option></term>
<listitem><para>
Print version information.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--g-fatal-warnings</option></term>
<listitem><para>
Make warnings fatal, that is, exit immediately once a warning occurs.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-h</option>, <option>--help</option></term>
<listitem><para>
Print brief help and exit.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option>, <option>--version</option></term>
<listitem><para>
Print version and exit.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--output=FILE</option></term>
<listitem><para>
Write output to <replaceable>FILE</replaceable> instead of the standard output.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--prototypes</option></term>
<listitem><para>
Generate function prototypes before the function definition in the C source
file, in order to avoid a <literal>missing-prototypes</literal> compiler
warning. This option is only useful when using the <option>--body</option>
option.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--pragma-once</option></term>
<listitem><para>
Use the <literal>once</literal> pragma instead of an old style header guard
when generating the C header file. This option is only useful when using the
<option>--header</option> option.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--include-header=<replaceable>HEADER</replaceable></option></term>
<listitem><para>
Adds a <literal>#include</literal> directive for the given file in the C
source file. This option is only useful when using the <option>--body</option>
option.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-D <replaceable>SYMBOL[=VALUE]</replaceable></option></term>
<listitem><para>
Adds a <literal>#define</literal> C pre-processor directive for
<replaceable>SYMBOL</replaceable> and its given <replaceable>VALUE</replaceable>,
or "1" if the value is unset. You can use this option multiple times; if you do,
all the symbols will be defined in the same order given on the command line, before
the symbols undefined using the <option>-U</option> option. This option is only
useful when using the <option>--body</option> option.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-U <replaceable>SYMBOL</replaceable></option></term>
<listitem><para>
Adds a <literal>#undef</literal> C pre-processor directive to undefine the
given <replaceable>SYMBOL</replaceable>. You can use this option multiple times;
if you do, all the symbols will be undefined in the same order given on the
command line, after the symbols defined using the <option>-D</option> option.
This option is only useful when using the <option>--body</option> option.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--quiet</option></term>
<listitem><para>
Minimizes the output of <command>glib-genmarshal</command>, by printing only
warnings and errors. This option is mutually exclusive with the
<option>--verbose</option> option.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--verbose</option></term>
<listitem><para>
Increases the verbosity of <command>glib-genmarshal</command>, by printing
debugging information. This option is mutually exclusive with the
<option>--quiet</option> option.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1><title>Using <command>glib-genmarshal</command> with Meson</title>
<para>
Meson supports generating closure marshallers using <command>glib-genmarshal</command>
out of the box in its "gnome" module.
</para>
<para>
In your <filename>meson.build</filename> file you will typically call the
<literal>gnome.genmarshal()</literal> method with the source list of marshallers
to generate:
</para>
<informalexample><programlisting>
gnome = import('gnome')
marshal_files = gnome.genmarshal('marshal',
sources: 'marshal.list',
internal: true,
)
</programlisting></informalexample>
<para>
The <literal>marshal_files</literal> variable will contain an array of two elements
in the following order:
</para>
<itemizedlist>
<listitem><para>a build target for the source file</para></listitem>
<listitem><para>a build target for the header file</para></listitem>
</itemizedlist>
<para>
You should use the returned objects to provide a dependency on every other
build target that references the source or header file; for instance, if you
are using the source to build a library:
</para>
<informalexample><programlisting>
mainlib = library('project',
sources: project_sources + marshal_files,
...
)
</programlisting></informalexample>
<para>
Additionally, if you are including the generated header file inside a build
target that depends on the library you just built, you must ensure that the
internal dependency includes the generated header as a required source file:
</para>
<informalexample><programlisting>
mainlib_dep = declare_dependency(sources: marshal_files[1], link_with: mainlib)
</programlisting></informalexample>
<para>
You should not include the generated source file as well, otherwise it will
be built separately for every target that depends on it, causing build
failures. To know more about why all this is required, please refer to the
<ulink url="https://mesonbuild.com/FAQ.html#how-do-i-tell-meson-that-my-sources-use-generated-headers">
corresponding Meson FAQ entry</ulink>.
</para>
<para>
For more information on how to use the method, see the
<ulink url="https://mesonbuild.com/Gnome-module.html#gnomegenmarshal">Meson
documentation for <literal>gnome.genmarshal()</literal></ulink>.
</para>
</refsect1>
<refsect1><title>Using <command>glib-genmarshal</command> with Autotools</title>
<para>
In order to use <command>glib-genmarshal</command> in your project when using
Autotools as the build system, you will first need to modify your
<filename>configure.ac</filename> file to ensure you find the appropriate
command using <command>pkg-config</command>, similarly as to how you discover
the compiler and linker flags for GLib.
</para>
<informalexample><programlisting>
PKG_PROG_PKG_CONFIG([0.28])
PKG_CHECK_VAR([GLIB_GENMARSHAL], [glib-2.0], [glib_genmarshal])
</programlisting></informalexample>
<para>
In your <filename>Makefile.am</filename> file you will typically need very
simple rules to generate the C files needed for the build.
</para>
<informalexample><programlisting>
marshal.h: marshal.list
$(AM_V_GEN)$(GLIB_GENMARSHAL) \
--header \
--output=$@ \
$&lt;
marshal.c: marshal.list marshal.h
$(AM_V_GEN)$(GLIB_GENMARSHAL) \
--include-header=marshal.h \
--body \
--output=$@ \
$&lt;
BUILT_SOURCES += marshal.h marshal.c
CLEANFILES += marshal.h marshal.c
EXTRA_DIST += marshal.list
</programlisting></informalexample>
<para>
In the example above, the first rule generates the header file and depends on
a <filename>marshal.list</filename> file in order to regenerate the result in
case the marshallers list is updated. The second rule generates the source file
for the same <filename>marshal.list</filename>, and includes the file generated
by the header rule.
</para>
</refsect1>
<refsect1><title>Example</title>
<para>
To generate marshallers for the following callback functions:
</para>
<informalexample><programlisting>
void foo (gpointer data1,
gpointer data2);
void bar (gpointer data1,
gint param1,
gpointer data2);
gfloat baz (gpointer data1,
gboolean param1,
guchar param2,
gpointer data2);
</programlisting></informalexample>
<para>
The <filename>marshaller.list</filename> file has to look like this:
</para>
<programlisting>
VOID:VOID
VOID:INT
FLOAT:BOOLEAN,UCHAR
</programlisting>
<para>
and you call glib-genmarshal like this:
</para>
<programlisting>
glib-genmarshal --header marshaller.list > marshaller.h
glib-genmarshal --body marshaller.list > marshaller.c
</programlisting>
<para>
The generated marshallers have the arguments encoded in their function name.
For this particular list, they are
</para>
<programlisting>
g_cclosure_user_marshal_VOID__VOID(...),
g_cclosure_user_marshal_VOID__INT(...),
g_cclosure_user_marshal_FLOAT__BOOLEAN_UCHAR(...).
</programlisting>
<para>
They can be used directly for GClosures or be passed in as the
GSignalCMarshaller c_marshaller; argument upon creation of signals:
</para>
<informalexample><programlisting>
GClosure *cc_foo, *cc_bar, *cc_baz;
cc_foo = g_cclosure_new (NULL, foo, NULL);
g_closure_set_marshal (cc_foo, g_cclosure_user_marshal_VOID__VOID);
cc_bar = g_cclosure_new (NULL, bar, NULL);
g_closure_set_marshal (cc_bar, g_cclosure_user_marshal_VOID__INT);
cc_baz = g_cclosure_new (NULL, baz, NULL);
g_closure_set_marshal (cc_baz, g_cclosure_user_marshal_FLOAT__BOOLEAN_UCHAR);
</programlisting></informalexample>
</refsect1>
<refsect1><title>See also</title>
<para>
<citerefentry>
<refentrytitle>glib-mkenums</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>
</para>
</refsect1>
</refentry>

View file

@ -0,0 +1,653 @@
<refentry id="glib-mkenums" lang="en">
<refentryinfo>
<title>gdbus</title>
<productname>GObject</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Owen</firstname>
<surname>Taylor</surname>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>glib-mkenums</refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class="manual">User Commands</refmiscinfo>
</refmeta>
<refnamediv>
<refname>glib-mkenums</refname>
<refpurpose>C language enum description generation utility</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>glib-mkenums</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="opt" rep="repeat">FILE</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1><title>Description</title>
<para><command>glib-mkenums</command> is a small utility that parses C code to
extract enum definitions and produces enum descriptions based on text templates
specified by the user. Typically, you can use this tool to generate enumeration
types for the GType type system, for GObject properties and signal marshalling;
additionally, you can use it to generate enumeration values of GSettings schemas.
</para>
<para><command>glib-mkenums</command> takes a list of valid C code files as
input. The options specified control the text that generated, substituting various
keywords enclosed in <literal>@</literal> characters in the templates.
</para>
<refsect2><title>Production text substitutions</title>
<para>
Certain keywords enclosed in <literal>@</literal> characters will be substituted in the
emitted text. For the substitution examples of the keywords below,
the following example enum definition is assumed:
</para>
<informalexample><programlisting>
typedef enum
{
PREFIX_THE_XVALUE = 1 &lt;&lt; 3,
PREFIX_ANOTHER_VALUE = 1 &lt;&lt; 4
} PrefixTheXEnum;
</programlisting></informalexample>
<variablelist>
<varlistentry>
<term><literal>@EnumName@</literal>></term>
<listitem><para>
The name of the enum currently being processed, enum names are assumed to be
properly namespaced and to use mixed capitalization to separate
words (e.g. <literal>PrefixTheXEnum</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>@enum_name@</literal></term>
<listitem><para>
The enum name with words lowercase and word-separated by underscores
(e.g. <literal>prefix_the_xenum</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>@ENUMNAME@</literal></term>
<listitem><para>
The enum name with words uppercase and word-separated by underscores
(e.g. <literal>PREFIX_THE_XENUM</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>@ENUMSHORT@</literal></term>
<listitem><para>
The enum name with words uppercase and word-separated by underscores,
prefix stripped (e.g. <literal>THE_XENUM</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>@ENUMPREFIX@</literal></term>
<listitem><para>
The prefix of the enum name (e.g. <literal>PREFIX</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>@VALUENAME@</literal></term>
<listitem><para>
The enum value name currently being processed with words uppercase and
word-separated by underscores,
this is the assumed literal notation of enum values in the C sources
(e.g. <literal>PREFIX_THE_XVALUE</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>@valuenick@</literal></term>
<listitem><para>
A nick name for the enum value currently being processed, this is usually
generated by stripping common prefix words of all the enum values of the
current enum, the words are lowercase and underscores are substituted by a
minus (e.g. <literal>the-xvalue</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>@valuenum@</literal></term>
<listitem><para>
The integer value for the enum value currently being processed. If the
evaluation fails then <command>glib-mkenums</command> will exit with an
error status, but this only happens if <literal>@valuenum@</literal>
appears in your value production template. (Since: 2.26)
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>@type@</literal></term>
<listitem><para>
This is substituted either by "enum" or "flags", depending on whether the
enum value definitions contained bit-shift operators or not (e.g. <literal>flags</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>@Type@</literal></term>
<listitem><para>
The same as <literal>@type@</literal> with the first letter capitalized (e.g. <literal>Flags</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>@TYPE@</literal></term>
<listitem><para>
The same as <literal>@type@</literal> with all letters uppercased (e.g. <literal>FLAGS</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>@filename@</literal></term>
<listitem><para>
The full path of the input file currently being processed (e.g. <literal>/build/environment/project/src/foo.h</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>@basename@</literal></term>
<listitem><para>
The base name of the input file currently being processed (e.g. <literal>foo.h</literal>).
Typically you want to use <literal>@basename@</literal> in place of <literal>@filename@</literal>
in your templates, to improve the reproducibility of the build. (Since: 2.22)
</para></listitem>
</varlistentry>
</variablelist>
</refsect2>
<refsect2><title>Trigraph extensions</title>
<para>
Some C comments are treated specially in the parsed enum definitions,
such comments start out with the trigraph sequence <literal>/*&lt;</literal>
and end with the trigraph sequence <literal>&gt;*/</literal>.
</para>
<para>The following options can be specified per enum definition:</para>
<variablelist>
<varlistentry>
<term><literal>skip</literal></term>
<listitem><para>
Indicates this enum definition should be skipped.
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>flags</literal></term>
<listitem><para>
Indicates this enum should be treated as a flags definition.
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>underscore_name</literal></term>
<listitem><para>
Specifies the word separation used in the <function>*_get_type()</function>
function. For instance, <literal>/*&lt; underscore_name=gnome_vfs_uri_hide_options &gt;*/</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>since</literal></term>
<listitem><para>
Specifies the version tag that will be used to substitute the <literal>@enumsince@</literal>
keyword in the template, useful when documenting methods generated from the enums
(e.g. <literal>Since: @enumsince@</literal>). (Since: 2.66)
</para></listitem>
</varlistentry>
</variablelist>
<para>The following options can be specified per value definition:</para>
<variablelist>
<varlistentry>
<term><literal>skip</literal></term>
<listitem><para>
Indicates the value should be skipped.
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>nick</literal></term>
<listitem><para>
Specifies the otherwise auto-generated nickname.
</para></listitem>
</varlistentry>
</variablelist>
<para>Examples:</para>
<informalexample><programlisting>
typedef enum /*&lt; skip &gt;*/
{
PREFIX_FOO
} PrefixThisEnumWillBeSkipped;
typedef enum /*&lt; flags,prefix=PREFIX,since=1.0 &gt;*/
{
PREFIX_THE_ZEROTH_VALUE, /*&lt; skip &gt;*/
PREFIX_THE_FIRST_VALUE,
PREFIX_THE_SECOND_VALUE,
PREFIX_THE_THIRD_VALUE, /*&lt; nick=the-last-value &gt;*/
} PrefixTheFlagsEnum;
</programlisting></informalexample>
</refsect2>
</refsect1>
<refsect1><title>Options</title>
<variablelist>
<varlistentry>
<term><option>--fhead</option> <replaceable>TEXT</replaceable></term>
<listitem><para>
Emits <replaceable>TEXT</replaceable> prior to processing input files.
</para>
<para>
You can specify this option multiple times, and the <replaceable>TEXT</replaceable>
will be concatenated.
</para>
<para>
When used along with a template file, <replaceable>TEXT</replaceable>
will be prepended to the template's <literal>file-header</literal> section.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--fprod</option> <replaceable>TEXT</replaceable></term>
<listitem><para>
Emits <replaceable>TEXT</replaceable> every time a new input file
is being processed.
</para>
<para>
You can specify this option multiple times, and the <replaceable>TEXT</replaceable>
will be concatenated.
</para>
<para>
When used along with a template file, <replaceable>TEXT</replaceable>
will be appended to the template's <literal>file-production</literal> section.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--ftail</option> <replaceable>TEXT</replaceable></term>
<listitem><para>
Emits <replaceable>TEXT</replaceable> after all input files have been
processed.
</para>
<para>
You can specify this option multiple times, and the <replaceable>TEXT</replaceable>
will be concatenated.
</para>
<para>
When used along with a template file, <replaceable>TEXT</replaceable>
will be appended to the template's <literal>file-tail</literal> section.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--eprod</option> <replaceable>TEXT</replaceable></term>
<listitem><para>
Emits <replaceable>TEXT</replaceable> every time an enum is encountered
in the input files.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--vhead</option> <replaceable>TEXT</replaceable></term>
<listitem><para>
Emits <replaceable>TEXT</replaceable> before iterating over the set of
values of an enum.
</para>
<para>
You can specify this option multiple times, and the <replaceable>TEXT</replaceable>
will be concatenated.
</para>
<para>
When used along with a template file, <replaceable>TEXT</replaceable>
will be prepended to the template's <literal>value-header</literal> section.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--vprod</option> <replaceable>TEXT</replaceable></term>
<listitem><para>
Emits <replaceable>TEXT</replaceable> for every value of an enum.
</para>
<para>
You can specify this option multiple times, and the <replaceable>TEXT</replaceable>
will be concatenated.
</para>
<para>
When used along with a template file, <replaceable>TEXT</replaceable>
will be appended to the template's <literal>value-production</literal> section.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--vtail</option> <replaceable>TEXT</replaceable></term>
<listitem><para>
Emits <replaceable>TEXT</replaceable> after iterating over all values
of an enum.
</para>
<para>
You can specify this option multiple times, and the <replaceable>TEXT</replaceable>
will be concatenated.
</para>
<para>
When used along with a template file, <replaceable>TEXT</replaceable>
will be appended to the template's <literal>value-tail</literal> section.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--comments</option> <replaceable>TEXT</replaceable></term>
<listitem><para>
Template for auto-generated comments, the default (for C code generations) is
<literal>"/* @comment@ */"</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--template</option> <replaceable>FILE</replaceable></term>
<listitem><para>
Read templates from the given file. The templates are enclosed in
specially-formatted C comments:
</para>
<informalexample><programlisting>
/*** BEGIN section ***/
/*** END section ***/
</programlisting></informalexample>
<para>
<replaceable>section</replaceable> may be <literal>file-header</literal>,
<literal>file-production</literal>, <literal>file-tail</literal>,
<literal>enumeration-production</literal>, <literal>value-header</literal>,
<literal>value-production</literal>, <literal>value-tail</literal> or
<literal>comment</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--identifier-prefix</option> <replaceable>PREFIX</replaceable></term>
<listitem><para>
Indicates what portion of the enum name should be interpreted as the
prefix (eg, the "<literal>Gtk</literal>" in
"<literal>GtkDirectionType</literal>"). Normally this will be figured
out automatically, but you may need to override the default if your
namespace is capitalized oddly.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--symbol-prefix</option> <replaceable>PREFIX</replaceable></term>
<listitem><para>
Indicates what prefix should be used to correspond to the identifier
prefix in related C function names (eg, the "<literal>gtk</literal>"
in "<literal>gtk_direction_type_get_type</literal>". Equivalently,
this is the lowercase version of the prefix component of the enum
value names (eg, the "<literal>GTK</literal>" in
"<literal>GTK_DIR_UP</literal>". The default value is the identifier
prefix, converted to lowercase.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--help</option></term>
<listitem><para>
Print brief help and exit.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--version</option></term>
<listitem><para>
Print version and exit.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--output=FILE</option></term>
<listitem><para>
Write output to FILE instead of stdout.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>@RSPFILE</option></term>
<listitem><para>
When passed as the sole argument, read and parse the actual arguments from
<literal>RSPFILE</literal>. Useful on systems with a low command-line length
limit. For example, Windows has a limit of 8191 characters.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1><title>Using templates</title>
<para>
Instead of passing the various sections of the generated file to the command
line of <command>glib-mkenums</command>, it's strongly recommended to use a
template file, especially for generating C sources.
</para>
<para>
A C header template file will typically look like this:
</para>
<informalexample><programlisting>
/*** BEGIN file-header ***/
#pragma once
/* Include the main project header */
#include "project.h"
G_BEGIN_DECLS
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@basename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GType @enum_name@_get_type (void) G_GNUC_CONST;
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
/*** END value-header ***/
/*** BEGIN file-tail ***/
G_END_DECLS
/*** END file-tail ***/
</programlisting></informalexample>
<para>
A C source template file will typically look like this:
</para>
<informalexample><programlisting>
/*** BEGIN file-header ***/
#include "config.h"
#include "enum-types.h"
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@basename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GType
@enum_name@_get_type (void)
{
static gsize static_g_@type@_type_id;
if (g_once_init_enter (&amp;static_g_@type@_type_id))
{
static const G@Type@Value values[] = {
/*** END value-header ***/
/*** BEGIN value-production ***/
{ @VALUENAME@, "@VALUENAME@", "@valuenick@" },
/*** END value-production ***/
/*** BEGIN value-tail ***/
{ 0, NULL, NULL }
};
GType g_@type@_type_id =
g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
g_once_init_leave (&amp;static_g_@type@_type_id, g_@type@_type_id);
}
return static_g_@type@_type_id;
}
/*** END value-tail ***/
</programlisting></informalexample>
<para>
Template files are easier to modify and update, and can be used
to generate various types of outputs using the same command line
or tools during the build.
</para>
</refsect1>
<refsect1><title>Using glib-mkenums with Meson</title>
<para>
Meson supports generating enumeration types using <command>glib-mkenums</command>
out of the box in its "gnome" module.
</para>
<para>
In your <filename>meson.build</filename> file you will typically call the
<literal>gnome.mkenums_simple()</literal> method to generate idiomatic enumeration
types from a list of headers to inspect:
</para>
<informalexample><programlisting>
project_headers = [
'project-foo.h',
'project-bar.h',
'project-baz.h',
]
gnome = import('gnome')
enum_files = gnome.mkenums_simple('enum-types',
sources: project_headers,
)
</programlisting></informalexample>
<para>
The <literal>enum_files</literal> variable will contain an array of two elements
in the following order:
</para>
<itemizedlist>
<listitem><para>a build target for the source file</para></listitem>
<listitem><para>a build target for the header file</para></listitem>
</itemizedlist>
<para>
You should use the returned objects to provide a dependency on every other
build target that references the source or header file; for instance, if you
are using the source to build a library:
</para>
<informalexample><programlisting>
mainlib = library('project',
sources: project_sources + enum_files,
...
)
</programlisting></informalexample>
<para>
Additionally, if you are including the generated header file inside a build
target that depends on the library you just built, you must ensure that the
internal dependency includes the generated header as a required source file:
</para>
<informalexample><programlisting>
mainlib_dep = declare_dependency(sources: enum_files[1], link_with: mainlib)
</programlisting></informalexample>
<para>
You should not include the generated source file as well, otherwise it will
be built separately for every target that depends on it, causing build
failures. To know more about why all this is required, please refer to the
<ulink url="https://mesonbuild.com/FAQ.html#how-do-i-tell-meson-that-my-sources-use-generated-headers">
corresponding Meson FAQ entry</ulink>.
</para>
<para>
If you are generating C header and source files that require special
templates, you can use <literal>gnome.mkenums()</literal> to provide those
headers, for instance:
</para>
<informalexample><programlisting>
enum_files = gnome.mkenums('enum-types',
sources: project_headers,
h_template: 'enum-types.h.in',
c_template: 'enum-types.c.in',
install_header: true,
)
</programlisting></informalexample>
<para>
For more information, see the <ulink url="https://mesonbuild.com/Gnome-module.html#gnomegenmarshal">Meson
documentation for <literal>gnome.mkenums()</literal></ulink>.
</para>
</refsect1>
<refsect1><title>Using glib-mkenums with Autotools</title>
<para>
In order to use <command>glib-mkenums</command> in your project when using
Autotools as the build system, you will first need to modify your
<filename>configure.ac</filename> file to ensure you find the appropriate
command using <command>pkg-config</command>, similarly as to how you discover
the compiler and linker flags for GLib.
</para>
<informalexample><programlisting>
PKG_PROG_PKG_CONFIG([0.28])
PKG_CHECK_VAR([GLIB_MKENUMS], [glib-2.0], [glib_mkenums])
</programlisting></informalexample>
<para>
In your <filename>Makefile.am</filename> file you will typically use rules
like these:
</para>
<informalexample><programlisting>
# A list of headers to inspect
project_headers = \
project-foo.h \
project-bar.h \
project-baz.h
enum-types.h: $(project_headers) enum-types.h.in
$(AM_V_GEN)$(GLIB_MKENUMS) \
--template=enum-types.h.in \
--output=$@ \
$(project_headers)
enum-types.c: $(project_headers) enum-types.c.in enum-types.h
$(AM_V_GEN)$(GLIB_MKENUMS) \
--template=enum-types.c.in \
--output=$@ \
$(project_headers)
# Build the enum types files before every other target
BUILT_SOURCES += enum-types.h enum-types.c
CLEANFILES += enum-types.h enum-types.c
EXTRA_DIST += enum-types.h.in enum-types.c.in
</programlisting></informalexample>
<para>
In the example above, we have a variable called <literal>project_headers</literal>
where we reference all header files we want to inspect for generating enumeration
GTypes. In the <filename>enum-types.h</filename> rule we use <command>glib-mkenums</command>
with a template called <filename>enum-types.h.in</filename> in order to generate the
header file; similarly, in the <filename>enum-types.c</filename> rule we use a
template called <filename>enum-types.c.in</filename>.
</para>
</refsect1>
<refsect1><title>See also</title>
<para>
<citerefentry>
<refentrytitle>glib-genmarshal</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>
</para>
</refsect1>
</refentry>

View file

@ -0,0 +1,224 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC '-//OASIS//DTD DocBook XML V4.5//EN'
'http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd' [
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
<!ENTITY version SYSTEM "version.xml">
]>
<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
<bookinfo>
<title>GObject Reference Manual</title>
<releaseinfo>
for GObject &version;
The latest version of this documentation can be found on-line at
<ulink role="online-location" url="https://developer.gnome.org/gobject/unstable/">https://developer.gnome.org/gobject/unstable/</ulink>.
</releaseinfo>
</bookinfo>
<preface>
<title>Introduction</title>
<para>
Most modern programming languages come with their own native object
systems and additional fundamental algorithmic language constructs.
Just as GLib serves as an implementation of such fundamental
types and algorithms (linked lists, hash tables and so forth), the
GLib Object System provides the required implementations of a
flexible, extensible, and intentionally easy to map (into other
languages) object-oriented framework for C.
The substantial elements that are provided can be summarized as:
<itemizedlist>
<listitem><para>
A generic type system to register arbitrary single-inherited
flat and deep derived types as well as interfaces for
structured types.
It takes care of creation, initialization and memory management
of the assorted object and class structures, maintains
parent/child relationships and deals with dynamic implementations
of such types. That is, their type specific implementations are
relocatable/unloadable during runtime.
</para></listitem>
<listitem><para>
A collection of fundamental type implementations, such as integers,
doubles, enums and structured types, to name a few.
</para></listitem>
<listitem><para>
A sample fundamental type implementation to base object hierarchies
upon - the GObject fundamental type.
</para></listitem>
<listitem><para>
A signal system that allows very flexible user customization of
virtual/overridable object methods and can serve as a powerful
notification mechanism.
</para></listitem>
<listitem><para>
An extensible parameter/value system, supporting all the provided
fundamental types that can be used to generically handle object
properties or otherwise parameterized types.
</para></listitem>
</itemizedlist>
</para>
</preface>
<part label="I">
<title>Concepts</title>
<xi:include href="tut_intro.xml" />
<xi:include href="tut_gtype.xml" />
<xi:include href="tut_gobject.xml" />
<xi:include href="tut_gsignal.xml" />
</part>
<reference label="II">
<title>API Reference</title>
<xi:include href="xml/gtype.xml" />
<xi:include href="xml/gtypeplugin.xml" />
<xi:include href="xml/gtypemodule.xml" />
<xi:include href="xml/objects.xml" />
<xi:include href="xml/enumerations_flags.xml" />
<xi:include href="xml/gboxed.xml" />
<xi:include href="xml/generic_values.xml" />
<xi:include href="xml/param_value_types.xml" />
<xi:include href="xml/gparamspec.xml" />
<xi:include href="xml/value_collection.xml" />
<xi:include href="xml/signals.xml" />
<xi:include href="xml/gsignalgroup.xml" />
<xi:include href="xml/gclosure.xml" />
<xi:include href="xml/value_arrays.xml" />
<xi:include href="xml/gbinding.xml" />
<xi:include href="xml/gbindinggroup.xml" />
</reference>
<reference label="III">
<title>Tools Reference</title>
<xi:include href="glib-mkenums.xml" />
<xi:include href="glib-genmarshal.xml" />
<xi:include href="gobject-query.xml" />
</reference>
<xi:include href="tut_howto.xml" />
<xi:include href="tut_tools.xml" />
<index id="api-index-full">
<title>Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-deprecated" role="deprecated">
<title>Index of deprecated symbols</title>
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-2" role="2.2">
<title>Index of new symbols in 2.2</title>
<xi:include href="xml/api-index-2.2.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-4" role="2.4">
<title>Index of new symbols in 2.4</title>
<xi:include href="xml/api-index-2.4.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-6" role="2.6">
<title>Index of new symbols in 2.6</title>
<xi:include href="xml/api-index-2.6.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-8" role="2.8">
<title>Index of new symbols in 2.8</title>
<xi:include href="xml/api-index-2.8.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-10" role="2.10">
<title>Index of new symbols in 2.10</title>
<xi:include href="xml/api-index-2.10.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-12" role="2.12">
<title>Index of new symbols in 2.12</title>
<xi:include href="xml/api-index-2.12.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-14" role="2.14">
<title>Index of new symbols in 2.14</title>
<xi:include href="xml/api-index-2.14.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-18" role="2.18">
<title>Index of new symbols in 2.18</title>
<xi:include href="xml/api-index-2.18.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-22" role="2.22">
<title>Index of new symbols in 2.22</title>
<xi:include href="xml/api-index-2.22.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-24" role="2.24">
<title>Index of new symbols in 2.24</title>
<xi:include href="xml/api-index-2.24.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-26" role="2.26">
<title>Index of new symbols in 2.26</title>
<xi:include href="xml/api-index-2.26.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-28" role="2.28">
<title>Index of new symbols in 2.28</title>
<xi:include href="xml/api-index-2.28.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-30" role="2.30">
<title>Index of new symbols in 2.30</title>
<xi:include href="xml/api-index-2.30.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-32" role="2.32">
<title>Index of new symbols in 2.32</title>
<xi:include href="xml/api-index-2.32.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-34" role="2.34">
<title>Index of new symbols in 2.34</title>
<xi:include href="xml/api-index-2.34.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-36" role="2.36">
<title>Index of new symbols in 2.36</title>
<xi:include href="xml/api-index-2.36.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-38" role="2.38">
<title>Index of new symbols in 2.38</title>
<xi:include href="xml/api-index-2.38.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-40" role="2.40">
<title>Index of new symbols in 2.40</title>
<xi:include href="xml/api-index-2.40.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-42" role="2.42">
<title>Index of new symbols in 2.42</title>
<xi:include href="xml/api-index-2.42.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-44" role="2.44">
<title>Index of new symbols in 2.44</title>
<xi:include href="xml/api-index-2.44.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-46" role="2.46">
<title>Index of new symbols in 2.46</title>
<xi:include href="xml/api-index-2.46.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-54" role="2.54">
<title>Index of new symbols in 2.54</title>
<xi:include href="xml/api-index-2.54.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-56" role="2.56">
<title>Index of new symbols in 2.56</title>
<xi:include href="xml/api-index-2.56.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-62" role="2.62">
<title>Index of new symbols in 2.62</title>
<xi:include href="xml/api-index-2.62.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-66" role="2.66">
<title>Index of new symbols in 2.66</title>
<xi:include href="xml/api-index-2.66.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-68" role="2.68">
<title>Index of new symbols in 2.68</title>
<xi:include href="xml/api-index-2.68.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-70" role="2.70">
<title>Index of new symbols in 2.70</title>
<xi:include href="xml/api-index-2.70.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-72" role="2.72">
<title>Index of new symbols in 2.72</title>
<xi:include href="xml/api-index-2.72.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>

View file

@ -0,0 +1,123 @@
<refentry id="gobject-query" lang="en">
<refentryinfo>
<title>gobject-query</title>
<productname>GObject</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Tim</firstname>
<surname>Janik</surname>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>gobject-query</refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class="manual">User Commands</refmiscinfo>
</refmeta>
<refnamediv>
<refname>gobject-query</refname>
<refpurpose>display a tree of types</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>gobject-query</command>
<arg choice="plain">froots</arg>
<arg choice="opt" rep="repeat">OPTION</arg>
</cmdsynopsis>
<cmdsynopsis>
<command>gobject-query</command>
<arg choice="plain">tree</arg>
<arg choice="opt" rep="repeat">OPTION</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1><title>Description</title>
<para>
<command>gobject-query</command> is a small utility that draws a tree of
types.
</para>
<para>
<command>gobject-query</command> takes a mandatory argument that specifies
whether it should iterate over the fundamental types or print a type tree.
</para>
</refsect1>
<refsect1><title>Commands</title>
<variablelist>
<varlistentry>
<term><option>froots</option></term>
<listitem><para>
iterate over fundamental roots
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>tree</option></term>
<listitem><para>
print type tree
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1><title>Options</title>
<variablelist>
<varlistentry>
<term><option>-r</option> <replaceable>TYPE</replaceable></term>
<listitem><para>
specify the root type
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-n</option></term>
<listitem><para>
don't descend type tree
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-b</option> <replaceable>STRING</replaceable></term>
<listitem><para>
specify indent string
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-i</option> <replaceable>STRING</replaceable></term>
<listitem><para>
specify incremental indent string
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-s</option> <replaceable>NUMBER</replaceable></term>
<listitem><para>
specify line spacing
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-h</option>, <option>--help</option></term>
<listitem><para>
Print brief help and exit.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option>, <option>--version</option></term>
<listitem><para>
Print version and exit.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
</refentry>

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,68 @@
if get_option('gtk_doc')
subdir('xml')
ignore_headers = [
'tests',
'gatomicarray.h',
'gobject_probes.h',
'gobject_trace.h',
'gtype-private.h',
'glib-enumtypes.h',
]
docpath = join_paths(glib_datadir, 'gtk-doc', 'html')
version_conf = configuration_data()
version_conf.set('GLIB_VERSION', meson.project_version())
configure_file(
input: 'version.xml.in',
output: 'version.xml',
configuration: version_conf
)
gtkdocincl = include_directories('.')
gnome.gtkdoc('gobject',
main_xml : 'gobject-docs.xml',
namespace : 'g',
mode : 'none',
dependencies : [libgobject_dep, libglib_dep],
include_directories : [gtkdocincl],
src_dir : 'gobject',
scan_args : gtkdoc_common_scan_args + [
'--rebuild-types',
'--ignore-headers=' + ' '.join(ignore_headers),
],
content_files : [
'glib-mkenums.xml',
'glib-genmarshal.xml',
'gobject-query.xml',
'tut_gobject.xml',
'tut_gsignal.xml',
'tut_gtype.xml',
'tut_howto.xml',
'tut_intro.xml',
'tut_tools.xml'
],
html_assets : [
'images/glue.png'
],
fixxref_args: [
'--html-dir=' + docpath,
'--extra-dir=' + join_paths('gobject', '..', 'glib', 'html'),
],
install: true,
check: true,
)
endif
if get_option('man')
manpages = ['glib-mkenums', 'glib-genmarshal', 'gobject-query']
foreach page : manpages
custom_target(page + '-man',
input: page + '.xml',
output: page + '.1',
command: xsltproc_command,
install: true,
install_dir: man1_dir)
endforeach
endif

View file

@ -0,0 +1,728 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<chapter id="chapter-gobject">
<title>The GObject base class</title>
<para>
The previous chapter discussed the details of GLib's Dynamic Type System.
The GObject library also contains an implementation for a base fundamental
type named <link linkend="GObject"><type>GObject</type></link>.
</para>
<para>
<link linkend="GObject"><type>GObject</type></link> is a fundamental classed instantiatable type. It implements:
<itemizedlist>
<listitem><para>Memory management with reference counting</para></listitem>
<listitem><para>Construction/Destruction of instances</para></listitem>
<listitem><para>Generic per-object properties with set/get function pairs</para></listitem>
<listitem><para>Easy use of signals</para></listitem>
</itemizedlist>
All the GNOME libraries which use the GLib type system (like GTK+ and GStreamer)
inherit from <link linkend="GObject"><type>GObject</type></link> which is why it is important to understand
the details of how it works.
</para>
<sect1 id="gobject-instantiation">
<title>Object instantiation</title>
<para>
The <function><link linkend="g-object-new">g_object_new</link></function>
family of functions can be used to instantiate any GType which inherits
from the GObject base type. All these functions make sure the class and
instance structures have been correctly initialized by GLib's type system
and then invoke at one point or another the constructor class method
which is used to:
<itemizedlist>
<listitem><para>
Allocate and clear memory through <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>,
</para></listitem>
<listitem><para>
Initialize the object's instance with the construction properties.
</para></listitem>
</itemizedlist>
Although one can expect all class and instance members (except the fields
pointing to the parents) to be set to zero, some consider it good practice
to explicitly set them.
</para>
<para>
Once all construction operations have been completed and constructor
properties set, the constructed class method is called.
</para>
<para>
Objects which inherit from GObject are allowed to override this
constructed class method.
The example below shows how <type>ViewerFile</type> overrides the parent's construction process:
<informalexample><programlisting>
#define VIEWER_TYPE_FILE viewer_file_get_type ()
G_DECLARE_FINAL_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject)
struct _ViewerFile
{
GObject parent_instance;
/* instance members */
gchar *filename;
guint zoom_level;
};
/* will create viewer_file_get_type and set viewer_file_parent_class */
G_DEFINE_TYPE (ViewerFile, viewer_file, G_TYPE_OBJECT)
static void
viewer_file_constructed (GObject *obj)
{
/* update the object state depending on constructor properties */
/* Always chain up to the parent constructed function to complete object
* initialisation. */
G_OBJECT_CLASS (viewer_file_parent_class)-&gt;constructed (obj);
}
static void
viewer_file_finalize (GObject *obj)
{
ViewerFile *self = VIEWER_FILE (obj);
g_free (self->filename);
/* Always chain up to the parent finalize function to complete object
* destruction. */
G_OBJECT_CLASS (viewer_file_parent_class)-&gt;finalize (obj);
}
static void
viewer_file_class_init (ViewerFileClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class-&gt;constructed = viewer_file_constructed;
object_class-&gt;finalize = viewer_file_finalize;
}
static void
viewer_file_init (ViewerFile *self)
{
/* initialize the object */
}
</programlisting></informalexample>
If the user instantiates an object <type>ViewerFile</type> with:
<informalexample><programlisting>
ViewerFile *file = g_object_new (VIEWER_TYPE_FILE, NULL);
</programlisting></informalexample>
If this is the first instantiation of such an object, the
<function>viewer_file_class_init</function> function will be invoked
after any <function>viewer_file_base_class_init</function> function.
This will make sure the class structure of this new object is
correctly initialized. Here, <function>viewer_file_class_init</function>
is expected to override the object's class methods and setup the
class' own methods. In the example above, the <literal>constructed</literal>
method is the only overridden method: it is set to
<function>viewer_file_constructed</function>.
</para>
<para>
Once <function><link linkend="g-object-new">g_object_new</link></function> has obtained a reference to an initialized
class structure, it invokes its constructor method to create an instance of the new
object, if the constructor has been overridden in <function>viewer_file_class_init</function>.
Overridden constructors must chain up to their parents constructor. In
order to find the parent class and chain up to the parent class
constructor, we can use the <literal>viewer_file_parent_class</literal>
pointer that has been set up for us by the
<link linkend="G-DEFINE-TYPE:CAPS"><literal>G_DEFINE_TYPE</literal></link>
macro.
</para>
<para>
Finally, at one point or another, <function>g_object_constructor</function> is invoked
by the last constructor in the chain. This function allocates the object's instance buffer
through <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>
which means that the <function>instance_init</function> function is invoked at this point if one
was registered. After <function>instance_init</function> returns, the object is fully initialized and should be
ready to have its methods called by the user. When
<function><link linkend="g-type-create-instance">g_type_create_instance</link></function>
returns, <function>g_object_constructor</function> sets the construction properties
(i.e. the properties which were given to <function><link linkend="g-object-new">g_object_new</link></function>) and returns
to the user's constructor.
</para>
<para>
The process described above might seem a bit complicated, but it can be
summarized easily by the table below which lists the functions invoked
by <function><link linkend="g-object-new">g_object_new</link></function>
and their order of invocation:
</para>
<para>
<table id="gobject-construction-table">
<title><function><link linkend="g-object-new">g_object_new</link></function></title>
<tgroup cols="3">
<colspec colwidth="*" colnum="1" align="left"/>
<colspec colwidth="*" colnum="2" align="left"/>
<colspec colwidth="8*" colnum="3" align="left"/>
<thead>
<row>
<entry>Invocation time</entry>
<entry>Function invoked</entry>
<entry>Function's parameters</entry>
<entry>Remark</entry>
</row>
</thead>
<tbody>
<row>
<entry morerows="3">First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry>
<entry>target type's <function>base_init</function> function</entry>
<entry>On the inheritance tree of classes from fundamental type to target type.
<function>base_init</function> is invoked once for each class structure.</entry>
<entry>Never used in practice. Unlikely you will need it.</entry>
</row>
<row>
<!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry-->
<entry>target type's <function>class_init</function> function</entry>
<entry>On target type's class structure</entry>
<entry>
Here, you should make sure to initialize or override class methods (that is,
assign to each class' method its function pointer) and create the signals and
the properties associated to your object.
</entry>
</row>
<row>
<!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry-->
<entry>interface's <function>base_init</function> function</entry>
<entry>On interface's vtable</entry>
<entry></entry>
</row>
<row>
<!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry-->
<entry>interface's <function>interface_init</function> function</entry>
<entry>On interface's vtable</entry>
<entry></entry>
</row>
<row>
<entry morerows="2">Each call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry>
<entry>target type's class <function>constructor</function> method: <function>GObjectClass->constructor</function></entry>
<entry>On object's instance</entry>
<entry>
If you need to handle construct properties in a custom way, or implement a singleton class, override the constructor
method and make sure to chain up to the object's
parent class before doing your own initialization.
In doubt, do not override the constructor method.
</entry>
</row>
<row>
<!--entry>Each call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry-->
<entry>type's <function>instance_init</function> function</entry>
<entry>On the inheritance tree of classes from fundamental type to target type.
the <function>instance_init</function> provided for each type is invoked once for each instance
structure.</entry>
<entry>
Provide an <function>instance_init</function> function to initialize your object before its construction
properties are set. This is the preferred way to initialize a GObject instance.
This function is equivalent to C++ constructors.
</entry>
</row>
<row>
<!--entry>Each call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry-->
<entry>target type's class <function>constructed</function> method: <function>GObjectClass->constructed</function></entry>
<entry>On object's instance</entry>
<entry>
If you need to perform object initialization steps after all construct properties have been set.
This is the final step in the object initialization process, and is only called if the <function>constructor</function>
method returned a new object instance (rather than, for example, an existing singleton).
</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
Readers should feel concerned about one little twist in the order in
which functions are invoked: while, technically, the class' constructor
method is called <emphasis>before</emphasis> the GType's <function>instance_init</function>
function (since <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> which calls <function>instance_init</function> is called by
<function>g_object_constructor</function> which is the top-level class
constructor method and to which users are expected to chain to), the
user's code which runs in a user-provided constructor will always
run <emphasis>after</emphasis> GType's <function>instance_init</function> function since the
user-provided constructor <emphasis>must</emphasis> (you've been warned)
chain up <emphasis>before</emphasis> doing anything useful.
</para>
</sect1>
<sect1 id="gobject-memory">
<title>Object memory management</title>
<para>
The memory-management API for GObjects is a bit complicated but the idea behind it
is pretty simple: the goal is to provide a flexible model based on reference counting
which can be integrated in applications which use or require different memory management
models (such as garbage collection). The methods which are used to
manipulate this reference count are described below.
</para>
<sect2 id="gobject-memory-refcount">
<title>Reference count</title>
<para>
The functions <function><link linkend="g-object-ref">g_object_ref</link></function>/<function><link linkend="g-object-unref">g_object_unref</link></function> respectively
increase and decrease the reference count. These functions are
thread-safe.
<function><link linkend="g-clear-object">g_clear_object</link></function>
is a convenience wrapper around <function>g_object_unref</function>
which also clears the pointer passed to it.
</para>
<para>
The reference count is initialized to one by
<function><link linkend="g-object-new">g_object_new</link></function> which means that the caller
is currently the sole owner of the newly-created reference. (If the object is derived from <link linkend="GInitiallyUnowned"><type>GInitiallyUnowned</type></link>, this reference count is <link linkend="floating-ref">floating</link>.)
When the reference count reaches zero, that is,
when <function><link linkend="g-object-unref">g_object_unref</link></function> is called by the last client holding
a reference to the object, the <emphasis>dispose</emphasis> and the
<emphasis>finalize</emphasis> class methods are invoked.
</para>
<para>
Finally, after <emphasis>finalize</emphasis> is invoked,
<function><link linkend="g-type-free-instance">g_type_free_instance</link></function> is called to free the object instance.
Depending on the memory allocation policy decided when the type was registered (through
one of the <function>g_type_register_*</function> functions), the object's instance
memory will be freed or returned to the object pool for this type.
Once the object has been freed, if it was the last instance of the type, the type's class
will be destroyed as described in <xref linkend="gtype-instantiatable-classed"/> and
<xref linkend="gtype-non-instantiatable-classed"/>.
</para>
<para>
The table below summarizes the destruction process of a GObject:
<table id="gobject-destruction-table">
<title><function><link linkend="g-object-unref">g_object_unref</link></function></title>
<tgroup cols="3">
<colspec colwidth="*" colnum="1" align="left"/>
<colspec colwidth="*" colnum="2" align="left"/>
<colspec colwidth="8*" colnum="3" align="left"/>
<thead>
<row>
<entry>Invocation time</entry>
<entry>Function invoked</entry>
<entry>Function's parameters</entry>
<entry>Remark</entry>
</row>
</thead>
<tbody>
<row>
<entry morerows="1">Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for an instance
of target type
</entry>
<entry>target type's dispose class function</entry>
<entry>GObject instance</entry>
<entry>
When dispose ends, the object should not hold any reference to any other
member object. The object is also expected to be able to answer client
method invocations (with possibly an error code but no memory violation)
until finalize is executed. dispose can be executed more than once.
dispose should chain up to its parent implementation just before returning
to the caller.
</entry>
</row>
<row>
<!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for an instance
of target type
</entry-->
<entry>target type's finalize class function</entry>
<entry>GObject instance</entry>
<entry>
Finalize is expected to complete the destruction process initiated by
dispose. It should complete the object's destruction. finalize will be
executed only once.
finalize should chain up to its parent implementation just before returning
to the caller.
The reason why the destruction process is split is two different phases is
explained in <xref linkend="gobject-memory-cycles"/>.
</entry>
</row>
<row>
<entry morerows="3">Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last
instance of target type
</entry>
<entry>interface's <function>interface_finalize</function> function</entry>
<entry>On interface's vtable</entry>
<entry>Never used in practice. Unlikely you will need it.</entry>
</row>
<row>
<!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function>for the last
instance of target type
</entry-->
<entry>interface's <function>base_finalize</function> function</entry>
<entry>On interface's vtable</entry>
<entry>Never used in practice. Unlikely you will need it.</entry>
</row>
<row>
<!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last
instance of target type
</entry-->
<entry>target type's <function>class_finalize</function> function</entry>
<entry>On target type's class structure</entry>
<entry>Never used in practice. Unlikely you will need it.</entry>
</row>
<row>
<!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last
instance of target type
</entry-->
<entry>type's <function>base_finalize</function> function</entry>
<entry>On the inheritance tree of classes from fundamental type to target type.
<function>base_init</function> is invoked once for each class structure.</entry>
<entry>Never used in practice. Unlikely you will need it.</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
</sect2>
<sect2 id="gobject-memory-weakref">
<title>Weak References</title>
<para>
Weak references are used to monitor object finalization:
<function><link linkend="g-object-weak-ref">g_object_weak_ref</link></function> adds a monitoring callback which does
not hold a reference to the object but which is invoked when the object runs
its dispose method. As such, each weak ref can be invoked more than once upon
object finalization (since dispose can run more than once during object
finalization).
</para>
<para>
<function><link linkend="g-object-weak-unref">g_object_weak_unref</link></function> can be used to remove a monitoring
callback from the object.
</para>
<para>
Weak references are also used to implement <function><link linkend="g-object-add-weak-pointer">g_object_add_weak_pointer</link></function>
and <function><link linkend="g-object-remove-weak-pointer">g_object_remove_weak_pointer</link></function>. These functions add a weak reference
to the object they are applied to which makes sure to nullify the pointer given by the user
when object is finalized.
</para>
<para>
Similarly, <link linkend="GWeakRef"><type>GWeakRef</type></link> can be
used to implement weak references if thread safety is required.
</para>
</sect2>
<sect2 id="gobject-memory-cycles">
<title>Reference counts and cycles</title>
<para>
GObject's memory management model was designed to be easily integrated in existing code
using garbage collection. This is why the destruction process is split in two phases:
the first phase, executed in the dispose handler is supposed to release all references
to other member objects. The second phase, executed by the finalize handler is supposed
to complete the object's destruction process. Object methods should be able to run
without program error in-between the two phases.
</para>
<para>
This two-step destruction process is very useful to break reference counting cycles.
While the detection of the cycles is up to the external code, once the cycles have been
detected, the external code can invoke <function><link linkend="g-object-run-dispose">g_object_run_dispose</link></function> which
will indeed break any existing cycles since it will run the dispose handler associated
to the object and thus release all references to other objects.
</para>
<para>
This explains one of the rules about the dispose handler stated earlier:
the dispose handler can be invoked multiple times. Let's say we
have a reference count cycle: object A references B which itself references object A.
Let's say we have detected the cycle and we want to destroy the two objects. One way to
do this would be to invoke <function><link linkend="g-object-run-dispose">g_object_run_dispose</link></function> on one of the
objects.
</para>
<para>
If object A releases all its references to all objects, this means it releases its
reference to object B. If object B was not owned by anyone else, this is its last
reference count which means this last unref runs B's dispose handler which, in turn,
releases B's reference on object A. If this is A's last reference count, this last
unref runs A's dispose handler which is running for the second time before
A's finalize handler is invoked !
</para>
<para>
The above example, which might seem a bit contrived, can really happen if
GObjects are being handled by language bindings — hence the rules for
object destruction should be closely followed.
</para>
</sect2>
</sect1>
<sect1 id="gobject-properties">
<title>Object properties</title>
<para>
One of GObject's nice features is its generic get/set mechanism for object
properties. When an object
is instantiated, the object's <function>class_init</function> handler should be used to register
the object's properties with <function><link linkend="g-object-class-install-properties">g_object_class_install_properties</link></function>.
</para>
<para>
The best way to understand how object properties work is by looking at a real example
of how it is used:
<informalexample><programlisting>
/************************************************/
/* Implementation */
/************************************************/
typedef enum
{
PROP_FILENAME = 1,
PROP_ZOOM_LEVEL,
N_PROPERTIES
} ViewerFileProperty;
static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
static void
viewer_file_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
ViewerFile *self = VIEWER_FILE (object);
switch ((ViewerFileProperty) property_id)
{
case PROP_FILENAME:
g_free (self-&gt;filename);
self-&gt;filename = g_value_dup_string (value);
g_print ("filename: %s\n", self-&gt;filename);
break;
case PROP_ZOOM_LEVEL:
self-&gt;zoom_level = g_value_get_uint (value);
g_print ("zoom level: &percnt;u\n", self-&gt;zoom_level);
break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
viewer_file_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
ViewerFile *self = VIEWER_FILE (object);
switch ((ViewerFileProperty) property_id)
{
case PROP_FILENAME:
g_value_set_string (value, self-&gt;filename);
break;
case PROP_ZOOM_LEVEL:
g_value_set_uint (value, self-&gt;zoom_level);
break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
viewer_file_class_init (ViewerFileClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class-&gt;set_property = viewer_file_set_property;
object_class-&gt;get_property = viewer_file_get_property;
obj_properties[PROP_FILENAME] =
g_param_spec_string ("filename",
"Filename",
"Name of the file to load and display from.",
NULL /* default value */,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
obj_properties[PROP_ZOOM_LEVEL] =
g_param_spec_uint ("zoom-level",
"Zoom level",
"Zoom level to view the file at.",
0 /* minimum value */,
10 /* maximum value */,
2 /* default value */,
G_PARAM_READWRITE);
g_object_class_install_properties (object_class,
N_PROPERTIES,
obj_properties);
}
/************************************************/
/* Use */
/************************************************/
ViewerFile *file;
GValue val = G_VALUE_INIT;
file = g_object_new (VIEWER_TYPE_FILE, NULL);
g_value_init (&amp;val, G_TYPE_UINT);
g_value_set_char (&amp;val, 11);
g_object_set_property (G_OBJECT (file), "zoom-level", &amp;val);
g_value_unset (&amp;val);
</programlisting></informalexample>
The client code above looks simple but a lot of things happen under the hood:
</para>
<para>
<function><link linkend="g-object-set-property">g_object_set_property</link></function> first ensures a property
with this name was registered in <emphasis>file</emphasis>'s <function>class_init</function> handler. If so it walks the class hierarchy,
from bottom-most most-derived type, to top-most fundamental type to find the class
which registered that property. It then tries to convert the user-provided
<link linkend="GValue"><type>GValue</type></link>
into a <type>GValue</type> whose type is that of the associated property.
</para>
<para>
If the user provides a <type>signed char</type> <type>GValue</type>, as is shown
here, and if the object's property was registered as an <type>unsigned int</type>,
<function><link linkend="g-value-transform">g_value_transform</link></function> will try to transform the input signed char into
an unsigned int. Of course, the success of the transformation depends on the availability
of the required transform function. In practice, there will almost always be a transformation
<footnote>
<para>Its behaviour might not be what you expect but it is up to you to actually avoid
relying on these transformations.
</para>
</footnote>
which matches and conversion will be carried out if needed.
</para>
<para>
After transformation, the <link linkend="GValue"><type>GValue</type></link> is validated by
<function><link linkend="g-param-value-validate">g_param_value_validate</link></function> which makes sure the user's
data stored in the <link linkend="GValue"><type>GValue</type></link> matches the characteristics specified by
the property's <link linkend="GParamSpec"><type>GParamSpec</type></link>.
Here, the <link linkend="GParamSpec"><type>GParamSpec</type></link> we
provided in <function>class_init</function> has a validation function which makes sure that the GValue
contains a value which respects the minimum and maximum bounds of the
<link linkend="GParamSpec"><type>GParamSpec</type></link>. In the example above, the client's GValue does not
respect these constraints (it is set to 11, while the maximum is 10). As such, the
<function><link linkend="g-object-set-property">g_object_set_property</link></function> function will return with an error.
</para>
<para>
If the user's GValue had been set to a valid value, <function><link linkend="g-object-set-property">g_object_set_property</link></function>
would have proceeded with calling the object's
<function>set_property</function> class method. Here, since our
implementation of <type>ViewerFile</type> did override this method, execution would jump to
<function>viewer_file_set_property</function> after having retrieved from the
<link linkend="GParamSpec"><type>GParamSpec</type></link> the <emphasis>param_id</emphasis>
<footnote>
<para>
It should be noted that the param_id used here need only to uniquely identify each
<link linkend="GParamSpec"><type>GParamSpec</type></link> within the <type>ViewerFileClass</type> such that the switch
used in the set and get methods actually works. Of course, this locally-unique
integer is purely an optimization: it would have been possible to use a set of
<emphasis>if (strcmp (a, b) == 0) {} else if (strcmp (a, b) == 0) {}</emphasis> statements.
</para>
</footnote>
which had been stored by
<function><link linkend="g-object-class-install-property">g_object_class_install_property</link></function>.
</para>
<para>
Once the property has been set by the object's
<function>set_property</function> class method, execution
returns to <function><link linkend="g-object-set-property">g_object_set_property</link></function> which makes sure that
the "notify" signal is emitted on the object's instance with the changed property as
parameter unless notifications were frozen by <function><link linkend="g-object-freeze-notify">g_object_freeze_notify</link></function>.
</para>
<para>
<function><link linkend="g-object-thaw-notify">g_object_thaw_notify</link></function> can be used to re-enable notification of
property modifications through the
<link linkend="GObject-notify"><type>“notify”</type></link> signal. It is important to remember that
even if properties are changed while property change notification is frozen, the "notify"
signal will be emitted once for each of these changed properties as soon as the property
change notification is thawed: no property change is lost for the "notify"
signal, although multiple notifications for a single property are
compressed. Signals can only be delayed by the notification freezing
mechanism.
</para>
<para>
It sounds like a tedious task to set up GValues every time when one wants to modify a property.
In practice one will rarely do this. The functions <function><link linkend="g-object-set-property">g_object_set_property</link></function>
and <function><link linkend="g-object-get-property">g_object_get_property</link></function>
are meant to be used by language bindings. For application there is an easier way and
that is described next.
</para>
<sect2 id="gobject-multi-properties">
<title>Accessing multiple properties at once</title>
<para>
It is interesting to note that the <function><link linkend="g-object-set">g_object_set</link></function> and
<function><link linkend="g-object-set-valist">g_object_set_valist</link></function> (variadic version) functions can be used to set
multiple properties at once. The client code shown above can then be re-written as:
<informalexample><programlisting>
ViewerFile *file;
file = /* */;
g_object_set (G_OBJECT (file),
"zoom-level", 6,
"filename", "~/some-file.txt",
NULL);
</programlisting></informalexample>
This saves us from managing the GValues that we were needing to handle when using
<function><link linkend="g-object-set-property">g_object_set_property</link></function>.
The code above will trigger one notify signal emission for each property modified.
</para>
<para>
Equivalent <function>_get</function> versions are also available:
<function><link linkend="g-object-get">g_object_get</link></function>
and <function><link linkend="g-object-get-valist">g_object_get_valist</link></function> (variadic version) can be used to get numerous
properties at once.
</para>
<para>
These high level functions have one drawback — they don't provide a return value.
One should pay attention to the argument types and ranges when using them.
A known source of errors is to pass a different type from what the
property expects; for instance, passing an integer when the property
expects a floating point value and thus shifting all subsequent parameters
by some number of bytes. Also forgetting the terminating
<literal>NULL</literal> will lead to undefined behaviour.
</para>
<para>
This explains how <function><link linkend="g-object-new">g_object_new</link></function>,
<function><link linkend="g-object-newv">g_object_newv</link></function> and <function><link linkend="g-object-new-valist">g_object_new_valist</link></function>
work: they parse the user-provided variable number of parameters and invoke
<function><link linkend="g-object-set">g_object_set</link></function> on the parameters only after the object has been successfully constructed.
The "notify" signal will be emitted for each property set.
</para>
</sect2>
<!-- @todo tell here about how to pass use handle properties in derived classes -->
</sect1>
</chapter>

View file

@ -0,0 +1,495 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<chapter id="chapter-signal">
<title>The GObject messaging system</title>
<sect1 id="closure">
<title>Closures</title>
<para>
Closures are central to the concept of asynchronous signal delivery
which is widely used throughout GTK+ and GNOME applications. A closure is an
abstraction, a generic representation of a callback. It is a small structure
which contains three objects:
<itemizedlist>
<listitem><para>a function pointer (the callback itself) whose prototype looks like:
<informalexample><programlisting>
return_type function_callback (… , gpointer user_data);
</programlisting></informalexample>
</para></listitem>
<listitem><para>
the <parameter>user_data</parameter> pointer which is passed to the callback upon invocation of the closure
</para></listitem>
<listitem><para>
a function pointer which represents the destructor of the closure: whenever the
closure's refcount reaches zero, this function will be called before the closure
structure is freed.
</para></listitem>
</itemizedlist>
</para>
<para>
The <link linkend="GClosure"><type>GClosure</type></link> structure represents the common functionality of all
closure implementations: there exists a different closure implementation for
each separate runtime which wants to use the GObject type system.
<footnote><para>
In practice, closures sit at the boundary of language runtimes: if you are
writing Python code and one of your Python callbacks receives a signal from
a GTK+ widget, the C code in GTK+ needs to execute your Python
code. The closure invoked by the GTK+ object invokes the Python callback:
it behaves as a normal C object for GTK+ and as a normal Python object for
Python code.
</para></footnote>
The GObject library provides a simple <link linkend="GCClosure"><type>GCClosure</type></link> type which
is a specific implementation of closures to be used with C/C++ callbacks.
</para>
<para>
A <link linkend="GClosure"><type>GClosure</type></link> provides simple services:
<itemizedlist>
<listitem><para>
Invocation (<function><link linkend="g-closure-invoke">g_closure_invoke</link></function>): this is what closures
were created for: they hide the details of callback invocation from the
callback invoker.</para>
</listitem>
<listitem><para>
Notification: the closure notifies listeners of certain events such as
closure invocation, closure invalidation and closure finalization. Listeners
can be registered with <function><link linkend="g-closure-add-finalize-notifier">g_closure_add_finalize_notifier</link></function>
(finalization notification), <function><link linkend="g-closure-add-invalidate-notifier">g_closure_add_invalidate_notifier</link></function>
(invalidation notification) and
<function><link linkend="g-closure-add-marshal-guards">g_closure_add_marshal_guards</link></function> (invocation notification).
There exist symmetric deregistration functions for finalization and invalidation
events (<function><link linkend="g-closure-remove-finalize-notifier">g_closure_remove_finalize_notifier</link></function> and
<function><link linkend="g-closure-remove-invalidate-notifier">g_closure_remove_invalidate_notifier</link></function>) but not for the invocation
process.
<footnote><para>
Closures are reference counted and notify listeners of their destruction in a two-stage
process: the invalidation notifiers are invoked before the finalization notifiers.
</para></footnote></para>
</listitem>
</itemizedlist>
</para>
<sect2>
<title>C Closures</title>
<para>
If you are using C or C++
to connect a callback to a given event, you will either use simple <link linkend="GCClosure"><type>GCClosure</type></link>s
which have a pretty minimal API or the even simpler <function><link linkend="g-signal-connect">g_signal_connect</link></function>
functions (which will be presented a bit later).
</para>
<para>
<function><link linkend="g-cclosure-new">g_cclosure_new</link></function> will create a new closure which can invoke the
user-provided callback_func with the user-provided
<parameter>user_data</parameter> as its last parameter. When the closure
is finalized (second stage of the destruction process), it will invoke
the <parameter>destroy_data</parameter> function if the user has
supplied one.
</para>
<para>
<function><link linkend="g-cclosure-new-swap">g_cclosure_new_swap</link></function> will create a new closure which can invoke the
user-provided <parameter>callback_func</parameter> with the
user-provided <parameter>user_data</parameter> as its first parameter
(instead of being the
last parameter as with <function><link linkend="g-cclosure-new">g_cclosure_new</link></function>). When the closure
is finalized (second stage of the destruction process), it will invoke
the <parameter>destroy_data</parameter> function if the user has
supplied one.
</para>
</sect2>
<sect2>
<title>Non-C closures (for the fearless)</title>
<para>
As was explained above, closures hide the details of callback invocation. In C,
callback invocation is just like function invocation: it is a matter of creating
the correct stack frame for the called function and executing a <emphasis>call</emphasis>
assembly instruction.
</para>
<para>
C closure marshallers transform the array of GValues which represent
the parameters to the target function into a C-style function parameter list, invoke
the user-supplied C function with this new parameter list, get the return value of the
function, transform it into a GValue and return this GValue to the marshaller caller.
</para>
<para>
A generic C closure marshaller is available as
<link linkend="g-cclosure-marshal-generic"><function>g_cclosure_marshal_generic</function></link>
which implements marshalling for all function types using libffi. Custom
marshallers for different types are not needed apart from performance
critical code where the libffi-based marshaller may be too slow.
</para>
<para>
An example of a custom marshaller is given below, illustrating how
<type>GValue</type>s can be converted to a C function call. The
marshaller is for a C function which takes an integer as its first
parameter and returns void.
<informalexample><programlisting>
g_cclosure_marshal_VOID__INT (GClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data)
{
typedef void (*GMarshalFunc_VOID__INT) (gpointer data1,
gint arg_1,
gpointer data2);
register GMarshalFunc_VOID__INT callback;
register GCClosure *cc = (GCClosure*) closure;
register gpointer data1, data2;
g_return_if_fail (n_param_values == 2);
data1 = g_value_peek_pointer (param_values + 0);
data2 = closure->data;
callback = (GMarshalFunc_VOID__INT) (marshal_data ? marshal_data : cc->callback);
callback (data1,
g_marshal_value_peek_int (param_values + 1),
data2);
}
</programlisting></informalexample>
</para>
<para>
There exist other kinds of marshallers, for example there is a generic
Python marshaller which is used by all Python closures (a Python closure
is used to invoke a callback written in Python). This Python marshaller
transforms the input GValue list representing the function parameters
into a Python tuple which is the equivalent structure in Python.
</para>
</sect2>
</sect1>
<sect1 id="signal">
<title>Signals</title>
<para>
GObject's signals have nothing to do with standard UNIX signals: they connect
arbitrary application-specific events with any number of listeners.
For example, in GTK+, every user event (keystroke or mouse move) is received
from the windowing system and generates a GTK+ event in the form of a signal emission
on the widget object instance.
</para>
<para>
Each signal is registered in the type system together with the type on which
it can be emitted: users of the type are said to <emphasis>connect</emphasis>
to the signal on a given type instance when they register a closure to be
invoked upon the signal emission. The closure will be called synchronously on emission.
Users can also emit the signal by themselves or stop the emission of the signal from
within one of the closures connected to the signal.
</para>
<para>
When a signal is emitted on a given type instance, all the closures
connected to this signal on this type instance will be invoked. All the closures
connected to such a signal represent callbacks whose signature looks like:
<informalexample><programlisting>
return_type function_callback (gpointer instance, …, gpointer user_data);
</programlisting></informalexample>
</para>
<sect2 id="signal-registration">
<title>Signal registration</title>
<para>
To register a new signal on an existing type, we can use any of <function><link linkend="g-signal-newv">g_signal_newv</link></function>,
<function><link linkend="g-signal-new-valist">g_signal_new_valist</link></function> or <function><link linkend="g-signal-new">g_signal_new</link></function> functions:
<informalexample><programlisting>
guint g_signal_newv (const gchar *signal_name,
GType itype,
GSignalFlags signal_flags,
GClosure *class_closure,
GSignalAccumulator accumulator,
gpointer accu_data,
GSignalCMarshaller c_marshaller,
GType return_type,
guint n_params,
GType *param_types);
</programlisting></informalexample>
The number of parameters to these functions is a bit intimidating but they are relatively
simple:
<itemizedlist>
<listitem><para>
<parameter>signal_name</parameter>: is a string which can be used to uniquely identify a given signal.
</para></listitem>
<listitem><para>
<parameter>itype</parameter>: is the instance type on which this signal can be emitted.
</para></listitem>
<listitem><para>
<parameter>signal_flags</parameter>: partly defines the order in which closures which were connected to the
signal are invoked.
</para></listitem>
<listitem><para>
<parameter>class_closure</parameter>: this is the default closure for the signal: if it is not NULL upon
the signal emission, it will be invoked upon this emission of the signal. The
moment where this closure is invoked compared to other closures connected to that
signal depends partly on the signal_flags.
</para></listitem>
<listitem><para>
<parameter>accumulator</parameter>: this is a function pointer which is invoked after each closure
has been invoked. If it returns FALSE, signal emission is stopped. If it returns
TRUE, signal emission proceeds normally. It is also used to compute the return
value of the signal based on the return value of all the invoked closures.
For example, an accumulator could ignore
<literal>NULL</literal> returns from closures; or it
could build a list of the values returned by the
closures.
</para></listitem>
<listitem><para>
<parameter>accu_data</parameter>: this pointer will be passed down to each invocation of the
accumulator during emission.
</para></listitem>
<listitem><para>
<parameter>c_marshaller</parameter>: this is the default C marshaller for any closure which is connected to
this signal.
</para></listitem>
<listitem><para>
<parameter>return_type</parameter>: this is the type of the return value of the signal.
</para></listitem>
<listitem><para>
<parameter>n_params</parameter>: this is the number of parameters this signal takes.
</para></listitem>
<listitem><para>
<parameter>param_types</parameter>: this is an array of GTypes which indicate the type of each parameter
of the signal. The length of this array is indicated by n_params.
</para></listitem>
</itemizedlist>
</para>
<para>
As you can see from the above definition, a signal is basically a description
of the closures which can be connected to this signal and a description of the
order in which the closures connected to this signal will be invoked.
</para>
</sect2>
<sect2 id="signal-connection">
<title>Signal connection</title>
<para>
If you want to connect to a signal with a closure, you have three possibilities:
<itemizedlist>
<listitem><para>
You can register a class closure at signal registration: this is a
system-wide operation. i.e.: the class closure will be invoked during each emission
of a given signal on <emphasis>any</emphasis> of the instances of the type which supports that signal.
</para></listitem>
<listitem><para>
You can use <function><link linkend="g-signal-override-class-closure">g_signal_override_class_closure</link></function> which
overrides the class closure of a given type. It is possible to call this function
only on a derived type of the type on which the signal was registered.
This function is of use only to language bindings.
</para></listitem>
<listitem><para>
You can register a closure with the <function><link linkend="g-signal-connect">g_signal_connect</link></function>
family of functions. This is an instance-specific operation: the closure
will be invoked only during emission of a given signal on a given instance.
</para></listitem>
</itemizedlist>
It is also possible to connect a different kind of callback on a given signal:
emission hooks are invoked whenever a given signal is emitted whatever the instance on
which it is emitted. Emission hooks are used for example to get all mouse_clicked
emissions in an application to be able to emit the small mouse click sound.
Emission hooks are connected with <function><link linkend="g-signal-add-emission-hook">g_signal_add_emission_hook</link></function>
and removed with <function><link linkend="g-signal-remove-emission-hook">g_signal_remove_emission_hook</link></function>.
</para>
</sect2>
<sect2 id="signal-emission">
<title>Signal emission</title>
<para>
Signal emission is done through the use of the <function><link linkend="g-signal-emit">g_signal_emit</link></function> family
of functions.
<informalexample><programlisting>
void g_signal_emitv (const GValue *instance_and_params,
guint signal_id,
GQuark detail,
GValue *return_value);
</programlisting></informalexample>
<itemizedlist>
<listitem><para>
The <parameter>instance_and_params</parameter> array of GValues contains the list of input
parameters to the signal. The first element of the array is the
instance pointer on which to invoke the signal. The following elements of
the array contain the list of parameters to the signal.
</para></listitem>
<listitem><para>
<parameter>signal_id</parameter> identifies the signal to invoke.
</para></listitem>
<listitem><para>
<parameter>detail</parameter> identifies the specific detail of the signal to invoke. A detail is a kind of
magic token/argument which is passed around during signal emission and which is used
by closures connected to the signal to filter out unwanted signal emissions. In most
cases, you can safely set this value to zero. See <xref linkend="signal-detail"/> for
more details about this parameter.
</para></listitem>
<listitem><para>
<parameter>return_value</parameter> holds the return value of the last closure invoked during emission if
no accumulator was specified. If an accumulator was specified during signal creation,
this accumulator is used to calculate the return value as a function of the return
values of all the closures invoked during emission.
If no closure is invoked during
emission, the <parameter>return_value</parameter> is nonetheless initialized to zero/null.
</para></listitem>
</itemizedlist>
</para>
<para>
Signal emission is done synchronously and can be decomposed in 5 steps:
<orderedlist>
<listitem><para>
<literal>RUN_FIRST</literal>: if the
<link linkend="G-SIGNAL-RUN-FIRST:CAPS"><literal>G_SIGNAL_RUN_FIRST</literal></link> flag was used
during signal registration and if there exists a class closure for this signal,
the class closure is invoked.
</para></listitem>
<listitem><para>
<literal>EMISSION_HOOK</literal>: if any emission hook was added to
the signal, they are invoked from first to last added. Accumulate return values.
</para></listitem>
<listitem><para>
<literal>HANDLER_RUN_FIRST</literal>: if any closure were connected
with the <function><link linkend="g-signal-connect">g_signal_connect</link></function> family of
functions, and if they are not blocked (with the <function><link linkend="g-signal-handler-block">g_signal_handler_block</link></function>
family of functions) they are run here, from first to last connected.
</para></listitem>
<listitem><para>
<literal>RUN_LAST</literal>: if the <literal>G_SIGNAL_RUN_LAST</literal>
flag was set during registration and if a class closure
was set, it is invoked here.
</para></listitem>
<listitem><para>
<literal>HANDLER_RUN_LAST</literal>: if any closure were connected
with the <function>g_signal_connect_after</function> family of
functions, if they were not invoked during <literal>HANDLER_RUN_FIRST</literal> and if they
are not blocked, they are run here, from first to last connected.
</para></listitem>
<listitem><para>
<literal>RUN_CLEANUP</literal>: if the <literal>G_SIGNAL_RUN_CLEANUP</literal> flag
was set during registration and if a class closure was set,
it is invoked here. Signal emission is completed here.
</para></listitem>
</orderedlist>
</para>
<para>
If, at any point during emission (except in <literal>RUN_CLEANUP</literal> or
<literal>EMISSION_HOOK</literal> state), one of the closures stops the signal emission with
<function><link linkend="g-signal-stop-emission">g_signal_stop_emission</link></function>,
emission jumps to <literal>RUN_CLEANUP</literal> state.
</para>
<para>
If, at any point during emission, one of the closures or emission hook
emits the same signal on the same instance, emission is restarted from
the <literal>RUN_FIRST</literal> state.
</para>
<para>
The accumulator function is invoked in all states, after invocation
of each closure (except in <literal>RUN_EMISSION_HOOK</literal> and
<literal>RUN_CLEANUP</literal>). It accumulates
the closure return value into the signal return value and returns TRUE or
FALSE. If, at any point, it does not return TRUE, emission jumps
to <literal>RUN_CLEANUP</literal> state.
</para>
<para>
If no accumulator function was provided, the value returned by the last handler
run will be returned by <function><link linkend="g-signal-emit">g_signal_emit</link></function>.
</para>
</sect2>
<sect2 id="signal-detail">
<title>The <emphasis>detail</emphasis> argument</title>
<para>All the functions related to signal emission or signal connection have a parameter
named the <emphasis>detail</emphasis>. Sometimes, this parameter is hidden by the API
but it is always there, in one form or another.
</para>
<para>
Of the three main connection functions,
only one has an explicit detail parameter as a <link linkend="GQuark"><type>GQuark</type></link>:
<link linkend="g-signal-connect-closure-by-id"><function>g_signal_connect_closure_by_id</function></link>.
<footnote>
<para>A GQuark is an integer which uniquely represents a string. It is possible to transform
back and forth between the integer and string representations with the functions
<function><link linkend="g-quark-from-string">g_quark_from_string</link></function> and <function><link linkend="g-quark-to-string">g_quark_to_string</link></function>.
</para>
</footnote>
</para>
<para>
The two other functions,
<link linkend="g-signal-connect-closure"><function>g_signal_connect_closure</function></link> and
<link linkend="g-signal-connect-data"><function>g_signal_connect_data</function></link>
hide the detail parameter in the signal name identification.
Their <parameter>detailed_signal</parameter> parameter is a
string which identifies the name of the signal to connect to.
The format of this string should match
<emphasis>signal_name::detail_name</emphasis>. For example,
connecting to the signal named
<emphasis>notify::cursor_position</emphasis> will actually
connect to the signal named <emphasis>notify</emphasis> with the
<emphasis>cursor_position</emphasis> detail.
Internally, the detail string is transformed to a GQuark if it is present.
</para>
<para>
Of the four main signal emission functions, one hides it in its
signal name parameter:
<link linkend="g-signal-connect"><function>g_signal_connect</function></link>.
The other three have an explicit detail parameter as a
<link linkend="GQuark"><type>GQuark</type></link> again:
<link linkend="g-signal-emit"><function>g_signal_emit</function></link>,
<link linkend="g-signal-emitv"><function>g_signal_emitv</function></link> and
<link linkend="g-signal-emit-valist"><function>g_signal_emit_valist</function></link>.
</para>
<para>
If a detail is provided by the user to the emission function, it is used during emission to match
against the closures which also provide a detail.
If a closure's detail does not match the detail provided by the user, it
will not be invoked (even though it is connected to a signal which is
being emitted).
</para>
<para>
This completely optional filtering mechanism is mainly used as an optimization for signals
which are often emitted for many different reasons: the clients can filter out which events they are
interested in before the closure's marshalling code runs. For example, this is used extensively
by the <link linkend="GObject-notify"><structfield>notify</structfield></link> signal of GObject: whenever a property is modified on a GObject,
instead of just emitting the <emphasis>notify</emphasis> signal, GObject associates as a detail to this
signal emission the name of the property modified. This allows clients who wish to be notified of changes
to only one property to filter most events before receiving them.
</para>
<para>
As a simple rule, users can and should set the detail parameter to zero: this will disable completely
this optional filtering for that signal.
</para>
</sect2>
</sect1>
</chapter>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,185 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<chapter id="chapter-intro">
<title>Background</title>
<para>
GObject, and its lower-level type system, GType, are used by GTK+ and most GNOME libraries to
provide:
<itemizedlist>
<listitem><para>object-oriented C-based APIs and</para></listitem>
<listitem><para>automatic transparent API bindings to other compiled
or interpreted languages.</para></listitem>
</itemizedlist>
</para>
<para>
A lot of programmers are used to working with compiled-only or dynamically interpreted-only
languages and do not understand the challenges associated with cross-language interoperability.
This introduction tries to provide an insight into these challenges and briefly describes
the solution chosen by GLib.
</para>
<para>
The following chapters go into greater detail into how GType and GObject work and
how you can use them as a C programmer. It is useful to keep in mind that
allowing access to C objects from other interpreted languages was one of the major design
goals: this can often explain the sometimes rather convoluted APIs and features present
in this library.
</para>
<sect1>
<title>Data types and programming</title>
<para>
One could say
that a programming language is merely a way to create data types and manipulate them. Most languages
provide a number of language-native types and a few primitives to create more complex types based
on these primitive types.
</para>
<para>
In C, the language provides types such as <emphasis>char</emphasis>, <emphasis>long</emphasis>,
<emphasis>pointer</emphasis>. During compilation of C code, the compiler maps these
language types to the compiler's target architecture machine types. If you are using a C interpreter
(assuming one exists), the interpreter (the program which interprets
the source code and executes it) maps the language types to the machine types of the target machine at
runtime, during the program execution (or just before execution if it uses a Just In Time compiler engine).
</para>
<para>
Perl and Python are interpreted languages which do not really provide type definitions similar
to those used by C. Perl and Python programmers manipulate variables and the type of the variables
is decided only upon the first assignment or upon the first use which forces a type on the variable.
The interpreter also often provides a lot of automatic conversions from one type to the other. For example,
in Perl, a variable which holds an integer can be automatically converted to a string given the
required context:
<informalexample><programlisting>
my $tmp = 10;
print "this is an integer converted to a string:" . $tmp . "\n";
</programlisting></informalexample>
Of course, it is also often possible to explicitly specify conversions when the default conversions provided
by the language are not intuitive.
</para>
</sect1>
<sect1>
<title>Exporting a C API</title>
<para>
C APIs are defined by a set of functions and global variables which are usually exported from a
binary. C functions have an arbitrary number of arguments and one return value. Each function is thus
uniquely identified by the function name and the set of C types which describe the function arguments
and return value. The global variables exported by the API are similarly identified by their name and
their type.
</para>
<para>
A C API is thus merely defined by a set of names to which a set of types are associated. If you know the
function calling convention and the mapping of the C types to the machine types used by the platform you
are on, you can resolve the name of each function to find where the code associated to this function
is located in memory, and then construct a valid argument list for the function. Finally, all you have to
do is trigger a call to the target C function with the argument list.
</para>
<para>
For the sake of discussion, here is a sample C function and the associated 32 bit x86
assembly code generated by GCC on a Linux computer:
<informalexample><programlisting>
static void
function_foo (int foo)
{
}
int
main (int argc,
char *argv[])
{
function_foo (10);
return 0;
}
push $0xa
call 0x80482f4 &lt;function_foo>
</programlisting></informalexample>
The assembly code shown above is pretty straightforward: the first instruction pushes
the hexadecimal value 0xa (decimal value 10) as a 32-bit integer on the stack and calls
<function>function_foo</function>. As you can see, C function calls are implemented by
GCC as native function calls (this is probably the fastest implementation possible).
</para>
<para>
Now, let's say we want to call the C function <function>function_foo</function> from
a Python program. To do this, the Python interpreter needs to:
<itemizedlist>
<listitem><para>Find where the function is located. This probably means finding the binary generated by the C compiler
which exports this function.</para></listitem>
<listitem><para>Load the code of the function in executable memory.</para></listitem>
<listitem><para>Convert the Python parameters to C-compatible parameters before calling
the function.</para></listitem>
<listitem><para>Call the function with the right calling convention.</para></listitem>
<listitem><para>Convert the return values of the C function to Python-compatible
variables to return them to the Python code.</para></listitem>
</itemizedlist>
</para>
<para>
The process described above is pretty complex and there are a lot of ways to make it entirely automatic
and transparent to C and Python programmers:
<itemizedlist>
<listitem><para>The first solution is to write by hand a lot of glue code, once for each function exported or imported,
which does the Python-to-C parameter conversion and the C-to-Python return value conversion. This glue code is then
linked with the interpreter which allows Python programs to call Python functions which delegate work to
C functions.</para></listitem>
<listitem><para>Another, nicer solution is to automatically generate the glue code, once for each function exported or
imported, with a special compiler which
reads the original function signature.</para></listitem>
<listitem><para>The solution used by GLib is to use the GType library which holds at runtime a description of
all the objects manipulated by the programmer. This so-called <emphasis>dynamic type</emphasis>
<footnote>
<para>
There are numerous different implementations of dynamic type systems: all C++
compilers have one, Java and .NET have one too. A dynamic type system allows you
to get information about every instantiated object at runtime. It can be implemented
by a process-specific database: every new object created registers the characteristics
of its associated type in the type system. It can also be implemented by introspection
interfaces. The common point between all these different type systems and implementations
is that they all allow you to query for object metadata at runtime.
</para>
</footnote>
library is then used by special generic glue code to automatically convert function parameters and
function calling conventions between different runtime domains.</para></listitem>
</itemizedlist>
The greatest advantage of the solution implemented by GType is that the glue code sitting at the runtime domain
boundaries is written once: the figure below states this more clearly.
<figure>
<mediaobject>
<imageobject> <!-- this is for HTML output -->
<imagedata fileref="glue.png" format="PNG" align="center"/>
</imageobject>
<imageobject> <!-- this is for PDF output -->
<imagedata fileref="glue.jpg" format="JPG" align="center"/>
</imageobject>
</mediaobject>
</figure>
Currently, there exist at least Python and Perl generic glue code which makes it possible to use
C objects written with GType directly in Python or Perl, with a minimum amount of work: there
is no need to generate huge amounts of glue code either automatically or by hand.
</para>
<para>
Although that goal was arguably laudable, its pursuit has had a major influence on
the whole GType/GObject library. C programmers are likely to be puzzled at the complexity
of the features exposed in the following chapters if they forget that the GType/GObject library
was not only designed to offer OO-like features to C programmers but also transparent
cross-language interoperability.
</para>
</sect1>
</chapter>

View file

@ -0,0 +1,125 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE part PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<part label="V">
<title>Related Tools</title>
<partintro>
<para>
Several useful developer tools have been build around GObject
technology. The next sections briefly introduce them and link to
the respective project pages.
</para>
<para>
For example, writing GObjects is often seen as a tedious task. It
requires a lot of typing and just doing a copy/paste requires a
great deal of care. A lot of projects and scripts have been
written to generate GObject skeleton form boilerplate code, or
even translating higher-level language into plain C.
</para>
</partintro>
<chapter id="tools-vala">
<title>Vala</title>
<para>
From the <ulink url="https://wiki.gnome.org/Projects/Vala">Vala
homepage</ulink> itself: <quote>Vala is a new programming language
that aims to bring modern programming language features to GNOME
developers without imposing any additional runtime requirements
and without using a different ABI compared to applications and
libraries written in C.</quote>
</para>
<para>
The syntax of Vala is similar to C#. The available compiler
translates Vala into GObject C code. It can also compile
non-GObject C, using plain C API.
</para>
</chapter>
<chapter id="tools-gob">
<title>GObject builder</title>
<para>
In order to help a GObject class developer, one obvious idea is
to use some sort of templates for the skeletons and then run
them through a special tool to generate the real C files. <ulink
url="http://www.5z.com/jirka/gob.html">GOB</ulink> (or GOB2) is
such a tool. It is a preprocessor which can be used to build
GObjects with inline C code so that there is no need to edit the
generated C code. The syntax is inspired by Java and Yacc or
Lex. The implementation is intentionally kept simple: the inline C
code provided by the user is not parsed.
</para>
</chapter>
<chapter id="tools-ginspector">
<title>Graphical inspection of GObjects</title>
<para>
Yet another tool that you may find helpful when working with
GObjects is <ulink
url="http://sourceforge.net/projects/g-inspector">G-Inspector</ulink>. It
is able to display GLib/GTK+ objects and their properties.
</para>
</chapter>
<chapter id="tools-refdb">
<title>Debugging reference count problems</title>
<para>
The reference counting scheme used by GObject does solve quite
a few memory management problems but also introduces new sources of bugs.
In large applications, finding the exact spot where the reference count
of an Object is not properly handled can be very difficult.
</para>
<para>
A useful tool in debugging reference counting problems is to
set breakpoints in gdb on g_object_ref() and g_object_unref().
Once you know the address of the object you are interested in,
you can make the breakpoints conditional:
<programlisting>
break g_object_ref if _object == 0xcafebabe
break g_object_unref if _object == 0xcafebabe
</programlisting>
</para>
</chapter>
<chapter id="tools-gtkdoc">
<title>Writing API docs</title>
<para>The API documentation for most of the GLib, GObject, GTK+ and GNOME
libraries is built with a combination of complex tools. Typically, the part of
the documentation which describes the behavior of each function is extracted
from the specially-formatted source code comments by a tool named gtk-doc which
generates DocBook XML and merges this DocBook XML with a set of template XML
DocBook files. These XML DocBook files are finally processed with xsltproc
(a small program part of the libxslt library) to generate the final HTML
output. Other tools can be used to generate PDF output from the source XML.
The following code excerpt shows what these comments look like.
<informalexample><programlisting>
/**
* gtk_widget_freeze_child_notify:
* @widget: a #GtkWidget
*
* Stops emission of "child-notify" signals on @widget. The signals are
* queued until gtk_widget_thaw_child_notify() is called on @widget.
*
* This is the analogue of g_object_freeze_notify() for child properties.
**/
void
gtk_widget_freeze_child_notify (GtkWidget *widget)
{
...
</programlisting></informalexample>
</para>
<para>
Thorough
<ulink url="https://developer.gnome.org/gtk-doc-manual/stable/">documentation</ulink>
on how to set up and use gtk-doc in your project is provided on the
<ulink url="https://developer.gnome.org/">GNOME developer website</ulink>.
</para>
</chapter>
</part>

View file

@ -0,0 +1 @@
@GLIB_VERSION@

View file

@ -0,0 +1,8 @@
<!ENTITY package "@PACKAGE@">
<!ENTITY package_bugreport "@PACKAGE_BUGREPORT@">
<!ENTITY package_name "@PACKAGE_NAME@">
<!ENTITY package_string "@PACKAGE_STRING@">
<!ENTITY package_tarname "@PACKAGE_TARNAME@">
<!ENTITY package_url "@PACKAGE_URL@">
<!ENTITY package_version "@PACKAGE_VERSION@">
<!ENTITY package_api_version "@PACKAGE_API_VERSION@">

View file

@ -0,0 +1,14 @@
ent_conf = configuration_data()
ent_conf.set('PACKAGE', 'glib')
ent_conf.set('PACKAGE_BUGREPORT', 'https://gitlab.gnome.org/GNOME/glib/issues/new')
ent_conf.set('PACKAGE_NAME', 'glib')
ent_conf.set('PACKAGE_STRING', 'glib')
ent_conf.set('PACKAGE_TARNAME', 'glib')
ent_conf.set('PACKAGE_URL', 'FIXME')
ent_conf.set('PACKAGE_VERSION', glib_version)
ent_conf.set('PACKAGE_API_VERSION', glib_api_version)
configure_file(
input: 'gtkdocentities.ent.in',
output: 'gtkdocentities.ent',
configuration: ent_conf
)