Import Upstream version 2.72.4
This commit is contained in:
commit
4ef3ff9793
2003 changed files with 1332420 additions and 0 deletions
579
docs/reference/gobject/glib-genmarshal.xml
Normal file
579
docs/reference/gobject/glib-genmarshal.xml
Normal 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=$@ \
|
||||
$<
|
||||
|
||||
marshal.c: marshal.list marshal.h
|
||||
$(AM_V_GEN)$(GLIB_GENMARSHAL) \
|
||||
--include-header=marshal.h \
|
||||
--body \
|
||||
--output=$@ \
|
||||
$<
|
||||
|
||||
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>
|
||||
653
docs/reference/gobject/glib-mkenums.xml
Normal file
653
docs/reference/gobject/glib-mkenums.xml
Normal 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 << 3,
|
||||
PREFIX_ANOTHER_VALUE = 1 << 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>/*<</literal>
|
||||
and end with the trigraph sequence <literal>>*/</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>/*< underscore_name=gnome_vfs_uri_hide_options >*/</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 /*< skip >*/
|
||||
{
|
||||
PREFIX_FOO
|
||||
} PrefixThisEnumWillBeSkipped;
|
||||
typedef enum /*< flags,prefix=PREFIX,since=1.0 >*/
|
||||
{
|
||||
PREFIX_THE_ZEROTH_VALUE, /*< skip >*/
|
||||
PREFIX_THE_FIRST_VALUE,
|
||||
PREFIX_THE_SECOND_VALUE,
|
||||
PREFIX_THE_THIRD_VALUE, /*< nick=the-last-value >*/
|
||||
} 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 (&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 (&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>
|
||||
224
docs/reference/gobject/gobject-docs.xml
Normal file
224
docs/reference/gobject/gobject-docs.xml
Normal 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>
|
||||
0
docs/reference/gobject/gobject-overrides.txt
Normal file
0
docs/reference/gobject/gobject-overrides.txt
Normal file
123
docs/reference/gobject/gobject-query.xml
Normal file
123
docs/reference/gobject/gobject-query.xml
Normal 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>
|
||||
1048
docs/reference/gobject/gobject-sections.txt
Normal file
1048
docs/reference/gobject/gobject-sections.txt
Normal file
File diff suppressed because it is too large
Load diff
BIN
docs/reference/gobject/images/glue.png
Normal file
BIN
docs/reference/gobject/images/glue.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
68
docs/reference/gobject/meson.build
Normal file
68
docs/reference/gobject/meson.build
Normal 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
|
||||
728
docs/reference/gobject/tut_gobject.xml
Normal file
728
docs/reference/gobject/tut_gobject.xml
Normal 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)->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)->finalize (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
viewer_file_class_init (ViewerFileClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = viewer_file_constructed;
|
||||
object_class->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 parent’s 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->filename);
|
||||
self->filename = g_value_dup_string (value);
|
||||
g_print ("filename: %s\n", self->filename);
|
||||
break;
|
||||
|
||||
case PROP_ZOOM_LEVEL:
|
||||
self->zoom_level = g_value_get_uint (value);
|
||||
g_print ("zoom level: %u\n", self->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->filename);
|
||||
break;
|
||||
|
||||
case PROP_ZOOM_LEVEL:
|
||||
g_value_set_uint (value, self->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->set_property = viewer_file_set_property;
|
||||
object_class->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 (&val, G_TYPE_UINT);
|
||||
g_value_set_char (&val, 11);
|
||||
|
||||
g_object_set_property (G_OBJECT (file), "zoom-level", &val);
|
||||
|
||||
g_value_unset (&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>
|
||||
495
docs/reference/gobject/tut_gsignal.xml
Normal file
495
docs/reference/gobject/tut_gsignal.xml
Normal 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>
|
||||
|
||||
1003
docs/reference/gobject/tut_gtype.xml
Normal file
1003
docs/reference/gobject/tut_gtype.xml
Normal file
File diff suppressed because it is too large
Load diff
1535
docs/reference/gobject/tut_howto.xml
Normal file
1535
docs/reference/gobject/tut_howto.xml
Normal file
File diff suppressed because it is too large
Load diff
185
docs/reference/gobject/tut_intro.xml
Normal file
185
docs/reference/gobject/tut_intro.xml
Normal 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 <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>
|
||||
125
docs/reference/gobject/tut_tools.xml
Normal file
125
docs/reference/gobject/tut_tools.xml
Normal 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>
|
||||
1
docs/reference/gobject/version.xml.in
Normal file
1
docs/reference/gobject/version.xml.in
Normal file
|
|
@ -0,0 +1 @@
|
|||
@GLIB_VERSION@
|
||||
8
docs/reference/gobject/xml/gtkdocentities.ent.in
Normal file
8
docs/reference/gobject/xml/gtkdocentities.ent.in
Normal 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@">
|
||||
14
docs/reference/gobject/xml/meson.build
Normal file
14
docs/reference/gobject/xml/meson.build
Normal 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
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue