Merge branch 'migrate-to-gi-docgen' into 'main'

Switch to using gi-docgen for docs (batch 1)

See merge request GNOME/glib!3591
This commit is contained in:
Philip Withnall 2023-10-11 15:21:10 +00:00
commit c140f83922
90 changed files with 261566 additions and 10764 deletions

View File

@ -11,10 +11,10 @@ cache:
- _ccache/
variables:
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/glib/fedora:v20"
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/glib/fedora:v21"
COVERITY_IMAGE: "registry.gitlab.gnome.org/gnome/glib/coverity:v7"
DEBIAN_IMAGE: "registry.gitlab.gnome.org/gnome/glib/debian-stable:v14"
MINGW_IMAGE: "registry.gitlab.gnome.org/gnome/glib/mingw:v10"
DEBIAN_IMAGE: "registry.gitlab.gnome.org/gnome/glib/debian-stable:v15"
MINGW_IMAGE: "registry.gitlab.gnome.org/gnome/glib/mingw:v11"
MESON_TEST_TIMEOUT_MULTIPLIER: 4
G_MESSAGES_DEBUG: all
MESON_COMMON_OPTIONS: "--buildtype debug --wrap-mode=nodownload --fatal-meson-warnings"
@ -61,6 +61,7 @@ variables:
extends: .only-default
before_script:
- rm -rf subprojects/gvdb
- git config --global --add safe.directory $(pwd)
- git submodule update --init --depth 1
variables:
GIT_SUBMODULE_STRATEGY: "none"

View File

@ -1,4 +1,4 @@
FROM debian:bullseye
FROM debian:bookworm
RUN apt-get update -qq && apt-get install --no-install-recommends -qq -y \
bindfs \
@ -16,6 +16,7 @@ RUN apt-get update -qq && apt-get install --no-install-recommends -qq -y \
gdb \
g++ \
gettext \
gi-docgen \
git \
libc6-dev \
gtk-doc-tools \
@ -37,6 +38,7 @@ RUN apt-get update -qq && apt-get install --no-install-recommends -qq -y \
python3-pip \
python3-setuptools \
python3-wheel \
reuse \
shared-mime-info \
shellcheck \
systemtap-sdt-dev \
@ -66,10 +68,7 @@ RUN locale-gen de_DE.UTF-8 \
ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8
RUN pip3 install meson==0.60.3
# FIXME: Once we use Debian Bookworm, we can just install the `reuse` package
RUN pip3 install reuse==1.0.0
RUN pip3 install --break-system-packages meson==0.60.3
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}

View File

@ -1,4 +1,4 @@
FROM fedora:34
FROM fedora:37
RUN dnf -y update \
&& dnf -y install \
@ -15,6 +15,7 @@ RUN dnf -y update \
gcc-c++ \
gdb \
gettext \
gi-docgen \
git \
glibc-devel \
glibc-headers \

View File

@ -1,72 +1,17 @@
FROM fedora:34
FROM registry.gitlab.gnome.org/gnome/glib/fedora:v21
USER root
RUN dnf -y install \
bindfs \
clang \
clang-analyzer \
desktop-file-utils \
elfutils-libelf-devel \
findutils \
fuse \
gcc \
gcc-c++ \
gettext \
git \
glibc-devel \
glibc-headers \
glibc-langpack-de \
glibc-langpack-el \
glibc-langpack-el \
glibc-langpack-en \
glibc-langpack-es \
glibc-langpack-es \
glibc-langpack-fa \
glibc-langpack-fr \
glibc-langpack-hr \
glibc-langpack-ja \
glibc-langpack-lt \
glibc-langpack-pl \
glibc-langpack-ru \
glibc-langpack-tr \
gtk-doc \
itstool \
lcov \
libattr-devel \
libffi-devel \
libmount-devel \
libselinux-devel \
libxslt \
mingw64-gcc \
mingw64-gcc-c++ \
mingw64-gettext \
mingw64-libffi \
mingw64-zlib \
ncurses-compat-libs \
ninja-build \
pcre2-devel \
python3 \
python3-pip \
python3-wheel \
systemtap-sdt-devel \
unzip \
wget \
xz \
zlib-devel \
&& dnf clean all
WORKDIR /opt
COPY cross_file_mingw64.txt /opt
RUN pip3 install meson==0.60.3
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
RUN useradd -u $HOST_USER_ID -ms /bin/bash user
USER user
WORKDIR /home/user
COPY cache-subprojects.sh .
RUN ./cache-subprojects.sh
ENV LANG C.UTF-8
WORKDIR /home/user

136814
docs/reference/gio/Gio-2.0.gir Normal file

File diff suppressed because it is too large Load Diff

View File

@ -15,8 +15,6 @@
</releaseinfo>
</bookinfo>
<xi:include href="xml/overview.xml"/>
<part>
<title>API Reference</title>
<chapter id="file_ops">
@ -270,9 +268,6 @@
<part id="migrating">
<title>Migrating to GIO</title>
<xi:include href="xml/migrating-posix.xml"/>
<xi:include href="xml/migrating-gnome-vfs.xml"/>
<xi:include href="xml/migrating-gconf.xml"/>
<xi:include href="xml/migrating-gdbus.xml"/>
</part>
<chapter id="gio-hierarchy">

View File

@ -0,0 +1,53 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# Copyright 2023 Matthias Clasen
# Copyright 2023 Philip Withnall
[library]
name = "Gio"
version = "@VERSION@"
browse_url = "https://gitlab.gnome.org/GNOME/glib/"
repository_url = "https://gitlab.gnome.org/GNOME/glib.git"
website_url = "https://www.gtk.org"
docs_urls = "https://docs.gtk.org/gio/"
authors = "GLib Development Team"
license = "LGPL-2.1-or-later"
description = "Gio is a library providing useful classes for general purpose I/O, networking, IPC, settings, and other high level application functionality"
dependencies = [ "GLib-2.0", "GModule-2.0", "GObject-2.0" ]
devhelp = true
search_index = true
[dependencies."GLib-2.0"]
name = "GLib"
description = "The base utility library"
docs_url = "https://docs.gtk.org/glib/"
[dependencies."GModule-2.0"]
name = "GModule"
description = "Portable API for dynamically loading modules"
docs_url = "https://docs.gtk.org/gmodule/"
[dependencies."GObject-2.0"]
name = "GObject"
description = "The base type system library"
docs_url = "https://docs.gtk.org/gobject/"
[theme]
name = "basic"
show_index_summary = true
show_class_hierarchy = true
[extra]
urlmap_file = "urlmap.js"
# The same order will be used when generating the index
content_files = [
"overview.md",
"migrating-gdbus.md",
"migrating-gconf.md",
"migrating-gnome-vfs.md",
]
content_images = [
"gvfs-overview.png",
"menu-example.png",
"menu-model.png",
]

View File

@ -161,11 +161,7 @@ if get_option('gtk_doc')
)
content_files = [
'overview.xml',
'migrating-posix.xml',
'migrating-gnome-vfs.xml',
'migrating-gconf.xml',
'migrating-gdbus.xml',
'gio-querymodules.xml',
'glib-compile-schemas.xml',
'glib-compile-resources.xml',
@ -198,11 +194,7 @@ if get_option('gtk_doc')
],
content_files : content_files,
expand_content_files : [
'overview.xml',
'migrating-posix.xml',
'migrating-gnome-vfs.xml',
'migrating-gconf.xml',
'migrating-gdbus.xml',
'gdbus-codegen.xml',
],
html_assets : [
@ -216,7 +208,7 @@ if get_option('gtk_doc')
'--extra-dir=' + join_paths('gio', '..', 'gobject', 'html'),
],
install: true,
check: true,
check: false,
)
endif
@ -234,3 +226,32 @@ if get_option('man')
install_dir: man1_dir)
endforeach
endif
# gi-docgen version
expand_content_files = [
'migrating-gconf.md',
'migrating-gdbus.md',
'migrating-gnome-vfs.md',
'overview.md',
]
gio_gir = meson.current_source_dir() / 'Gio-2.0.gir'
gio_toml = configure_file(input: 'gio.toml.in', output: 'gio.toml', configuration: toml_conf)
custom_target('gio-docs',
input: [ gio_toml, gio_gir ],
output: 'gio',
command: [
gidocgen,
'generate',
gidocgen_common_args,
'--config=@INPUT0@',
'--output-dir=@OUTPUT@',
'--content-dir=@0@'.format(meson.current_source_dir()),
'--add-include-path=@0@'.format(meson.current_source_dir() / '../glib'),
'--add-include-path=@0@'.format(meson.current_source_dir() / '../gobject'),
'@INPUT1@',
],
build_by_default: true,
depend_files: expand_content_files,
)

View File

@ -0,0 +1,466 @@
Title: Migrating from GConf to GSettings
SPDX-License-Identifier: LGPL-2.1-or-later
SPDX-FileCopyrightText: 2010, 2012 Matthias Clasen
SPDX-FileCopyrightText: 2010 Allison Lortie
SPDX-FileCopyrightText: 2011 Ray Strode
# Migrating from GConf to GSettings
## Before you start
Converting individual applications and their settings from GConf to
GSettings can be done at will. But desktop-wide settings like font or theme
settings often have consumers in multiple modules. Therefore, some
consideration has to go into making sure that all users of a setting are
converted to GSettings at the same time or that the program responsible for
configuring that setting continues to update the value in both places.
It is always a good idea to have a look at how others have handled similar
problems before.
## Conceptual differences
Conceptually, GConf and GSettings are fairly similar. Both have a concept of
pluggable backends. Both keep information about keys and their types in
schemas. Both have a concept of mandatory values, which lets you implement
lock-down.
There are some differences in the approach to schemas. GConf installs the
schemas into the database and has API to handle schema information
(`gconf_client_get_default_from_schema()`, `gconf_value_get_schema()`, etc).
GSettings on the other hand assumes that an application knows its own
schemas, and does not provide API to handle schema information at runtime.
GSettings is also more strict about requiring a schema whenever you want to
read or write a key. To deal with more free-form information that would
appear in schema-less entries in GConf, GSettings allows for schemas to be
'relocatable'.
One difference in the way applications interact with their settings is that
with GConf you interact with a tree of settings (ie the keys you pass to
functions when reading or writing values are actually paths with the actual
name of the key as the last element. With GSettings, you create a GSettings
object which has an implicit prefix that determines where the settings get
stored in the global tree of settings, but the keys you pass when reading or
writing values are just the key names, not the full path.
## GConfClient (and GConfBridge) API conversion
Most people use GConf via the high-level `GConfClient` API. The
corresponding API is the [class@Gio.Settings] object. While not every
`GConfClient` function has a direct GSettings equivalent, many do:
| GConfClient | GSettings |
|-------------|-----------|
| `gconf_client_get_default()` | no direct equivalent, instead you call [`ctor@Gio.Settings.new`] for the schemas you use |
| `gconf_client_set()` | [`method@Gio.Settings.set`] |
| `gconf_client_get()` | `g_settings_get()` |
| `gconf_client_get_bool()` | `g_settings_get_boolean()` |
| `gconf_client_set_bool()` | `g_settings_set_boolean()` |
| `gconf_client_get_int()` | `g_settings_get_int()` |
| `gconf_client_set_int()` | `g_settings_set_int()` |
| `gconf_client_get_float()` | `g_settings_get_double()` |
| `gconf_client_set_float()` | `g_settings_set_double()` |
| `gconf_client_get_string()` | `g_settings_get_string()` |
| `gconf_client_set_string()` | `g_settings_set_string()` |
| `gconf_client_get_list()` | for string lists, see `g_settings_get_strv()`, else see `g_settings_get_value()` and GVariant API |
| `gconf_client_set_list()` | for string lists, see `g_settings_set_strv()`, else see `g_settings_set_value()` and GVariant API |
| `gconf_entry_get_is_writable()` | `g_settings_is_writable()` |
| `gconf_client_notify_add()` | not required, the “changed” signal is emitted automatically |
| `gconf_client_add_dir()` | not required, each GSettings instance automatically watches all keys in its path |
| `GConfChangeSet` | `g_settings_delay()`, `g_settings_apply()` |
| `gconf_client_get_default_from_schema()` | no equivalent, applications are expected to know their schema |
| `gconf_client_all_entries()` | no equivalent, applications are expected to know their schema, and GSettings does not allow schema-less entries |
| `gconf_client_get_without_default()` | no equivalent |
| `gconf_bridge_bind_property()` | `g_settings_bind()` |
| `gconf_bridge_bind_property_full()` | `g_settings_bind_with_mapping()` |
GConfBridge was a third-party library that used GConf to bind an object
property to a particular configuration key. GSettings offers this service
itself.
There is a pattern that is sometimes used for GConf, where a setting can
have explicit 'value A', explicit 'value B' or 'use the system default'.
With GConf, 'use the system default' is sometimes implemented by unsetting
the user value. This is not possible in GSettings, since it does not have
API to determine if a value is the default and does not let you unset
values. The recommended way (and much clearer) way in which this can be
implemented in GSettings is to have a separate 'use-system-default' boolean
setting.
## Change notification
GConf requires you to call `gconf_client_add_dir()` and
`gconf_client_notify_add()` to get change notification. With GSettings, this
is not necessary; signals get emitted automatically for every change.
The [signal@Gio.Settings::changed] signal is emitted for each changed key.
There is also a [`signal@Gio.Settings::change-event`] signal that you can
handle if you need to see groups of keys that get changed at the same time.
GSettings also notifies you about changes in writability of keys, with the
[signal@Gio.Settings::writable-changed] signal (and the
[signal@Gio.Settings::writable-change-event] signal).
## Change sets
GConf has a concept of a set of changes which can be applied or reverted at
once: `GConfChangeSet` (GConf doesn't actually apply changes atomically,
which is one of its shortcomings).
Instead of a separate object to represent a change set, GSettings has a
'delayed-apply' mode, which can be turned on for a [class@Gio.Settings]
object by calling [method@Gio.Settings.delay]. In this mode, changes done to
the GSettings object are not applied - they are still visible when calling
[method@Gio.Settings.get] on the same object, but not to other GSettings
instances or even other processes.
To apply the pending changes all at once (GSettings does atomicity here),
call [method@Gio.Settings.apply]. To revert the pending changes, call
[method@Gio.Settings.revert] or just drop the reference to the GSettings
object.
## Schema conversion
If you are porting your application from GConf, most likely you already have
a GConf schema. GConf comes with a commandline tool
`gsettings-schema-convert` that can help with the task of converting a GConf
schema into an equivalent GSettings schema. The tool is not perfect and may
need assistance in some cases.
### An example for using gsettings-schema-convert
Running `gsettings-schema-convert --gconf --xml --schema-id
"org.gnome.font-rendering" --output org.gnome.font-rendering.gschema.xml
destop_gnome_font_rendering.schemas` on the following
`desktop_gnome_font_rendering.schemas` file:
```xml
<?xml version="1.0"?>
<gconfschemafile>
<schemalist>
<schema>
<key>/schemas/desktop/gnome/font_rendering/dpi</key>
<applyto>/desktop/gnome/font_rendering/dpi</applyto>
<owner>gnome</owner>
<type>int</type>
<default>96</default>
<locale name="C">
<short>DPI</short>
<long>The resolution used for converting font sizes to pixel sizes, in dots per inch.</long>
</locale>
</schema>
</schemalist>
</gconfschemafile>
```
produces an `org.gnome.font-rendering.gschema.xml` file with the following content:
```xml
<schemalist>
<schema id="org.gnome.font-rendering" path="/desktop/gnome/font_rendering/">
<key name="dpi" type="i">
<default>96</default>
<summary>DPI</summary>
<description>The resolution used for converting font sizes to pixel sizes, in dots per inch.</description>
</key>
</schema>
</schemalist>
```
GSettings schemas are identified at runtime by their id (as specified in the
XML source file). It is recommended to use a dotted name as schema id,
similar in style to a D-Bus bus name, e.g. "org.gnome.SessionManager". In
cases where the settings are general and not specific to one application,
the id should not use StudlyCaps, e.g. "org.gnome.font-rendering". The
filename used for the XML schema source is immaterial, but schema compiler
expects the files to have the extension `.gschema.xml`. It is recommended to
simply use the schema id as the filename, followed by this extension, e.g.
`org.gnome.SessionManager.gschema.xml`.
The XML source file for your GSettings schema needs to get installed into
`$datadir/glib-2.0/schemas`, and needs to be compiled into a binary form. At
runtime, GSettings looks for compiled schemas in the `glib-2.0/schemas`
subdirectories of all `XDG_DATA_DIRS` directories, so if you install your
schema in a different location, you need to set the `XDG_DATA_DIRS`
environment variable appropriately.
Schemas are compiled into binary form by the `glib-compile-schemas` utility.
GIO provides a `glib_compile_schemas` variable in its pkg-config file
pointing to the schema compiler binary.
### Using schemas with Meson
You should use `install_data()` to install the `.gschema.xml` file in the
correct directory, e.g.
```
install_data('my.app.gschema.xml', install_dir: get_option('datadir') / 'glib-2.0/schemas')
```
Schema compilation is done at installation time; if you are using Meson 0.57 or newer, you can use the `gnome.post_install()` function from the GNOME module:
```
gnome.post_install(glib_compile_schemas: true)
```
Alternatively, you can use `meson.add_install_script()` and the following
Python script:
```py
#!/usr/bin/env python3
# build-aux/compile-schemas.py
import os
import subprocess
install_prefix = os.environ['MESON_INSTALL_PREFIX']
schemadir = os.path.join(install_prefix, 'share', 'glib-2.0', 'schemas')
if not os.environ.get('DESTDIR'):
print('Compiling gsettings schemas...')
subprocess.call(['glib-compile-schemas', schemadir])
```
```
meson.add_install_script('build-aux/compile-schemas.py')
```
### Using schemas with Autotools
GLib provides m4 macros for hiding the various complexities and reduce the
chances of getting things wrong.
To handle schemas in your Autotools build, start by adding this to your
`configure.ac`:
```
GLIB_GSETTINGS
```
Then add this fragment to your `Makefile.am`:
```
# gsettings_SCHEMAS is a list of all the schemas you want to install
gsettings_SCHEMAS = my.app.gschema.xml
# include the appropriate makefile rules for schema handling
@GSETTINGS_RULES@
```
This is not sufficient on its own. You need to mention what the source of
the `my.app.gschema.xml` file is. If the schema file is distributed directly
with your project's tarball then a mention in `EXTRA_DIST` is appropriate. If
the schema file is generated from another source then you will need the
appropriate rule for that, plus probably an item in `EXTRA_DIST` for the
source files used by that rule.
One possible pitfall in doing schema conversion is that the default values
in GSettings schemas are parsed by the GVariant parser. This means that
strings need to include quotes in the XML. Also note that the types are now
specified as GVariant type strings.
```xml
<type>string</type>
<default>rgb</default>
```
becomes
```xml
<key name="rgba-order" type="s">
<default>'rgb'</default> <!-- note quotes -->
</key>
```
Another possible complication is that GConf specifies full paths for each
key, while a GSettings schema has a 'path' attribute that contains the
prefix for all the keys in the schema, and individual keys just have a
simple name. So
```xml
<key>/schemas/desktop/gnome/font_rendering/antialiasing</key>
```
becomes
```xml
<schema id="org.gnome.font" path="/desktop/gnome/font_rendering/">
<key name="antialiasing" type="s">
```
Default values can be localized in both GConf and GSettings schemas, but
GSettings uses gettext for the localization. You can specify the gettext
domain to use in the gettext-domain attribute. Therefore, when converting
localized defaults in GConf,
```xml
<key>/schemas/apps/my_app/font_size</key>
<locale name="C">
<default>18</default>
</locale>
<locale name="be">
<default>24</default>
</locale>
</key>
```
becomes
```xml
<schema id="..." gettext-domain="your-domain">
...
<key name="font-size" type="i">
<default l10n="messages" context="font_size">18</default>
</key>
```
GSettings uses gettext for translation of default values. The string that is
translated is exactly the string that appears inside of the `<default>`
element. This includes the quotation marks that appear around strings.
Default values must be marked with the l10n attribute in the `<default>` tag,
which should be set as equal to 'messages' or 'time' depending on the
desired category. An optional translation context can also be specified with
the context attribute, as in the example. This is usually recommended, since
the string "18" is not particularly easy to translate without context. The
translated version of the default value should be stored in the specified
gettext-domain. Care must be taken during translation to ensure that all
translated values remain syntactically valid; mistakes here will cause
runtime errors.
GSettings schemas have optional `<summary>` and `<description>` elements for
each key which correspond to the `<short>` and `<long>` elements in the
GConf schema and can be used in the same way by a GUI editor, so you should
use the same conventions for them: The summary is just a short label with no
punctuation, the description can be one or more complete sentences. If
multiple paragraphs are desired for the description, the paragraphs should
be separated by a completely empty line.
Translations for these strings will also be handled via gettext, so you
should arrange for these strings to be extracted into your gettext catalog.
Gettext supports GSettings schemas natively since version 0.19, so all you
have to do is add the XML schema file to the list of translatable files
inside your `POTFILES.in`.
GSettings is a bit more restrictive about key names than GConf. Key names in
GSettings can be at most 32 characters long, and must only consist of
lowercase characters, numbers and dashes, with no consecutive dashes. The
first character must not be a number or dash, and the last character cannot
be '-'.
If you are using the GConf backend for GSettings during the transition, you
may want to keep your key names the same they were in GConf, so that
existing settings in the users GConf database are preserved. You can achieve
this by using the `--allow-any-name` with the `glib-compile-schemas` schema
compiler. Note that this option is only meant to ease the process of porting
your application, allowing parts of your application to continue to access
GConf and parts to use GSettings. By the time you have finished porting your
application you must ensure that all key names are valid.
## Data conversion
GConf comes with a GSettings backend that can be used to facility the
transition to the GSettings API until you are ready to make the jump to a
different backend (most likely dconf). To use it, you need to set the
`GSETTINGS_BACKEND` to 'gconf', e.g. by using
```c
g_setenv ("GSETTINGS_BACKEND", "gconf", TRUE);
```
early on in your program. Note that this backend is meant purely as a
transition tool, and should not be used in production.
GConf also comes with a utility called `gsettings-data-convert`, which is
designed to help with the task of migrating user settings from GConf into
another GSettings backend. It can be run manually, but it is designed to be
executed automatically, every time a user logs in. It keeps track of the
data migrations that it has already done, and it is harmless to run it more
than once.
To make use of this utility, you must install a keyfile in the directory
`/usr/share/GConf/gsettings` which lists the GSettings keys and GConf paths
to map to each other, for each schema that you want to migrate user data
for.
Here is an example:
```
[org.gnome.fonts]
antialiasing = /desktop/gnome/font_rendering/antialiasing
dpi = /desktop/gnome/font_rendering/dpi
hinting = /desktop/gnome/font_rendering/hinting
rgba-order = /desktop/gnome/font_rendering/rgba_order
[apps.myapp:/path/to/myapps/]
some-odd-key1 = /apps/myapp/some_ODD-key1
```
The last key demonstrates that it may be necessary to modify the key name to
comply with stricter GSettings key name rules. Of course, that means your
application must use the new key names when looking up settings in
GSettings.
The last group in the example also shows how to handle the case of
'relocatable' schemas, which don't have a fixed path. You can specify the
path to use in the group name, separated by a colon.
There are some limitations: `gsettings-data-convert` does not do any
transformation of the values. And it does not handle complex GConf types
other than lists of strings or integers.
**Don't forget to require GConf 2.31.1 or newer in your configure script if
you are making use of the GConf backend or the conversion utility.**
If, as an application developer, you are interested in manually ensuring
that `gsettings-data-convert` has been invoked (for example, to deal with the
case where the user is logged in during a distribution upgrade or for
non-XDG desktop environments which do not run the command as an autostart)
you may invoke it manually during your program initialisation. This is not
recommended for all application authors -- it is your choice if this use
case concerns you enough.
Internally, `gsettings-data-convert` uses a keyfile to track which settings
have been migrated. The following code fragment will check that keyfile to
see if your data conversion script has been run yet and, if not, will
attempt to invoke the tool to run it. You should adapt it to your
application as you see fit.
```c
static void
ensure_migrated (const gchar *name)
{
gboolean needed = TRUE;
GKeyFile *kf;
gchar **list;
gsize i, n;
kf = g_key_file_new ();
g_key_file_load_from_data_dirs (kf, "gsettings-data-convert",
NULL, G_KEY_FILE_NONE, NULL);
list = g_key_file_get_string_list (kf, "State", "converted", &n, NULL);
if (list)
{
for (i = 0; i < n; i++)
if (strcmp (list[i], name) == 0)
{
needed = FALSE;
break;
}
g_strfreev (list);
}
g_key_file_free (kf);
if (needed)
g_spawn_command_line_sync ("gsettings-data-convert",
NULL, NULL, NULL, NULL);
}
```
Although there is the possibility that the `gsettings-data-convert` script
will end up running multiple times concurrently with this approach, it is
believed that this is safe.

View File

@ -1,515 +0,0 @@
<chapter>
<title>Migrating from GConf to GSettings</title>
<section>
<title>Before you start</title>
<para>
Converting individual applications and their settings from GConf to
GSettings can be done at will. But desktop-wide settings like font or
theme settings often have consumers in multiple modules. Therefore,
some consideration has to go into making sure that all users of a setting
are converted to GSettings at the same time or that the program
responsible for configuring that setting continues to update the value in
both places.
</para>
<para>
It is always a good idea to have a look at how others have handled
similar problems before.
</para>
</section>
<section>
<title>Conceptual differences</title>
<para>
Conceptually, GConf and GSettings are fairly similar. Both
have a concept of pluggable backends. Both keep information
about keys and their types in schemas. Both have a concept of
mandatory values, which lets you implement lock-down.
</para>
<para>
There are some differences in the approach to schemas. GConf
installs the schemas into the database and has API to handle
schema information (gconf_client_get_default_from_schema(),
gconf_value_get_schema(), etc). GSettings on the other hand
assumes that an application knows its own schemas, and does
not provide API to handle schema information at runtime.
GSettings is also more strict about requiring a schema whenever
you want to read or write a key. To deal with more free-form
information that would appear in schema-less entries in GConf,
GSettings allows for schemas to be 'relocatable'.
</para>
<para>
One difference in the way applications interact with their
settings is that with GConf you interact with a tree of
settings (ie the keys you pass to functions when reading
or writing values are actually paths with the actual name
of the key as the last element. With GSettings, you create
a GSettings object which has an implicit prefix that determines
where the settings get stored in the global tree of settings,
but the keys you pass when reading or writing values are just
the key names, not the full path.
</para>
</section>
<section>
<title>GConfClient (and GConfBridge) API conversion</title>
<para>
Most people use GConf via the high-level #GConfClient API.
The corresponding API is the #GSettings object. While not
every GConfClient function has a direct GSettings equivalent,
many do:
<table id="gconf-client-vs-gsettings">
<tgroup cols="2">
<thead>
<row><entry>GConfClient</entry><entry>GSettings</entry></row>
</thead>
<tbody>
<row><entry>gconf_client_get_default()</entry><entry>no direct equivalent,
instead you call g_settings_new() for the schemas you use</entry></row>
<row><entry>gconf_client_set()</entry><entry>g_settings_set()</entry></row>
<row><entry>gconf_client_get()</entry><entry>g_settings_get()</entry></row>
<row><entry>gconf_client_get_bool()</entry><entry>g_settings_get_boolean()</entry></row>
<row><entry>gconf_client_set_bool()</entry><entry>g_settings_set_boolean()</entry></row>
<row><entry>gconf_client_get_int()</entry><entry>g_settings_get_int()</entry></row>
<row><entry>gconf_client_set_int()</entry><entry>g_settings_set_int()</entry></row>
<row><entry>gconf_client_get_float()</entry><entry>g_settings_get_double()</entry></row>
<row><entry>gconf_client_set_float()</entry><entry>g_settings_set_double()</entry></row>
<row><entry>gconf_client_get_string()</entry><entry>g_settings_get_string()</entry></row>
<row><entry>gconf_client_set_string()</entry><entry>g_settings_set_string()</entry></row>
<row><entry>gconf_client_get_list()</entry><entry>for string lists, see g_settings_get_strv(), else see g_settings_get_value() and #GVariant API</entry></row>
<row><entry>gconf_client_set_list()</entry><entry>for string lists, see g_settings_set_strv(), else see g_settings_set_value() and #GVariant API</entry></row>
<row><entry>gconf_entry_get_is_writable()</entry><entry>g_settings_is_writable()</entry></row>
<row><entry>gconf_client_notify_add()</entry><entry>not required, the #GSettings::changed signal is emitted automatically</entry></row>
<row><entry>gconf_client_add_dir()</entry><entry>not required, each GSettings instance automatically watches all keys in its path</entry></row>
<row><entry>#GConfChangeSet</entry><entry>g_settings_delay(), g_settings_apply()</entry></row>
<row><entry>gconf_client_get_default_from_schema()</entry><entry>no equivalent, applications are expected to know their schema</entry></row>
<row><entry>gconf_client_all_entries()</entry><entry>no equivalent, applications are expected to know their schema, and GSettings does not allow schema-less entries</entry></row>
<row><entry>gconf_client_get_without_default()</entry><entry>no equivalent</entry></row>
<row><entry>gconf_bridge_bind_property()</entry><entry>g_settings_bind()</entry></row>
<row><entry>gconf_bridge_bind_property_full()</entry><entry>g_settings_bind_with_mapping()</entry></row>
</tbody>
</tgroup>
</table>
</para>
<para>
GConfBridge was a third-party library that used GConf to bind an object property
to a particular configuration key. GSettings offers this service itself.
</para>
<para>
There is a pattern that is sometimes used for GConf, where a setting can have
explicit 'value A', explicit 'value B' or 'use the system default'. With GConf,
'use the system default' is sometimes implemented by unsetting the user value.
</para>
<para>
This is not possible in GSettings, since it does not have API to determine if a value
is the default and does not let you unset values. The recommended way (and much
clearer) way in which this can be implemented in GSettings is to have a separate
'use-system-default' boolean setting.
</para>
</section>
<section>
<title>Change notification</title>
<para>
GConf requires you to call gconf_client_add_dir() and
gconf_client_notify_add() to get change notification. With
GSettings, this is not necessary; signals get emitted automatically
for every change.
</para>
<para>
The #GSettings::changed signal is emitted for each changed key.
There is also a #GSettings::change-event signal that you can handle
if you need to see groups of keys that get changed at the same time.
</para>
<para>
GSettings also notifies you about changes in writability of keys,
with the #GSettings::writable-changed signal (and the
#GSettings::writable-change-event signal).
</para>
</section>
<section><title>Change sets</title>
<para>
GConf has a concept of a set of changes which can be applied or reverted
at once: #GConfChangeSet (GConf doesn't actually apply changes atomically,
which is one of its shortcomings).
</para>
<para>
Instead of a separate object to represent a change set, GSettings has a
'delayed-apply' mode, which can be turned on for a GSettings object by
calling g_settings_delay(). In this mode, changes done to the GSettings
object are not applied - they are still visible when calling g_settings_get()
<emphasis>on the same object</emphasis>, but not to other GSettings instances
or even other processes.
</para>
<para>
To apply the pending changes all at once (GSettings <emphasis>does</emphasis>
atomicity here), call g_settings_apply(). To revert the pending changes,
call g_settings_revert() or just drop the reference to the #GSettings object.
</para>
</section>
<section>
<title>Schema conversion</title>
<para>
If you are porting your application from GConf, most likely you already
have a GConf schema. GConf comes with a commandline tool
gsettings-schema-convert that can help with the task of converting
a GConf schema into an equivalent GSettings schema. The tool is not
perfect and may need assistance in some cases.
</para>
<example><title>An example for using gsettings-schema-convert</title>
<para>Running <userinput>gsettings-schema-convert --gconf --xml --schema-id "org.gnome.font-rendering" --output org.gnome.font-rendering.gschema.xml destop_gnome_font_rendering.schemas</userinput> on the following <filename>desktop_gnome_font_rendering.schemas</filename> file:
<programlisting>
<![CDATA[
<?xml version="1.0"?>
<gconfschemafile>
<schemalist>
<schema>
<key>/schemas/desktop/gnome/font_rendering/dpi</key>
<applyto>/desktop/gnome/font_rendering/dpi</applyto>
<owner>gnome</owner>
<type>int</type>
<default>96</default>
<locale name="C">
<short>DPI</short>
<long>The resolution used for converting font sizes to pixel sizes, in dots per inch.</long>
</locale>
</schema>
</schemalist>
</gconfschemafile>
]]>
</programlisting>
produces a <filename>org.gnome.font-rendering.gschema.xml</filename> file with the following content:
<programlisting>
<![CDATA[
<schemalist>
<schema id="org.gnome.font-rendering" path="/desktop/gnome/font_rendering/">
<key name="dpi" type="i">
<default>96</default>
<summary>DPI</summary>
<description>The resolution used for converting font sizes to pixel sizes, in dots per inch.</description>
</key>
</schema>
</schemalist>
]]>
</programlisting>
</para>
</example>
<para>
GSettings schemas are identified at runtime by their id (as specified
in the XML source file). It is recommended to use a dotted name as schema
id, similar in style to a D-Bus bus name, e.g. "org.gnome.SessionManager".
In cases where the settings are general and not specific to one application,
the id should not use StudlyCaps, e.g. "org.gnome.font-rendering".
The filename used for the XML schema source is immaterial, but
schema compiler expects the files to have the extension
<filename>.gschema.xml</filename>. It is recommended to simply
use the schema id as the filename, followed by this extension,
e.g. <filename>org.gnome.SessionManager.gschema.xml</filename>.
</para>
<para>
The XML source file for your GSettings schema needs to get installed
into <filename>$datadir/glib-2.0/schemas</filename>, and needs to be
compiled into a binary form. At runtime, GSettings looks for compiled
schemas in the <filename>glib-2.0/schemas</filename> subdirectories
of all <envar>XDG_DATA_DIRS</envar> directories, so if you install
your schema in a different location, you need to set the
<envar>XDG_DATA_DIRS</envar> environment variable appropriately.
</para>
<para>
Schemas are compiled into binary form by the
<link linkend="glib-compile-schemas">glib-compile-schemas</link> utility.
GIO provides a <literal>glib_compile_schemas</literal>
variable for the schema compiler.
</para>
<para>
You can ignore all of this by using the provided m4 macros. To
do this, add to your <filename>configure.ac</filename>:
<programlisting>
GLIB_GSETTINGS
</programlisting>
The corresponding <filename>Makefile.am</filename> fragment looks like
this:
<programlisting>
# gsettings_SCHEMAS is a list of all the schemas you want to install
gsettings_SCHEMAS = my.app.gschema.xml
# include the appropriate makefile rules for schema handling
@GSETTINGS_RULES@
</programlisting>
</para>
<para>
This is not sufficient on its own. You need to mention what the source
of the <filename>my.app.gschema.xml</filename> file is. If the schema
file is distributed directly with your project's tarball then a mention
in <varname>EXTRA_DIST</varname> is appropriate. If the schema file is
generated from another source then you will need the appropriate rule
for that, plus probably an item in <varname>EXTRA_DIST</varname> for the
source files used by that rule.
</para>
<para>
One possible pitfall in doing schema conversion is that the default
values in GSettings schemas are parsed by the #GVariant parser.
This means that strings need to include quotes in the XML. Also note
that the types are now specified as #GVariant type strings.
<programlisting>
<![CDATA[
<type>string</type>
<default>rgb</default>
]]>
</programlisting>
becomes
<programlisting>
<![CDATA[
<key name="rgba-order" type="s">
<default>'rgb'</default> <!-- note quotes -->
</key>
]]>
</programlisting>
</para>
<para>
Another possible complication is that GConf specifies full paths
for each key, while a GSettings schema has a 'path' attribute that
contains the prefix for all the keys in the schema, and individual
keys just have a simple name. So
<programlisting>
<![CDATA[
<key>/schemas/desktop/gnome/font_rendering/antialiasing</key>
]]>
</programlisting>
becomes
<programlisting>
<![CDATA[
<schema id="org.gnome.font" path="/desktop/gnome/font_rendering/">
<key name="antialiasing" type="s">
]]>
</programlisting>
</para>
<para>
Default values can be localized in both GConf and GSettings schemas,
but GSettings uses gettext for the localization. You can specify
the gettext domain to use in the <tag class="attribute">gettext-domain</tag>
attribute. Therefore, when converting localized defaults in GConf,
<programlisting>
<![CDATA[
<key>/schemas/apps/my_app/font_size</key>
<locale name="C">
<default>18</default>
</locale>
<locale name="be">
<default>24</default>
</locale>
</key>
]]>
</programlisting>
becomes
<programlisting>
<![CDATA[
<schema id="..." gettext-domain="your-domain">
...
<key name="font-size" type="i">
<default l10n="messages" context="font_size">18</default>
</key>
]]>
</programlisting>
</para>
<para>
GSettings uses gettext for translation of default values.
The string that is translated is exactly the string that appears
inside of the <tag class='starttag'>default</tag> element. This
includes the quotation marks that appear around strings.
Default values must be marked with the <varname>l10n</varname>
attribute in the <tag class='starttag'>default</tag> tag, which
should be set as equal to <literal>'messages'</literal> or
<literal>'time'</literal> depending on the desired category. An
optional translation context can also be specified with the
<varname>context</varname> attribute, as in the example. This
is usually recommended, since the string "<literal>18</literal>"
is not particularly easy to translate without context. The
translated version of the default value should be stored in the
specified <varname>gettext-domain</varname>. Care must be taken
during translation to ensure that all translated values remain
syntactically valid; mistakes here will cause runtime errors.
</para>
<para>
GSettings schemas have optional <tag class="starttag">summary</tag> and
<tag class="starttag">description</tag> elements for each key which
correspond to the <tag class="starttag">short</tag> and
<tag class="starttag">long</tag> elements in the GConf schema and
will be used in similar ways by a future gsettings-editor, so you
should use the same conventions for them: The summary is just a short
label with no punctuation, the description can be one or more complete
sentences. If multiple paragraphs are desired for the description, the
paragraphs should be separated by a completely empty line.
</para>
<para>
Translations for these strings will also be handled
via gettext, so you should arrange for these strings to be
extracted into your gettext catalog. One way to do that is to use
intltool. Since intltool 0.50.1, schema files are
supported, so all you have to do is to add your .gschema.xml
files to <filename>POTFILES.in</filename> with a line like
<programlisting>
[type: gettext/gsettings]data/org.foo.MyApp.gschema.xml
</programlisting>
</para>
<para>
GSettings is a bit more restrictive about key names than GConf. Key
names in GSettings can be at most 32 characters long, and must only
consist of lowercase characters, numbers and dashes, with no
consecutive dashes. The first character must not be a number or dash,
and the last character cannot be '-'.
</para>
<para>
If you are using the GConf backend for GSettings during the
transition, you may want to keep your key names the same they
were in GConf, so that existing settings in the users GConf
database are preserved. You can achieve this by using the
<option>--allow-any-name</option> with the
<link linkend="glib-compile-schemas">glib-compile-schemas</link> schema
compiler. Note that this option is only meant
to ease the process of porting your application, allowing parts
of your application to continue to access GConf and parts to use
GSettings. By the time you have finished porting your application
you must ensure that all key names are valid.
</para>
</section>
<section><title>Data conversion</title>
<para>
GConf comes with a GSettings backend that can be used to
facility the transition to the GSettings API until you are
ready to make the jump to a different backend (most likely
dconf). To use it, you need to set the <envar>GSETTINGS_BACKEND</envar>
to 'gconf', e.g. by using
<programlisting>
g_setenv ("GSETTINGS_BACKEND", "gconf", TRUE);
</programlisting>
early on in your program. Note that this backend is meant purely
as a transition tool, and should not be used in production.
</para>
<para>
GConf also comes with a utility called
<command>gsettings-data-convert</command>, which is designed to help
with the task of migrating user settings from GConf into another
GSettings backend. It can be run manually, but it is designed to be
executed automatically, every time a user logs in. It keeps track of
the data migrations that it has already done, and it is harmless to
run it more than once.
</para>
<para>
To make use of this utility, you must install a keyfile in the
directory <filename>/usr/share/GConf/gsettings</filename> which
lists the GSettings keys and GConf paths to map to each other, for
each schema that you want to migrate user data for.
</para>
<para>
Here is an example:
<programlisting>
<![CDATA[
[org.gnome.fonts]
antialiasing = /desktop/gnome/font_rendering/antialiasing
dpi = /desktop/gnome/font_rendering/dpi
hinting = /desktop/gnome/font_rendering/hinting
rgba-order = /desktop/gnome/font_rendering/rgba_order
[apps.myapp:/path/to/myapps/]
some-odd-key1 = /apps/myapp/some_ODD-key1
]]>
</programlisting>
The last key demonstrates that it may be necessary to modify the key
name to comply with stricter GSettings key name rules. Of course,
that means your application must use the new key names when looking
up settings in GSettings.
</para>
<para>
The last group in the example also shows how to handle the case
of 'relocatable' schemas, which don't have a fixed path. You can
specify the path to use in the group name, separated by a colon.
</para>
<para>
There are some limitations: <command>gsettings-data-convert</command>
does not do any transformation of the values. And it does not handle
complex GConf types other than lists of strings or integers.
</para>
<para>
Don't forget to require GConf 2.31.1 or newer in your configure
script if you are making use of the GConf backend or the conversion
utility.
</para>
<para>
If, as an application developer, you are interested in manually
ensuring that <command>gsettings-data-convert</command> has been
invoked (for example, to deal with the case where the user is
logged in during a distribution upgrade or for non-XDG desktop
environments which do not run the command as an autostart) you
may invoke it manually during your program initialisation. This
is not recommended for all application authors -- it is your
choice if this use case concerns you enough.
</para>
<para>
Internally, <command>gsettings-data-convert</command> uses a
keyfile to track which settings have been migrated. The
following code fragment will check that keyfile to see if your
data conversion script has been run yet and, if not, will
attempt to invoke the tool to run it. You should adapt it to
your application as you see fit.
</para>
<para>
<programlisting>
<![CDATA[
static void
ensure_migrated (const gchar *name)
{
gboolean needed = TRUE;
GKeyFile *kf;
gchar **list;
gsize i, n;
kf = g_key_file_new ();
g_key_file_load_from_data_dirs (kf, "gsettings-data-convert",
NULL, G_KEY_FILE_NONE, NULL);
list = g_key_file_get_string_list (kf, "State", "converted", &n, NULL);
if (list)
{
for (i = 0; i < n; i++)
if (strcmp (list[i], name) == 0)
{
needed = FALSE;
break;
}
g_strfreev (list);
}
g_key_file_free (kf);
if (needed)
g_spawn_command_line_sync ("gsettings-data-convert",
NULL, NULL, NULL, NULL);
}
]]>
</programlisting>
</para>
<para>
Although there is the possibility that the
<command>gsettings-data-convert</command> script will end up
running multiple times concurrently with this approach, it is
believed that this is safe.
</para>
</section>
</chapter>

View File

@ -0,0 +1,633 @@
Title: Migrating to GDBus
SPDX-License-Identifier: LGPL-2.1-or-later
SPDX-FileCopyrightText: 2010 Matthias Clasen
SPDX-FileCopyrightText: 2010, 2011 David Zeuthen
# Migrating to GDBus
## Conceptual differences
The central concepts of D-Bus are modelled in a very similar way in
dbus-glib and GDBus. Both have objects representing connections, proxies and
method invocations. But there are some important differences:
- dbus-glib uses the libdbus reference implementation, GDBus doesn't.
Instead, it relies on GIO streams as transport layer, and has its own
implementation for the D-Bus connection setup and authentication. Apart
from using streams as transport, avoiding libdbus also lets GDBus avoid
some thorny multithreading issues.
- dbus-glib uses the GObject type system for method arguments and return
values, including a homegrown container specialization mechanism. GDBus
relies on the GVariant type system which is explicitly designed to match
D-Bus types.
- dbus-glib models only D-Bus interfaces and does not provide any types for
objects. GDBus models both D-Bus interfaces (via the GDBusInterface,
GDBusProxy and GDBusInterfaceSkeleton types) and objects (via the
GDBusObject, GDBusObjectSkeleton and GDBusObjectProxy types).
- GDBus includes native support for the org.freedesktop.DBus.Properties (via
the GDBusProxy type) and org.freedesktop.DBus.ObjectManager D-Bus
interfaces, dbus-glib doesn't.
- The typical way to export an object in dbus-glib involves generating glue
code from XML introspection data using dbus-binding-tool. GDBus provides a
similar tool called gdbus-codegen that can also generate Docbook D-Bus
interface documentation.
- dbus-glib doesn't provide any convenience API for owning and watching bus
names, GDBus provides the `g_bus_own_name()` and `g_bus_watch_name()`
family of convenience functions.
- GDBus provides API to parse, generate and work with Introspection XML,
dbus-glib doesn't.
- GTestDBus provides API to create isolated unit tests
## API comparison
| dbus-glib | GDBus |
|-----------|-------|
| `DBusGConnection` | `GDBusConnection` |
| `DBusGProxy` | `GDBusProxy`, `GDBusInterface` - also see `GDBusObjectProxy` |
| `DBusGObject` | `GDBusInterfaceSkeleton`, `GDBusInterface` - also see `GDBusObjectSkeleton` |
| `DBusGMethodInvocation` | `GDBusMethodInvocation` |
| `dbus_g_bus_get()` | `g_bus_get_sync()`, also see `g_bus_get()` |
| `dbus_g_proxy_new_for_name()` | `g_dbus_proxy_new_sync()` and `g_dbus_proxy_new_for_bus_sync()`, also see `g_dbus_proxy_new()` |
| `dbus_g_proxy_add_signal()` | not needed, use the generic “g-signal” |
| `dbus_g_proxy_connect_signal()` | use `g_signal_connect()` with “g-signal” |
| `dbus_g_connection_register_g_object()` | `g_dbus_connection_register_object()` - also see `g_dbus_object_manager_server_export()` |
| `dbus_g_connection_unregister_g_object()` | `g_dbus_connection_unregister_object()` - also see `g_dbus_object_manager_server_unexport()` |
| `dbus_g_object_type_install_info()` | introspection data is installed while registering an object, see `g_dbus_connection_register_object()` |
| `dbus_g_proxy_begin_call()` | `g_dbus_proxy_call()` |
| `dbus_g_proxy_end_call()` | `g_dbus_proxy_call_finish()` |
| `dbus_g_proxy_call()` | `g_dbus_proxy_call_sync()` |
| `dbus_g_error_domain_register()` | `g_dbus_error_register_error_domain()` |
| `dbus_g_error_has_name()` | no direct equivalent, see `g_dbus_error_get_remote_error()` |
| `dbus_g_method_return()` | `g_dbus_method_invocation_return_value()` |
| `dbus_g_method_return_error()` | `g_dbus_method_invocation_return_error()` and variants |
| `dbus_g_method_get_sender()` | `g_dbus_method_invocation_get_sender()` |
## Owning bus names
Using dbus-glib, you typically call RequestName manually to own a name, like in the following excerpt:
```c
error = NULL;
res = dbus_g_proxy_call (system_bus_proxy,
"RequestName",
&error,
G_TYPE_STRING, NAME_TO_CLAIM,
G_TYPE_UINT, DBUS_NAME_FLAG_ALLOW_REPLACEMENT,
G_TYPE_INVALID,
G_TYPE_UINT, &result,
G_TYPE_INVALID);
if (!res)
{
if (error != NULL)
{
g_warning ("Failed to acquire %s: %s",
NAME_TO_CLAIM, error->message);
g_error_free (error);
}
else
{
g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
}
goto out;
}
if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
{
if (error != NULL)
{
g_warning ("Failed to acquire %s: %s",
NAME_TO_CLAIM, error->message);
g_error_free (error);
}
else
{
g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
}
exit (1);
}
dbus_g_proxy_add_signal (system_bus_proxy, "NameLost",
G_TYPE_STRING, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (system_bus_proxy, "NameLost",
G_CALLBACK (on_name_lost), NULL, NULL);
/* further setup ... */
```
While you can do things this way with GDBus too, using
`g_dbus_proxy_call_sync()`, it is much nicer to use the high-level API for
this:
```c
static void
on_name_acquired (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
/* further setup ... */
}
/* ... */
owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
NAME_TO_CLAIM,
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,
on_bus_acquired,
on_name_acquired,
on_name_lost,
NULL,
NULL);
g_main_loop_run (loop);
g_bus_unown_name (owner_id);
```
Note that `g_bus_own_name()` works asynchronously and requires you to enter
your mainloop to await the `on_name_aquired()` callback. Also note that in
order to avoid race conditions (e.g. when your service is activated by a
method call), you have to export your manager object before acquiring the
name. The `on_bus_acquired()` callback is the right place to do such
preparations.
## Creating proxies for well-known names
dbus-glib lets you create proxy objects for well-known names, like the following example:
```c
proxy = dbus_g_proxy_new_for_name (system_bus_connection,
"org.freedesktop.Accounts",
"/org/freedesktop/Accounts",
"org.freedesktop.Accounts");
```
For a DBusGProxy constructed like this, method calls will be sent to the current owner of the name, and that owner can change over time.
The same can be achieved with GDBusProxy:
```c
error = NULL;
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL, /* GDBusInterfaceInfo */
"org.freedesktop.Accounts",
"/org/freedesktop/Accounts",
"org.freedesktop.Accounts",
NULL, /* GCancellable */
&error);
```
For an added layer of safety, you can specify what D-Bus interface the proxy
is expected to conform to by using the GDBusInterfaceInfo type.
Additionally, GDBusProxy loads, caches and tracks changes to the D-Bus
properties on the remote object. It also sets up match rules so D-Bus
signals from the remote object are delivered locally.
The GDBusProxy type normally isn't used directly - instead proxies
subclassing GDBusProxy generated by `gdbus-codegen` is used, see the section
called “Using gdbus-codegen”.
## Generating code and docs
### Using gdbus-codegen
dbus-glib comes with dbus-binding-tool, which can produce somewhat nice
client- and server-side wrappers for a D-Bus interface. With GDBus,
gdbus-codegen is used and like its counterpart, it also takes D-Bus
Introspection XML as input:
#### Example D-Bus Introspection XML
```xml
<node>
<!-- org.gtk.GDBus.Example.ObjectManager.Animal:
@short_description: Example docs generated by gdbus-codegen
@since: 2.30
This D-Bus interface is used to describe a simple animal.
-->
<interface name="org.gtk.GDBus.Example.ObjectManager.Animal">
<!-- Mood: The mood of the animal.
@since: 2.30
Known values for this property include
<literal>Happy</literal> and <literal>Sad</literal>. Use the
org.gtk.GDBus.Example.ObjectManager.Animal.Poke() method to
change this property.
This property influences how often the animal jumps up and
down, see the
#org.gtk.GDBus.Example.ObjectManager.Animal::Jumped signal
for more details.
-->
<property name="Mood" type="s" access="read"/>
<!--
Poke:
@make_sad: Whether to make the animal sad.
@make_happy: Whether to make the animal happy.
@since: 2.30
Method used to changing the mood of the animal. See also the
#org.gtk.GDBus.Example.ObjectManager.Animal:Mood property.
-->
<method name="Poke">
<arg direction="in" type="b" name="make_sad"/>
<arg direction="in" type="b" name="make_happy"/>
</method>
<!--
Jumped:
@height: Height, in meters, that the animal jumped.
@since: 2.30
Emitted when the animal decides to jump.
-->
<signal name="Jumped">
<arg type="d" name="height"/>
</signal>
<!--
Foo:
Property with no <quote>since</quote> annotation (should inherit the 2.30 from its containing interface).
-->
<property name="Foo" type="s" access="read"/>
<!--
Bar:
@since: 2.36
Property with a later <quote>since</quote> annotation.
-->
<property name="Bar" type="s" access="read"/>
</interface>
<!-- org.gtk.GDBus.Example.ObjectManager.Cat:
@short_description: More example docs generated by gdbus-codegen
This D-Bus interface is used to describe a cat. Right now there
are no properties, methods or signals associated with this
interface so it is essentially a <ulink
url="http://en.wikipedia.org/wiki/Marker_interface_pattern">Marker
Interface</ulink>.
Note that D-Bus objects implementing this interface also
implement the #org.gtk.GDBus.Example.ObjectManager.Animal
interface.
-->
<interface name="org.gtk.GDBus.Example.ObjectManager.Cat">
</interface>
</node>
```
If this XML is processed like this
```
gdbus-codegen --interface-prefix org.gtk.GDBus.Example.ObjectManager. \
--generate-c-code generated-code \
--c-namespace Example \
--c-generate-object-manager \
--generate-docbook generated-docs \
gdbus-example-objectmanager.xml
```
then two files generated-code.h and generated-code.c are generated.
Additionally, two XML files
generated-docs-org.gtk.GDBus.Example.ObjectManager.Animal and
generated-docs-org.gtk.GDBus.Example.ObjectManager.Cat with Docbook XML are
generated.
While the contents of `generated-code.h` and `generated-code.c` are best described by the `gdbus-codegen` manual page, here's a brief example of how this generated code can be used:
```c
#include "gdbus-object-manager-example/objectmanager-gen.h"
/* ---------------------------------------------------------------------------------------------------- */
static GDBusObjectManagerServer *manager = NULL;
static gboolean
on_animal_poke (ExampleAnimal *animal,
GDBusMethodInvocation *invocation,
gboolean make_sad,
gboolean make_happy,
gpointer user_data)
{
if ((make_sad && make_happy) || (!make_sad && !make_happy))
{
g_dbus_method_invocation_return_dbus_error (invocation,
"org.gtk.GDBus.Examples.ObjectManager.Error.Failed",
"Exactly one of make_sad or make_happy must be TRUE");
goto out;
}
if (make_sad)
{
if (g_strcmp0 (example_animal_get_mood (animal), "Sad") == 0)
{
g_dbus_method_invocation_return_dbus_error (invocation,
"org.gtk.GDBus.Examples.ObjectManager.Error.SadAnimalIsSad",
"Sad animal is already sad");
goto out;
}
example_animal_set_mood (animal, "Sad");
example_animal_complete_poke (animal, invocation);
goto out;
}
if (make_happy)
{
if (g_strcmp0 (example_animal_get_mood (animal), "Happy") == 0)
{
g_dbus_method_invocation_return_dbus_error (invocation,
"org.gtk.GDBus.Examples.ObjectManager.Error.HappyAnimalIsHappy",
"Happy animal is already happy");
goto out;
}
example_animal_set_mood (animal, "Happy");
example_animal_complete_poke (animal, invocation);
goto out;
}
g_assert_not_reached ();
out:
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
static void
on_bus_acquired (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
ExampleObjectSkeleton *object;
guint n;
g_print ("Acquired a message bus connection\n");
/* Create a new org.freedesktop.DBus.ObjectManager rooted at /example/Animals */
manager = g_dbus_object_manager_server_new ("/example/Animals");
for (n = 0; n < 10; n++)
{
gchar *s;
ExampleAnimal *animal;
/* Create a new D-Bus object at the path /example/Animals/N where N is 000..009 */
s = g_strdup_printf ("/example/Animals/%03d", n);
object = example_object_skeleton_new (s);
g_free (s);
/* Make the newly created object export the interface
* org.gtk.GDBus.Example.ObjectManager.Animal (note
* that @object takes its own reference to @animal).
*/
animal = example_animal_skeleton_new ();
example_animal_set_mood (animal, "Happy");
example_object_skeleton_set_animal (object, animal);
g_object_unref (animal);
/* Cats are odd animals - so some of our objects implement the
* org.gtk.GDBus.Example.ObjectManager.Cat interface in addition
* to the .Animal interface
*/
if (n % 2 == 1)
{
ExampleCat *cat;
cat = example_cat_skeleton_new ();
example_object_skeleton_set_cat (object, cat);
g_object_unref (cat);
}
/* Handle Poke() D-Bus method invocations on the .Animal interface */
g_signal_connect (animal,
"handle-poke",
G_CALLBACK (on_animal_poke),
NULL); /* user_data */
/* Export the object (@manager takes its own reference to @object) */
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
g_object_unref (object);
}
/* Export all objects */
g_dbus_object_manager_server_set_connection (manager, connection);
}
static void
on_name_acquired (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
g_print ("Acquired the name %s\n", name);
}
static void
on_name_lost (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
g_print ("Lost the name %s\n", name);
}
gint
main (gint argc, gchar *argv[])
{
GMainLoop *loop;
guint id;
loop = g_main_loop_new (NULL, FALSE);
id = g_bus_own_name (G_BUS_TYPE_SESSION,
"org.gtk.GDBus.Examples.ObjectManager",
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
G_BUS_NAME_OWNER_FLAGS_REPLACE,
on_bus_acquired,
on_name_acquired,
on_name_lost,
loop,
NULL);
g_main_loop_run (loop);
g_bus_unown_name (id);
g_main_loop_unref (loop);
return 0;
}
```
This, on the other hand, is a client-side application using generated code:
```c
#include "gdbus-object-manager-example/objectmanager-gen.h"
/* ---------------------------------------------------------------------------------------------------- */
static void
print_objects (GDBusObjectManager *manager)
{
GList *objects;
GList *l;
g_print ("Object manager at %s\n", g_dbus_object_manager_get_object_path (manager));
objects = g_dbus_object_manager_get_objects (manager);
for (l = objects; l != NULL; l = l->next)
{
ExampleObject *object = EXAMPLE_OBJECT (l->data);
GList *interfaces;
GList *ll;
g_print (" - Object at %s\n", g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (object));
for (ll = interfaces; ll != NULL; ll = ll->next)
{
GDBusInterface *interface = G_DBUS_INTERFACE (ll->data);
g_print (" - Interface %s\n", g_dbus_interface_get_info (interface)->name);
/* Note that @interface is really a GDBusProxy instance - and additionally also
* an ExampleAnimal or ExampleCat instance - either of these can be used to
* invoke methods on the remote object. For example, the generated function
*
* void example_animal_call_poke_sync (ExampleAnimal *proxy,
* gboolean make_sad,
* gboolean make_happy,
* GCancellable *cancellable,
* GError **error);
*
* can be used to call the Poke() D-Bus method on the .Animal interface.
* Additionally, the generated function
*
* const gchar *example_animal_get_mood (ExampleAnimal *object);
*
* can be used to get the value of the :Mood property.
*/
}
g_list_free_full (interfaces, g_object_unref);
}
g_list_free_full (objects, g_object_unref);
}
static void
on_object_added (GDBusObjectManager *manager,
GDBusObject *object,
gpointer user_data)
{
gchar *owner;
owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (manager));
g_print ("Added object at %s (owner %s)\n", g_dbus_object_get_object_path (object), owner);
g_free (owner);
}
static void
on_object_removed (GDBusObjectManager *manager,
GDBusObject *object,
gpointer user_data)
{
gchar *owner;
owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (manager));
g_print ("Removed object at %s (owner %s)\n", g_dbus_object_get_object_path (object), owner);
g_free (owner);
}
static void
on_notify_name_owner (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (object);
gchar *name_owner;
name_owner = g_dbus_object_manager_client_get_name_owner (manager);
g_print ("name-owner: %s\n", name_owner);
g_free (name_owner);
}
static void
on_interface_proxy_properties_changed (GDBusObjectManagerClient *manager,
GDBusObjectProxy *object_proxy,
GDBusProxy *interface_proxy,
GVariant *changed_properties,
const gchar *const *invalidated_properties,
gpointer user_data)
{
GVariantIter iter;
const gchar *key;
GVariant *value;
gchar *s;
g_print ("Properties Changed on %s:\n", g_dbus_object_get_object_path (G_DBUS_OBJECT (object_proxy)));
g_variant_iter_init (&iter, changed_properties);
while (g_variant_iter_next (&iter, "{&sv}", &key, &value))
{
s = g_variant_print (value, TRUE);
g_print (" %s -> %s\n", key, s);
g_variant_unref (value);
g_free (s);
}
}
gint
main (gint argc, gchar *argv[])
{
GDBusObjectManager *manager;
GMainLoop *loop;
GError *error;
gchar *name_owner;
manager = NULL;
loop = NULL;
loop = g_main_loop_new (NULL, FALSE);
error = NULL;
manager = example_object_manager_client_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
"org.gtk.GDBus.Examples.ObjectManager",
"/example/Animals",
NULL, /* GCancellable */
&error);
if (manager == NULL)
{
g_printerr ("Error getting object manager client: %s", error->message);
g_error_free (error);
goto out;
}
name_owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (manager));
g_print ("name-owner: %s\n", name_owner);
g_free (name_owner);
print_objects (manager);
g_signal_connect (manager,
"notify::name-owner",
G_CALLBACK (on_notify_name_owner),
NULL);
g_signal_connect (manager,
"object-added",
G_CALLBACK (on_object_added),
NULL);
g_signal_connect (manager,
"object-removed",
G_CALLBACK (on_object_removed),
NULL);
g_signal_connect (manager,
"interface-proxy-properties-changed",
G_CALLBACK (on_interface_proxy_properties_changed),
NULL);
g_main_loop_run (loop);
out:
if (manager != NULL)
g_object_unref (manager);
if (loop != NULL)
g_main_loop_unref (loop);
return 0;
}
```

View File

@ -1,310 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE chapter 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">
]>
<chapter>
<title>Migrating to GDBus</title>
<section>
<title>Conceptual differences</title>
<para>
The central concepts of D-Bus are modelled in a very similar way
in dbus-glib and GDBus. Both have objects representing connections,
proxies and method invocations. But there are some important
differences:
<itemizedlist>
<listitem><para>
dbus-glib uses the <ulink
url="http://www.freedesktop.org/wiki/Software/dbus#ReferenceImplementation.28dbus-daemonandlibdbus.29">libdbus
reference implementation</ulink>, GDBus doesn't. Instead, it
relies on GIO streams as transport layer, and has its own
implementation for the D-Bus connection setup and
authentication. Apart from using streams as transport,
avoiding libdbus also lets GDBus avoid some thorny
multithreading issues.
</para></listitem>
<listitem><para>
dbus-glib uses the GObject type system for method arguments and
return values, including a homegrown container specialization
mechanism. GDBus relies on the #GVariant type system which is
explicitly designed to match D-Bus types.
</para></listitem>
<listitem><para>
dbus-glib models only D-Bus interfaces and does not provide
any types for objects. GDBus models both D-Bus interfaces
(via the #GDBusInterface, #GDBusProxy and
#GDBusInterfaceSkeleton types) and objects (via the
#GDBusObject, #GDBusObjectSkeleton and #GDBusObjectProxy types).
</para></listitem>
<listitem><para>
GDBus includes native support for the <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties">org.freedesktop.DBus.Properties</ulink> (via the #GDBusProxy type) and <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">org.freedesktop.DBus.ObjectManager</ulink> D-Bus interfaces, dbus-glib doesn't.
</para></listitem>
<listitem><para>
The typical way to export an object in dbus-glib involves
generating glue code from XML introspection data using
<command>dbus-binding-tool</command>. GDBus provides a
similar tool called <command><link
linkend="gdbus-codegen">gdbus-codegen</link></command> that
can also generate Docbook D-Bus interface documentation.
</para></listitem>
<listitem><para>
dbus-glib doesn't provide any convenience API for owning and
watching bus names, GDBus provides the g_bus_own_name() and
g_bus_watch_name() family of convenience functions.
</para></listitem>
<listitem><para>
GDBus provides API to parse, generate and work with <link
linkend="gio-D-Bus-Introspection-Data">Introspection
XML</link>, dbus-glib doesn't.
</para></listitem>
<listitem><para>
GTestDBus provides API to create isolated unit tests <link
linkend="gio-D-Bus-Test-Scaffolding">GDBus Test Scaffolding</link>.
</para></listitem>
</itemizedlist>
</para>
</section>
<section>
<title>API comparison</title>
<table id="dbus-glib-vs-gdbus">
<title>dbus-glib APIs and their GDBus counterparts</title>
<tgroup cols="2">
<thead>
<row><entry>dbus-glib</entry><entry>GDBus</entry></row>
</thead>
<tbody>
<row><entry>#DBusGConnection</entry><entry>#GDBusConnection</entry></row>
<row><entry>#DBusGProxy</entry><entry>#GDBusProxy, #GDBusInterface - also see #GDBusObjectProxy</entry></row>
<row><entry>#DBusGObject</entry><entry>#GDBusInterfaceSkeleton, #GDBusInterface - also see #GDBusObjectSkeleton</entry></row>
<row><entry>#DBusGMethodInvocation</entry><entry>#GDBusMethodInvocation</entry></row>
<row><entry>dbus_g_bus_get()</entry><entry>g_bus_get_sync(), also see
g_bus_get()</entry></row>
<row><entry>dbus_g_proxy_new_for_name()</entry><entry>g_dbus_proxy_new_sync() and
g_dbus_proxy_new_for_bus_sync(), also see g_dbus_proxy_new()</entry></row>
<row><entry>dbus_g_proxy_add_signal()</entry><entry>not needed, use the generic #GDBusProxy::g-signal</entry></row>
<row><entry>dbus_g_proxy_connect_signal()</entry><entry>use g_signal_connect() with #GDBusProxy::g-signal</entry></row>
<row><entry>dbus_g_connection_register_g_object()</entry><entry>g_dbus_connection_register_object() - also see g_dbus_object_manager_server_export()</entry></row>
<row><entry>dbus_g_connection_unregister_g_object()</entry><entry>g_dbus_connection_unregister_object() - also see g_dbus_object_manager_server_unexport()</entry></row>
<row><entry>dbus_g_object_type_install_info()</entry><entry>introspection data is installed while registering
an object, see g_dbus_connection_register_object()</entry></row>
<row><entry>dbus_g_proxy_begin_call()</entry><entry>g_dbus_proxy_call()</entry></row>
<row><entry>dbus_g_proxy_end_call()</entry><entry>g_dbus_proxy_call_finish()</entry></row>
<row><entry>dbus_g_proxy_call()</entry><entry>g_dbus_proxy_call_sync()</entry></row>
<row><entry>dbus_g_error_domain_register()</entry><entry>g_dbus_error_register_error_domain()</entry></row>
<row><entry>dbus_g_error_has_name()</entry><entry>no direct equivalent, see g_dbus_error_get_remote_error()</entry></row>
<row><entry>dbus_g_method_return()</entry><entry>g_dbus_method_invocation_return_value()</entry></row>
<row><entry>dbus_g_method_return_error()</entry><entry>g_dbus_method_invocation_return_error() and variants</entry></row>
<row><entry>dbus_g_method_get_sender()</entry><entry>g_dbus_method_invocation_get_sender()</entry></row>
</tbody>
</tgroup>
</table>
</section>
<section>
<title>Owning bus names</title>
<para>
Using dbus-glib, you typically call RequestName manually
to own a name, like in the following excerpt:
<informalexample><programlisting><![CDATA[
error = NULL;
res = dbus_g_proxy_call (system_bus_proxy,
"RequestName",
&error,
G_TYPE_STRING, NAME_TO_CLAIM,
G_TYPE_UINT, DBUS_NAME_FLAG_ALLOW_REPLACEMENT,
G_TYPE_INVALID,
G_TYPE_UINT, &result,
G_TYPE_INVALID);
if (!res)
{
if (error != NULL)
{
g_warning ("Failed to acquire %s: %s",
NAME_TO_CLAIM, error->message);
g_error_free (error);
}
else
{
g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
}
goto out;
}
if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
{
if (error != NULL)
{
g_warning ("Failed to acquire %s: %s",
NAME_TO_CLAIM, error->message);
g_error_free (error);
}
else
{
g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
}
exit (1);
}
dbus_g_proxy_add_signal (system_bus_proxy, "NameLost",
G_TYPE_STRING, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (system_bus_proxy, "NameLost",
G_CALLBACK (on_name_lost), NULL, NULL);
/* further setup ... */
]]>
</programlisting></informalexample>
</para>
<para>
While you can do things this way with GDBus too, using
g_dbus_proxy_call_sync(), it is much nicer to use the high-level API
for this:
<informalexample><programlisting><![CDATA[
static void
on_name_acquired (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
/* further setup ... */
}
/* ... */
owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
NAME_TO_CLAIM,
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,
on_bus_acquired,
on_name_acquired,
on_name_lost,
NULL,
NULL);
g_main_loop_run (loop);
g_bus_unown_name (owner_id);
]]>
</programlisting></informalexample>
Note that g_bus_own_name() works asynchronously and requires
you to enter your mainloop to await the on_name_aquired()
callback. Also note that in order to avoid race conditions (e.g.
when your service is activated by a method call), you have to export
your manager object <emphasis>before</emphasis> acquiring the
name. The on_bus_acquired() callback is the right place to do
such preparations.
</para>
</section>
<section>
<title>Creating proxies for well-known names</title>
<para>
dbus-glib lets you create proxy objects for well-known names, like the
following example:
<informalexample><programlisting><![CDATA[
proxy = dbus_g_proxy_new_for_name (system_bus_connection,
"org.freedesktop.Accounts",
"/org/freedesktop/Accounts",
"org.freedesktop.Accounts");
]]>
</programlisting></informalexample>
For a #DBusGProxy constructed like this, method calls will be sent to
the current owner of the name, and that owner can change over time.
</para>
<para>
The same can be achieved with #GDBusProxy:
<informalexample><programlisting><![CDATA[
error = NULL;
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL, /* GDBusInterfaceInfo */
"org.freedesktop.Accounts",
"/org/freedesktop/Accounts",
"org.freedesktop.Accounts",
NULL, /* GCancellable */
&error);
]]>
</programlisting></informalexample>
For an added layer of safety, you can specify what D-Bus
interface the proxy is expected to conform to by using the
#GDBusInterfaceInfo type. Additionally, #GDBusProxy loads,
caches and tracks changes to the D-Bus properties on the remote
object. It also sets up match rules so D-Bus signals from the
remote object are delivered locally.
</para>
<para>
The #GDBusProxy type normally isn't used directly - instead
proxies subclassing #GDBusProxy generated by <command><link
linkend="gdbus-codegen">gdbus-codegen</link></command> is used, see <xref linkend="gdbus-example-gdbus-codegen"/>
</para>
</section>
<section>
<title>Generating code and docs</title>
<section id="gdbus-example-gdbus-codegen">
<title>Using gdbus-codegen</title>
<para>
dbus-glib comes with <command>dbus-binding-tool</command>, which
can produce somewhat nice client- and server-side wrappers for a D-Bus interface.
With GDBus, <command><link
linkend="gdbus-codegen">gdbus-codegen</link></command> is used and like
its counterpart, it also takes D-Bus Introspection XML as input:
</para>
<example id="gdbus-example-codegen-input"><title>Example D-Bus Introspection XML</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../../gio/tests/gdbus-object-manager-example/gdbus-example-objectmanager.xml"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT: gdbus-example-objectmanager.xml</xi:fallback></xi:include></programlisting></example>
<para>
If this XML is processed like this
<informalexample><programlisting><![CDATA[
gdbus-codegen --interface-prefix org.gtk.GDBus.Example.ObjectManager. \
--generate-c-code generated-code \
--c-namespace Example \
--c-generate-object-manager \
--generate-docbook generated-docs \
gdbus-example-objectmanager.xml
]]></programlisting></informalexample>
then two files <filename>generated-code.h</filename> and
<filename>generated-code.c</filename> are
generated. Additionally, two XML files
<filename>generated-docs-org.gtk.GDBus.Example.ObjectManager.Animal</filename> and
<filename>generated-docs-org.gtk.GDBus.Example.ObjectManager.Cat</filename>
with Docbook XML are generated. For an example of what the docs look
like see <link
linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Animal">the Animal D-Bus interface documentation</link>.
and
<link
linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Cat">the Cat D-Bus interface documentation</link>.
</para>
<para>
While the contents of <filename>generated-code.h</filename> and
<filename>generated-code.c</filename> are best described by the
<command><link
linkend="gdbus-codegen">gdbus-codegen</link></command> manual
page, brief examples of how this generated code can be used can be found in
<xref linkend="gdbus-example-codegen-server"/>
and <xref
linkend="gdbus-example-codegen-client"/>. Additionally, since
the generated code has 100% gtk-doc coverage, see
#ExampleAnimal, #ExampleCat, #ExampleObject and
#ExampleObjectManagerClient pages for documentation.
</para>
<example id="gdbus-example-codegen-server"><title>Server-side application using generated code</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../../gio/tests/gdbus-example-objectmanager-server.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT: gdbus-example-objectmanager-server.c</xi:fallback></xi:include></programlisting></example>
<example id="gdbus-example-codegen-client"><title>Client-side application using generated code</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../../gio/tests/gdbus-example-objectmanager-client.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT: gdbus-example-objectmanager-client.c</xi:fallback></xi:include></programlisting></example>
</section>
<!-- All XInclude paths are relative to the html/ directory under the build root directory -->
<xi:include href="../../../../gio/tests/gdbus-object-manager-example/objectmanager-gen-org.gtk.GDBus.Example.ObjectManager.Animal.xml"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT: objectmanager-gen-org.gtk.GDBus.Example.ObjectManager.Animal.xml</xi:fallback></xi:include>
<xi:include href="../../../../gio/tests/gdbus-object-manager-example/objectmanager-gen-org.gtk.GDBus.Example.ObjectManager.Cat.xml"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT: objectmanager-gen-org.gtk.GDBus.Example.ObjectManager.Cat.xml</xi:fallback></xi:include>
<xi:include href="../gdbus-object-manager-example/xml/ExampleAnimal.xml"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT: ExampleAnimal.xml</xi:fallback></xi:include>
<xi:include href="../gdbus-object-manager-example/xml/ExampleCat.xml"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT: ExampleCat.xml</xi:fallback></xi:include>
<xi:include href="../gdbus-object-manager-example/xml/ExampleObject.xml"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT: ExampleObject.xml</xi:fallback></xi:include>
<xi:include href="../gdbus-object-manager-example/xml/ExampleObjectManagerClient.xml"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT: ExampleObjectManagerClient.xml</xi:fallback></xi:include>
</section>
</chapter>

View File

@ -0,0 +1,109 @@
Title: Migrating from GnomeVFS to GIO
SPDX-License-Identifier: LGPL-2.1-or-later
SPDX-FileCopyrightText: 2010 Matthias Clasen
# Migrating from GnomeVFS to GIO
## Comparison of GnomeVFS and GIO concepts
| GnomeVFS | GIO |
|----------|-----|
| `GnomeVFSURI` | [iface@Gio.File] |
| `GnomeVFSFileInfo` | [class@Gio.FileInfo] |
| `GnomeVFSResult` | [struct@GLib.Error], with `G_IO_ERROR` values |
| `GnomeVFSHandle` & `GnomeVFSAsyncHandle` | [class@Gio.InputStream] or [class@Gio.OutputStream] |
| `GnomeVFSDirectoryHandle` | [class@Gio.FileEnumerator] |
| MIME type | content type |
| `GnomeVFSMonitor` | [class@Gio.FileMonitor] |
| `GnomeVFSVolumeMonitor` | [class@Gio.VolumeMonitor] |
| `GnomeVFSVolume` | [iface@Gio.Mount] |
| `GnomeVFSDrive` | [iface@Gio.Volume] |
| - | [iface@Gio.Drive] |
| `GnomeVFSContext` | [class@Gio.Cancellable] |
| `gnome_vfs_async_cancel()` | [method@Gio.Cancellable.cancel] |
## Trash handling
The handling of trashed files has been changed in GIO, compared to
gnome-vfs. gnome-vfs has a home-grown trash implementation that predates the
freedesktop.org [Desktop Trash
Can](http://www.freedesktop.org/wiki/Specifications/trash-spec)
specification that is implemented in GIO. The location for storing trashed
files has changed from `$HOME/.Trash` to `$HOME/.local/share/Trash` (or more
correctly `$XDG_DATA_HOME/Trash`), which means that there is a need for
migrating files that have been trashed by gnome-vfs to the new location.
In gnome-vfs, the `trash://` scheme offering a merged view of all trash
directories was implemented in Nautilus, and trash-handling applications had
to find and monitor all trash directories themselves. With GIO, the
`trash://` implementation has been moved to gvfs and applications can simply
monitor that location:
```c
static void
file_changed (GFileMonitor *file_monitor,
GFile *child,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
{
switch (event_type)
{
case G_FILE_MONITOR_EVENT_DELETED:
g_print ("'%s' removed from trash\n", g_file_get_basename (child));
break;
case G_FILE_MONITOR_EVENT_CREATED:
g_print ("'%s' added to trash\n", g_file_get_basename (child));
break;
default: ;
}
}
static void
start_monitoring_trash (void)
{
GFile *file;
GFileMonitor *monitor;
file = g_file_new_for_uri ("trash://");
monitor = g_file_monitor_directory (file, 0, NULL, NULL);
g_object_unref (file);
g_signal_connect (monitor, "changed", G_CALLBACK (file_changed), NULL);
/* ... */
}
```
GIO exposes some useful metadata about trashed files. There are
`trash::orig-path` and `trash::deletion-date` attributes. The
`standard::icon` attribute of the `trash://` itself provides a suitable icon
for displaying the trash can on the desktop. If you are using this icon,
make sure to monitor this attribute for changes, since the icon may be
updated to reflect that state of the trash can.
Moving a file to the trash is much simpler with GIO. Instead of using
`gnome_vfs_find_directory()` with `GNOME_VFS_DIRECTORY_KIND_TRASH` to find
out where to move the trashed file, just use the [`method@Gio.File.trash`]
method.
## Operations on multiple files
gnome-vfs has the dreaded `gnome_vfs_xfer_uri_list()` function which has
tons of options and offers the equivalent of `cp`, `mv`, `ln`, `mkdir` and
`rm` at the same time.
GIO offers a much simpler asynchronous task functionality instead, that lets
you schedule a function to be called in a separate thread, making sure that
updates are scheduled within the main context that created the task, so you
can update your user interface. See: [`class@Gio.Task`].
## Mime monitoring
gnome-vfs offered a way to monitor the association between mime types and
default handlers for changes, with the `GnomeVFSMIMEMonitor` object. GIO
does not offer a replacement for this functionality at this time, since we
have not found a compelling use case where `GnomeVFSMIMEMonitor` was used.
If you think you have such a use case, please [open an issue on the GLib
issue tracker](https://gitlab.gnome.org/GNOME/glib/issues/new).

View File

@ -1,133 +0,0 @@
<chapter>
<title>Migrating from GnomeVFS to GIO</title>
<table id="gnome-vfs-vs-gio">
<title>Comparison of GnomeVFS and GIO concepts</title>
<tgroup cols="2">
<thead>
<row><entry>GnomeVFS</entry><entry>GIO</entry></row>
</thead>
<tbody>
<row><entry>GnomeVFSURI</entry><entry>GFile</entry></row>
<row><entry>GnomeVFSFileInfo</entry><entry>GFileInfo</entry></row>
<row><entry>GnomeVFSResult</entry><entry>GError, with G_IO_ERROR values</entry></row>
<row><entry>GnomeVFSHandle &amp; GnomeVFSAsyncHandle</entry><entry>GInputStream or GOutputStream</entry></row>
<row><entry>GnomeVFSDirectoryHandle</entry><entry>GFileEnumerator</entry></row>
<row><entry>mime type</entry><entry>content type</entry></row>
<row><entry>GnomeVFSMonitor</entry><entry>GFileMonitor</entry></row>
<row><entry>GnomeVFSVolumeMonitor</entry><entry>GVolumeMonitor</entry></row>
<row><entry>GnomeVFSVolume</entry><entry>GMount</entry></row>
<row><entry>GnomeVFSDrive</entry><entry>GVolume</entry></row>
<row><entry>-</entry><entry>GDrive</entry></row>
<row><entry>GnomeVFSContext</entry><entry>GCancellable</entry></row>
<row><entry>gnome_vfs_async_cancel</entry><entry>g_cancellable_cancel</entry></row>
</tbody>
</tgroup>
</table>
<section>
<title>Trash handling</title>
<para>
The handling of trashed files has been changed in GIO, compared
to gnome-vfs. gnome-vfs has a home-grown trash implementation that
predates the freedesktop.org <ulink url="http://www.freedesktop.org/wiki/Specifications/trash-spec">Desktop Trash Can</ulink> specification
that is implemented in GIO. The location for storing trashed files
has changed from <filename>$HOME/.Trash</filename> to
<filename>$HOME/.local/share/Trash</filename> (or more correctly
<filename>$XDG_DATA_HOME/Trash</filename>), which means that
there is a need for migrating files that have been trashed by
gnome-vfs to the new location.
</para>
<para>
In gnome-vfs, the <filename>trash://</filename> scheme offering a
merged view of all trash directories was implemented in nautilus,
and trash-handling applications had to find and monitor all trash
directories themselves. With GIO, the <filename>trash://</filename>
implementation has been moved to gvfs and applications can simply
monitor that location:
</para>
<informalexample><programlisting>
static void
file_changed (GFileMonitor *file_monitor,
GFile *child,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
{
switch (event_type)
{
case G_FILE_MONITOR_EVENT_DELETED:
g_print ("'%s' removed from trash\n", g_file_get_basename (child));
break;
case G_FILE_MONITOR_EVENT_CREATED:
g_print ("'%s' added to trash\n", g_file_get_basename (child));
break;
default: ;
}
}
static void
start_monitoring_trash (void)
{
GFile *file;
GFileMonitor *monitor;
file = g_file_new_for_uri ("trash://");
monitor = g_file_monitor_directory (file, 0, NULL, NULL);
g_object_unref (file);
g_signal_connect (monitor, "changed", G_CALLBACK (file_changed), NULL);
/* ... */
}
</programlisting></informalexample>
<para>
GIO exposes some useful metadata about trashed files. There are
trash::orig-path and trash::deletion-date attributes. The
standard::icon attribute of the <filename>trash://</filename>
itself provides a suitable icon for displaying the trash can on
the desktop. If you are using this icon, make sure to monitor
this attribute for changes, since the icon may be updated to
reflect that state of the trash can.
</para>
<para>
Moving a file to the trash is much simpler with GIO. Instead of
using gnome_vfs_find_directory() with %GNOME_VFS_DIRECTORY_KIND_TRASH
to find out where to move the trashed file, just use the g_file_trash()
function.
</para>
</section>
<section>
<title>Operations on multiple files</title>
<para>
gnome-vfs has the dreaded gnome_vfs_xfer_uri_list() function which
has tons of options and offers the equivalent of cp, mv, ln, mkdir
and rm at the same time.
</para>
<para>
GIO offers a much simpler I/O scheduler functionality instead, that
lets you schedule a function to be called in a separate thread, or
if threads are not available, as an idle in the mainloop.
See g_io_scheduler_push_job().
</para>
</section>
<section>
<title>Mime monitoring</title>
<para>
gnome-vfs offered a way to monitor the association between mime types
and default handlers for changes, with the #GnomeVFSMIMEMonitor object.
GIO does not offer a replacement for this functionality at this time,
since we have not found a compelling use case where
#GnomeVFSMIMEMonitor was used. If you think you have such a use
case, please report it at
<ulink url="https://gitlab.gnome.org/GNOME/glib/issues/new">https://gitlab.gnome.org/GNOME/glib/issues/new</ulink>.
</para>
</section>
</chapter>

View File

@ -0,0 +1,406 @@
Title: Overview
SPDX-License-Identifier: LGPL-2.1-or-later
SPDX-FileCopyrightText: 2007, 2008, 2010, 2011, 2012, 2013 Matthias Clasen
SPDX-FileCopyrightText: 2007, 2009 Alexander Larsson
SPDX-FileCopyrightText: 2008 A. Walton
SPDX-FileCopyrightText: 2010 David Zeuthen
SPDX-FileCopyrightText: 2013 Stef Walter
SPDX-FileCopyrightText: 2015 Collabora, Ltd.
SPDX-FileCopyrightText: 2016 Colin Walters
SPDX-FileCopyrightText: 2020 Wouter Bolsterlee
SPDX-FileCopyrightText: 2022 Endless OS Foundation, LLC
# Overview
GIO is striving to provide a modern, easy-to-use VFS API that sits at the
right level in the library stack, as well as other generally useful APIs
for desktop applications (such as networking and D-Bus support). The goal
is to overcome the shortcomings of GnomeVFS and provide an API that is so
good that developers prefer it over raw POSIX calls. Among other things
that means using GObject. It also means not cloning the POSIX API, but
providing higher-level, document-centric interfaces.
The abstract file system model of GIO consists of a number of interfaces and
base classes for I/O and files:
[iface@Gio.File]
: reference to a file
[class@Gio.FileInfo]
: information about a file or filesystem
[class@Gio.FileEnumerator]
: list files in directories
[iface@Gio.Drive]
: represents a drive
[iface@Gio.Volume]
: represents a file system in an abstract way
[iface@Gio.Mount]
: represents a mounted file system
Then there is a number of stream classes, similar to the input and output
stream hierarchies that can be found in frameworks like Java:
[class@Gio.InputStream]
: read data
[class@Gio.OutputStream]
: write data
[class@Gio.IOStream]
: read and write data
[iface@Gio.Seekable]
: interface optionally implemented by streams to support seeking
There are interfaces related to applications and the types of files they
handle:
[iface@Gio.AppInfo]
: information about an installed application
[iface@Gio.Icon]
: abstract type for file and application icons
There is a framework for storing and retrieving application settings:
[class@Gio.Settings]
: stores and retrieves application settings
There is support for network programming, including connectivity monitoring,
name resolution, lowlevel socket APIs and highlevel client and server helper
classes:
[class@Gio.Socket]
: lowlevel platform independent socket object
[class@Gio.Resolver]
: asynchronous and cancellable DNS resolver
[class@Gio.SocketClient]
: high-level network client helper
[class@Gio.SocketService]
: high-level network server helper
[class@Gio.SocketConnection]
: network connection stream
[iface@Gio.NetworkMonitor]
: network connectivity monitoring
There is support for connecting to
[D-Bus](https://www.freedesktop.org/wiki/Software/dbus/), sending and receiving
messages, owning and watching bus names, and making objects available on the bus:
[class@Gio.DBusConnection]
: a D-Bus connection
[class@Gio.DBusMethodInvocation]
: for handling remote calls
[class@Gio.DBusServer]
: helper for accepting connections
[class@Gio.DBusProxy]
: proxy to access D-Bus interfaces on a remote object
Beyond these, GIO provides facilities for file monitoring, asynchronous I/O
and filename completion. In addition to the interfaces, GIO provides
implementations for the local case. Implementations for various network file
systems are provided by the GVFS package as loadable modules.
Other design choices which consciously break with the GnomeVFS design are to
move backends out-of-process, which minimizes the dependency bloat and makes
the whole system more robust. The backends are not included in GIO, but in
the separate GVFS package. The GVFS package also contains the GVFS daemon,
which spawn further mount daemons for each individual connection.
![GIO in the GTK library stack](./gvfs-overview.png)
The GIO model of I/O is stateful: if an application establishes e.g. a SFTP
connection to a server, it becomes available to all applications in the
session; the user does not have to enter his password over and over again.
One of the big advantages of putting the VFS in the GLib layer is that GTK
can directly use it, e.g. in the filechooser.
## Writing GIO applications
The information in the GLib documentation about writing GLib applications is
generally applicable when writing GIO applications.
### Threads
GDBus has its own private worker thread, so applications using GDBus have at
least 3 threads. GIO makes heavy use of the concept of a thread-default main
context to execute callbacks of asynchronous methods in the same context in
which the operation was started.
### Asynchronous Programming
Many GIO functions come in two versions: synchronous and asynchronous,
denoted by an `_async` suffix. It is important to use these appropriately:
synchronous calls should not be used from within a main loop which is shared
with other code, such as one in the applications main thread. Synchronous
calls block until they complete, and I/O operations can take noticeable
amounts of time (even on fast SSDs). Blocking a main loop iteration while
waiting for I/O means that other sources in the main loop will not be
dispatched, such as input and redraw handlers for the applications UI. This
can cause the application to freeze until I/O completes.
A few self-contained groups of functions, such as code generated by
gdbus-codegen, use a different convention: functions are asynchronous
default, and it is the synchronous version which has a `_sync` suffix. Aside
from naming differences, they should be treated the same way as functions
following the normal convention above.
The asynchronous (`_async`) versions of functions return control to the
caller immediately, after scheduling the I/O in the kernel and adding a
callback for it to the main loop. This callback will be invoked when the
operation has completed. From the callback, the paired `_finish` function
should be called to retrieve the return value of the I/O operation, and any
errors which occurred. For more information on using and implementing
asynchronous functions, see [iface@Gio.AsyncResult] and [class@Gio.Task].
By starting multiple asynchronous operations in succession, they will be
executed in parallel (up to an arbitrary limit imposed by GIOs internal
worker thread pool).
The synchronous versions of functions can be used early in application
startup when there is no main loop to block, for example to load initial
configuration files. They can also be used for I/O on files which are
guaranteed to be small and on the local disk. Note that the users home
directory is not guaranteed to be on the local disk. Security
When your program needs to carry out some privileged operation (say, create
a new user account), there are various ways in which you can go about this:
- Implement a daemon that offers the privileged operation. A convenient way
to do this is as a D-Bus system-bus service. The daemon will probably need
ways to check the identity and authorization of the caller before
executing the operation.
[polkit](https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html)
is a framework that allows this.
- Use a small helper that is executed with elevated privileges via pkexec.
[`pkexec`](https://www.freedesktop.org/software/polkit/docs/latest/pkexec.1.html)
is a small program launcher that is part of polkit.
- Use a small helper that is executed with elevated privileges by being suid
root.
None of these approaches is the clear winner, they all have their advantages
and disadvantages.
When writing code that runs with elevated privileges, it is important to
follow some basic rules of secure programming. David Wheeler has an
excellent book on this topic,
[Secure Programming for Linux and Unix HOWTO](https://dwheeler.com/secure-programs/Secure-Programs-HOWTO/index.html).
When using GIO in code that runs with elevated privileges, you have to be
careful. GIO has extension points whose implementations get loaded from
modules (executable code in shared objects), which could allow an attacker
to sneak his own code into your application by tricking it into loading the
code as a module. However, GIO will never load modules from your home
directory except when explicitly asked to do so via an environment variable.
In most cases, your helper program should be so small that you don't need
GIO, whose APIs are largely designed to support full-blown desktop
applications. If you can't resist the convenience of these APIs, here are
some steps you should take:
- Clear the environment, e.g. using the `clearenv()` function. David Wheeler
has a good
[explanation](https://dwheeler.com/secure-programs/Secure-Programs-HOWTO/environment-variables.html)
for why it is important to sanitize the environment. See the section on
running GIO applications for a list of all environment variables affecting
GIO. In particular, `PATH` (used to locate binaries), `GIO_EXTRA_MODULES`
(used to locate loadable modules) and `DBUS_{SYSTEM,SESSION}_BUS_ADDRESS`
(used to locate the D-Bus system and session bus) are important.
- Don't use GVfs, by setting `GIO_USE_VFS=local` in the environment. The
reason to avoid GVfs in security-sensitive programs is that it uses many
libraries which have not necessarily been audited for security problems.
Gvfs is also heavily distributed and relies on a session bus to be
present.
## Compiling GIO applications
GIO comes with a `gio-2.0.pc` file that you should use together with
pkg-config to obtain the necessary information about header files and
libraries. See the pkg-config man page or the GLib documentation for more
information on how to use pkg-config to compile your application.
If you are using GIO on UNIX-like systems, you may want to use UNIX-specific
GIO interfaces such as `GUnixInputStream`, `GUnixOutputStream`, `GUnixMount`
or `GDesktopAppInfo`. To do so, use the `gio-unix-2.0.pc` file instead of
`gio-2.0.pc`.
## Running GIO applications
GIO inspects a few environment variables in addition to the ones used by GLib.
- `XDG_DATA_HOME`, `XDG_DATA_DIRS`. GIO uses these environment variables to
locate MIME information. For more information, see the
[Shared MIME-info Database](https://specifications.freedesktop.org/shared-mime-info-spec/latest/)
and the [Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/latest/).
- `GVFS_DISABLE_FUSE`. This variable can be set to keep Gvfs from starting
the fuse backend, which may be unwanted or unnecessary in certain
situations.
- `GIO_USE_VFS`. This environment variable can be set to the name of a GVfs
implementation to override the default for debugging purposes. The GVfs
implementation for local files that is included in GIO has the name
"local", the implementation in the gvfs module has the name "gvfs". Most
commonly, system software will set this to "local" to avoid having `GFile`
APIs perform unnecessary D-Bus calls. The special value help can be used
to print a list of available implementations to standard output.
The following environment variables are only useful for debugging GIO itself
or modules that it loads. They should not be set in a production
environment.
- `GIO_USE_FILE_MONITOR`. This variable can be set to the name of a
GFileMonitor implementation to override the default for debugging
purposes. The GFileMonitor implementation for local files that is included
in GIO on Linux has the name "inotify", others that are built are built as
modules (depending on the platform) are called "fam" and "fen". The
special value help can be used to print a list of available
implementations to standard output.
- `GIO_USE_VOLUME_MONITOR`. This variable can be set to the name of a
GVolumeMonitor implementation to override the default for debugging
purposes. The GVolumeMonitor implementation for local files that is
included in GIO has the name "unix", the udisks2-based implementation in
the gvfs module has the name "udisks2". The special value help can be used
to print a list of available implementations to standard output.
- `GIO_USE_TLS`. This variable can be set to the name of a GTlsBackend
implementation to override the default for debugging purposes. GIO does
not include a GTlsBackend implementation, the gnutls-based implementation
in the glib-networking module has the name "gnutls". The special value
help can be used to print a list of available implementations to standard
output.
- `GIO_USE_PORTALS`. This variable can be set to override detection of portals
and force them to be used to provide various bits of GIO functionality, for
testing and debugging. This variable is not intended to be used in production.
- `GIO_MODULE_DIR`. When this environment variable is set to a path, GIO
will load modules from this alternate directory instead of the directory
built into GIO. This is useful when running tests, for example. This
environment variable is ignored when running in a setuid program.
- `GIO_EXTRA_MODULES`. When this environment variable is set to a path, or
a set of paths separated by a colon, GIO will attempt to load additional
modules from within the path. This environment variable is ignored when
running in a setuid program.
- `GSETTINGS_BACKEND`. This variable can be set to the name of a
GSettingsBackend implementation to override the default for debugging
purposes. The memory-based implementation that is included in GIO has the
name "memory", the one in dconf has the name "dconf". The special value
help can be used to print a list of available implementations to standard
output.
- `GSETTINGS_SCHEMA_DIR`. This variable can be set to the names of
directories to consider when looking for compiled schemas for GSettings,
in addition to the `glib-2.0/schemas` subdirectories of the XDG system
data dirs. To specify multiple directories, use `G_SEARCHPATH_SEPARATOR_S`
as a separator.
- `DBUS_SYSTEM_BUS_ADDRESS`. This variable is consulted to find the address
of the D-Bus system bus. For the format of D-Bus addresses, see the
[D-Bus specification](https://dbus.freedesktop.org/doc/dbus-specification.html#addresses).
Setting this variable overrides platform-specific ways of determining the
system bus address.
- `DBUS_SESSION_BUS_ADDRESS`. This variable is consulted to find the
address of the D-Bus session bus. Setting this variable overrides
platform-specific ways of determining the session bus address.
- `DBUS_STARTER_BUS_TYPE`. This variable is consulted to find out the
'starter' bus for an application that has been started via D-Bus
activation. The possible values are 'system' or 'session'.
- `G_DBUS_DEBUG`. This variable can be set to a list of debug options,
which cause GLib to print out different types of debugging information
when using the D-Bus routines.
- `transport`: Show IO activity (e.g. reads and writes)
- `message`: Show all sent and received D-Bus messages
- `payload`: Show payload for all sent and received D-Bus messages (implies
message)
- `call`: Trace `g_dbus_connection_call()` and
`g_dbus_connection_call_sync()` API usage
- `signal`: Show when a D-Bus signal is received
- `incoming`: Show when an incoming D-Bus method call is received
- `return`: Show when a reply is returned via the GDBusMethodInvocation API
- `emission`: Trace `g_dbus_connection_emit_signal()` API usage
- `authentication`: Show information about connection authentication
- `address`: Show information about D-Bus address lookups and autolaunching
- `all`: Turn on all debug options
- `help`: Print a list of supported options to the standard output
- `G_DBUS_COOKIE_SHA1_KEYRING_DIR`. Can be used to override the directory
used to store the keyring used in the `DBUS_COOKIE_SHA1` authentication
mechanism. Normally the directory used is `.dbus-keyrings` in the user's
home directory.
- `G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION`. If set, the
permissions of the directory used to store the keyring used in the
`DBUS_COOKIE_SHA1` authentication mechanism won't be checked. Normally the
directory must be readable only by the user.
## Extending GIO
A lot of the functionality that is accessible through GIO is implemented in
loadable modules, and modules provide a convenient way to extend GIO. In
addition to the [`class@Gio.IOModule`] API which supports writing such modules, GIO has a
mechanism to define extension points, and register implementations thereof,
see [`struct@Gio.IOExtensionPoint`].
The following extension points are currently defined by GIO:
- `G_VFS_EXTENSION_POINT_NAME`. Allows to override the functionality of the
GVfs class. Implementations of this extension point must be derived from
GVfs. GIO uses the implementation with the highest priority that is
active, see `g_vfs_is_active()`. GIO implements this extension point for
local files, gvfs contains an implementation that supports all the
backends in gvfs.
- `G_VOLUME_MONITOR_EXTENSION_POINT_NAME`. Allows to add more volume
monitors. Implementations of this extension point must be derived from
GVolumeMonitor. GIO uses all registered extensions. gvfs contains an
implementation that works together with the GVfs implementation in gvfs.
- `G_NATIVE_VOLUME_MONITOR_EXTENSION_POINT_NAME`. Allows to override the
'native' volume monitor. Implementations of this extension point must be
derived from GNativeVolumeMonitor. GIO uses the implementation with the
highest priority that is supported, as determined by the `is_supported()`
vfunc in GVolumeMonitorClass. GIO implements this extension point for
local mounts, gvfs contains a udisks2-based implementation.
- `G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME`. Allows to override the file
monitor implementation for local files. Implementations of this extension
point must be derived from GLocalFileMonitor. GIO uses the implementation
with the highest priority that is supported, as determined by the
`is_supported()` vfunc in GLocalFileMonitorClass. GIO uses this extension
point internally, to switch between its fam-based and inotify-based file
monitoring implementations.
- `G_LOCAL_DIRECTORY_MONITOR_EXTENSION_POINT_NAME`. Allows to override the
directory monitor implementation for local files. Implementations of this
extension point must be derived from GLocalDirectoryMonitor. GIO uses the
implementation with the highest priority that is supported, as determined
by the `is_supported()` vfunc in GLocalDirectoryMonitorClass. GIO uses
this extension point internally, to switch between its fam-based and
inotify-based directory monitoring implementations.
- `G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME`. Unix-only. Allows to
provide a way to associate default handlers with URI schemes.
Implementations of this extension point must implement the
GDesktopAppInfoLookup interface. GIO uses the implementation with the
highest priority. This extension point has been discontinued in GLib 2.28.
It is still available to keep API and ABI stability, but GIO is no longer
using it for default handlers. Instead, the mime handler mechanism is
used, together with x-scheme-handler pseudo-mimetypes.
- `G_SETTINGS_BACKEND_EXTENSION_POINT_NAME`. Allows to provide an
alternative storage for GSettings. Implementations of this extension point
must derive from the GSettingsBackend type. GIO contains a keyfile-based
implementation of this extension point, another one is provided by dconf.
- `G_PROXY_EXTENSION_POINT_NAME`. Allows to provide implementations for
network proxying. Implementations of this extension point must provide the
GProxy interface, and must be named after the network protocol they are
proxying. glib-networking contains an implementation of this extension
point based on libproxy.
- `G_TLS_BACKEND_EXTENSION_POINT_NAME`. Allows to provide implementations
for TLS support. Implementations of this extension point must implement
the GTlsBackend interface. glib-networking contains an implementation of
this extension point.
- `G_NETWORK_MONITOR_EXTENSION_POINT_NAME`. Allows to provide
implementations for network connectivity monitoring. Implementations of
this extension point must implement the GNetworkMonitorInterface
interface. GIO contains an implementation of this extension point that is
using the netlink interface of the Linux kernel.

View File

@ -1,755 +0,0 @@
<part>
<title>GIO Overview</title>
<chapter>
<title>Introduction</title>
<para>
GIO is striving to provide a modern, easy-to-use VFS API that sits
at the right level in the library stack, as well as other generally
useful APIs for desktop applications (such as networking and
D-Bus support). The goal is to overcome the shortcomings of GnomeVFS
and provide an API that is so good that developers prefer it over raw
POSIX calls. Among other things that means using GObject. It also means
not cloning the POSIX API, but providing higher-level, document-centric
interfaces.
</para>
<para>
The abstract file system model of GIO consists of a number of
interfaces and base classes for I/O and files:
<variablelist>
<varlistentry>
<term>GFile</term>
<listitem><para>reference to a file</para></listitem>
</varlistentry>
<varlistentry>
<term>GFileInfo</term>
<listitem><para>information about a file or filesystem</para></listitem>
</varlistentry>
<varlistentry>
<term>GFileEnumerator</term>
<listitem><para>list files in directories</para></listitem>
</varlistentry>
<varlistentry>
<term>GDrive</term>
<listitem><para>represents a drive</para></listitem>
</varlistentry>
<varlistentry>
<term>GVolume</term>
<listitem><para>represents a file system in an abstract way</para></listitem>
</varlistentry>
<varlistentry>
<term>GMount</term>
<listitem><para>represents a mounted file system</para></listitem>
</varlistentry>
</variablelist>
Then there is a number of stream classes, similar to the input and
output stream hierarchies that can be found in frameworks like Java:
<variablelist>
<varlistentry>
<term>GInputStream</term>
<listitem><para>read data</para></listitem>
</varlistentry>
<varlistentry>
<term>GOutputStream</term>
<listitem><para>write data</para></listitem>
</varlistentry>
<varlistentry>
<term>GIOStream</term>
<listitem><para>read and write data</para></listitem>
</varlistentry>
<varlistentry>
<term>GSeekable</term>
<listitem><para>interface optionally implemented by streams to support seeking</para></listitem>
</varlistentry>
</variablelist>
There are interfaces related to applications and the types
of files they handle:
<variablelist>
<varlistentry>
<term>GAppInfo</term>
<listitem><para>information about an installed application</para></listitem>
</varlistentry>
<varlistentry>
<term>GIcon</term>
<listitem><para>abstract type for file and application icons</para></listitem>
</varlistentry>
</variablelist>
There is a framework for storing and retrieving application settings:
<variablelist>
<varlistentry>
<term>GSettings</term>
<listitem><para>stores and retrieves application settings</para></listitem>
</varlistentry>
</variablelist>
There is support for network programming, including connectivity monitoring,
name resolution, lowlevel socket APIs and highlevel client and server
helper classes:
<variablelist>
<varlistentry>
<term>GSocket</term>
<listitem><para>lowlevel platform independent socket object</para></listitem>
</varlistentry>
<varlistentry>
<term>GResolver</term>
<listitem><para>asynchronous and cancellable DNS resolver</para></listitem>
</varlistentry>
<varlistentry>
<term>GSocketClient</term>
<listitem><para>high-level network client helper</para></listitem>
</varlistentry>
<varlistentry>
<term>GSocketService</term>
<listitem><para>high-level network server helper</para></listitem>
</varlistentry>
<varlistentry>
<term>GSocketConnection</term>
<listitem><para>network connection stream</para></listitem>
</varlistentry>
<varlistentry>
<term>GNetworkMonitor</term>
<listitem><para>network connectivity monitoring</para></listitem>
</varlistentry>
</variablelist>
There is support for connecting to <ulink url="http://www.freedesktop.org/wiki/Software/dbus">D-Bus</ulink>,
sending and receiving messages, owning and watching bus names,
and making objects available on the bus:
<variablelist>
<varlistentry>
<term>GDBusConnection</term>
<listitem><para>a D-Bus connection</para></listitem>
</varlistentry>
<varlistentry>
<term>GDBusMethodInvocation</term>
<listitem><para>for handling remote calls</para></listitem>
</varlistentry>
<varlistentry>
<term>GDBusServer</term>
<listitem><para>helper for accepting connections</para></listitem>
</varlistentry>
<varlistentry>
<term>GDBusProxy</term>
<listitem><para>proxy to access D-Bus interfaces on a remote object</para></listitem>
</varlistentry>
</variablelist>
Beyond these, GIO provides facilities for file monitoring,
asynchronous I/O and filename completion. In addition to the
interfaces, GIO provides implementations for the local case.
Implementations for various network file systems are provided
by the GVFS package as loadable modules.
</para>
<para>
Other design choices which consciously break with the GnomeVFS
design are to move backends out-of-process, which minimizes the
dependency bloat and makes the whole system more robust. The backends
are not included in GIO, but in the separate GVFS package. The GVFS
package also contains the GVFS daemon, which spawn further mount
daemons for each individual connection.
</para>
<figure id="gvfs-overview">
<title>GIO in the GTK library stack</title>
<graphic fileref="gvfs-overview.png" format="PNG"></graphic>
</figure>
<para>
The GIO model of I/O is stateful: if an application establishes e.g.
a SFTP connection to a server, it becomes available to all applications
in the session; the user does not have to enter their password over
and over again.
</para>
<para>
One of the big advantages of putting the VFS in the GLib layer
is that GTK can directly use it, e.g. in the filechooser.
</para>
</chapter>
<chapter>
<title>Writing GIO applications</title>
<para>
The information in the GLib <ulink url="http://developer.gnome.org/glib/stable/glib-programming.html">documentation</ulink> about writing GLib
applications is generally applicable when writing GIO applications.
</para>
<simplesect><title>Threads</title>
<para>
GDBus has its own private worker thread, so applications using
GDBus have at least 3 threads. GIO makes heavy use of the concept
of a <link linkend="g-main-context-push-thread-default">thread-default
main context</link> to execute callbacks of asynchronous
methods in the same context in which the operation was started.
</para>
</simplesect>
<simplesect id="async-programming"><title>Asynchronous Programming</title>
<para>
Many GIO functions come in two versions: synchronous and asynchronous,
denoted by an <code>_async</code> suffix. It is important to use these
appropriately: synchronous calls should not be used from
within a main loop which is shared with other code, such as one in the
applications main thread. Synchronous calls block until they complete,
and I/O operations can take noticeable amounts of time (even on fast
SSDs). Blocking a main loop iteration while waiting for I/O means that
other sources in the main loop will not be dispatched, such as input and
redraw handlers for the applications UI. This can cause the application
to freeze until I/O completes.
</para>
<para>
A few self-contained groups of functions, such as code generated by
<link linkend="gdbus-codegen"><application>gdbus-codegen</application></link>,
use a different convention: functions are asynchronous default, and it is
the <emphasis>synchronous</emphasis> version which has a
<code>_sync</code>
suffix. Aside from naming differences, they should be treated the same
way as functions following the normal convention above.
</para>
<para>
The asynchronous (<code>_async</code>) versions of functions return
control to the caller immediately, after scheduling the I/O in the kernel
and adding a callback for it to the main loop. This callback will be
invoked when the operation has completed. From the callback, the paired
<code>_finish</code> function should be called to retrieve the return
value of the I/O operation, and any errors which occurred. For more
information on using and implementing asynchronous functions, see
<link linkend="GAsyncResult.description"><type>GAsyncResult</type></link>
and <link linkend="GTask.description"><type>GTask</type></link>.
</para>
<para>
By starting multiple asynchronous operations in succession, they will be
executed in parallel (up to an arbitrary limit imposed by GIOs internal
worker thread pool).
</para>
<para>
The synchronous versions of functions can be used early in application
startup when there is no main loop to block, for example to load initial
configuration files. They can also be used for I/O on files which are
guaranteed to be small and on the local disk. Note that the users home
directory is not guaranteed to be on the local disk.
</para>
</simplesect>
<simplesect><title>Security</title>
<para>
When your program needs to carry out some privileged operation (say,
create a new user account), there are various ways in which you can go
about this:
<itemizedlist>
<listitem><para>
Implement a daemon that offers the privileged operation. A convenient
way to do this is as a D-Bus system-bus service. The daemon will probably
need ways to check the identity and authorization of the caller before
executing the operation. <ulink url="http://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html">polkit</ulink> is a framework that allows this.
</para></listitem>
<listitem><para>
Use a small helper that is executed with elevated privileges via
pkexec. <ulink url="http://www.freedesktop.org/software/polkit/docs/latest/pkexec.1.html">pkexec</ulink> is a small program launcher that is part of polkit.
</para></listitem>
<listitem><para>
Use a small helper that is executed with elevated privileges by
being suid root.
</para></listitem>
</itemizedlist>
None of these approaches is the clear winner, they all have their
advantages and disadvantages.
</para>
<para>
When writing code that runs with elevated privileges, it is important
to follow some basic rules of secure programming. David Wheeler has an
excellent book on this topic,
<ulink url="http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/index.html">Secure Programming for Linux and Unix HOWTO</ulink>.
</para>
<para>
When using GIO in code that runs with elevated privileges, you have to
be careful. GIO has extension points whose implementations get loaded
from modules (executable code in shared objects), which could allow
an attacker to sneak their own code into your application by tricking it
into loading the code as a module. However, GIO will never load modules
from your home directory except when explicitly asked to do so via an
environment variable.
</para>
<para>
In most cases, your helper program should be so small that you don't
need GIO, whose APIs are largely designed to support full-blown desktop
applications. If you can't resist the convenience of these APIs, here
are some steps you should take:
<itemizedlist>
<listitem><para>
Clear the environment, e.g. using the <function>clearenv()</function>
function.
David Wheeler has a good <ulink url="http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/environment-variables.html">explanation</ulink> for why it is
important to sanitize the environment.
See <xref linkend="running-gio-apps"/>
for a list of all environment variables affecting GIO. In particular,
<envar>PATH</envar> (used to locate binaries), <envar>GIO_EXTRA_MODULES</envar> (used to locate loadable modules) and <envar>DBUS_{SYSTEM,SESSION}_BUS_ADDRESS</envar> (used to locate the D-Bus system and session bus) are important.
</para></listitem>
<listitem><para>
Don't use GVfs, by setting <envar>GIO_USE_VFS=local</envar> in the environment.
The reason to avoid GVfs in security-sensitive programs is that it uses
many libraries which have not necessarily been audited for security problems.
Gvfs is also heavily distributed and relies on a session bus to be present.
</para></listitem>
</itemizedlist>
</para>
</simplesect>
</chapter>
<chapter>
<title>Compiling GIO applications</title>
<para>
GIO comes with a <filename>gio-2.0.pc</filename> file that you
should use together with <literal>pkg-config</literal> to obtain
the necessary information about header files and libraries. See
the <literal>pkg-config</literal> man page or the GLib documentation
for more information on how to use <literal>pkg-config</literal>
to compile your application.
</para>
<para>
If you are using GIO on UNIX-like systems, you may want to use
UNIX-specific GIO interfaces such as #GUnixInputStream,
#GUnixOutputStream, #GUnixMount or #GDesktopAppInfo.
To do so, use the <filename>gio-unix-2.0.pc</filename> file
instead of <filename>gio-2.0.pc</filename>
</para>
</chapter>
<chapter id="running-gio-apps">
<title>Running GIO applications</title>
<para>
GIO inspects a few environment variables in addition to the
ones used by GLib.
</para>
<formalpara>
<title><envar>XDG_DATA_HOME</envar>, <envar>XDG_DATA_DIRS</envar></title>
<para>
GIO uses these environment variables to locate MIME information.
For more information, see the <ulink url="http://freedesktop.org/Standards/shared-mime-info-spec">Shared MIME-info Database</ulink>
and the <ulink url="http://freedesktop.org/Standards/basedir-spec">Base Directory Specification</ulink>.
</para>
</formalpara>
<formalpara>
<title><envar>GVFS_DISABLE_FUSE</envar></title>
<para>
This variable can be set to keep #Gvfs from starting the fuse backend,
which may be unwanted or unnecessary in certain situations.
</para>
</formalpara>
<formalpara>
<title><envar>GIO_USE_VFS</envar></title>
<para>
This environment variable can be set to the name of a #GVfs
implementation to override the default for debugging purposes.
The #GVfs implementation for local files that is included in GIO
has the name "local", the implementation in the gvfs module has
the name "gvfs". Most commonly, system software will set this to "local"
to avoid having `GFile` APIs perform unnecessary D-Bus calls.
</para><para>
The special value <literal>help</literal> can be used to print a list of
available implementations to standard output.
</para>
</formalpara>
<para>
The following environment variables are only useful for debugging
GIO itself or modules that it loads. They should not be set in a
production environment.
</para>
<formalpara>
<title><envar>GIO_USE_FILE_MONITOR</envar></title>
<para>
This variable can be set to the name of a #GFileMonitor
implementation to override the default for debugging purposes.
The #GFileMonitor implementation for local files that is included
in GIO on Linux has the name <literal>inotify</literal>, others that are built
are built as modules (depending on the platform) are called
<literal>kqueue</literal> and <literal>win32filemonitor</literal>.
</para><para>
The special value <literal>help</literal> can be used to print a list of
available implementations to standard output.
</para>
</formalpara>
<formalpara>
<title><envar>GIO_USE_VOLUME_MONITOR</envar></title>
<para>
This variable can be set to the name of a #GVolumeMonitor
implementation to override the default for debugging purposes.
The #GVolumeMonitor implementation for local files that is included
in GIO has the name "unix", the udisks2-based implementation in the
gvfs module has the name "udisks2".
</para><para>
The special value <literal>help</literal> can be used to print a list of
available implementations to standard output.
</para>
</formalpara>
<formalpara>
<title><envar>GIO_USE_TLS</envar></title>
<para>
This variable can be set to the name of a #GTlsBackend
implementation to override the default for debugging purposes.
GIO does not include a #GTlsBackend implementation, the gnutls-based
implementation in the glib-networking module has the name "gnutls".
</para><para>
The special value <literal>help</literal> can be used to print a list of
available implementations to standard output.
</para>
</formalpara>
<formalpara>
<title><envar>GIO_USE_PORTALS</envar></title>
<para>
This variable can be set to override detection of portals and force them
to be used to provide various bits of GIO functionality, for testing and
debugging. This variable is not intended to be used in production.
</para>
</formalpara>
<formalpara>
<title><envar>GIO_MODULE_DIR</envar></title>
<para>
When this environment variable is set to a path, GIO will load
modules from this alternate directory instead of the directory
built into GIO. This is useful when running tests, for example.
</para>
<para>
This environment variable is ignored when running in a setuid program.
</para>
</formalpara>
<formalpara>
<title><envar>GIO_EXTRA_MODULES</envar></title>
<para>
When this environment variable is set to a path, or a set of
paths separated by a colon, GIO will attempt to load
additional modules from within the path.
</para>
<para>
This environment variable is ignored when running in a setuid program.
</para>
</formalpara>
<formalpara>
<title><envar>GSETTINGS_BACKEND</envar></title>
<para>
This variable can be set to the name of a #GSettingsBackend
implementation to override the default for debugging purposes.
The memory-based implementation that is included in GIO has
the name "memory", the one in dconf has the name "dconf".
</para><para>
The special value <literal>help</literal> can be used to print a list of
available implementations to standard output.
</para>
</formalpara>
<formalpara>
<title><envar>GSETTINGS_SCHEMA_DIR</envar></title>
<para>
This variable can be set to the names of directories to consider when looking for compiled schemas for #GSettings,
in addition to the <filename>glib-2.0/schemas</filename>
subdirectories of the XDG system data dirs. To specify multiple directories, use <constant>G_SEARCHPATH_SEPARATOR_S</constant> as a separator.
</para>
</formalpara>
<formalpara>
<title><envar>DBUS_SYSTEM_BUS_ADDRESS</envar></title>
<para>
This variable is consulted to find the address of the D-Bus system
bus. For the format of D-Bus addresses, see the D-Bus
<ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html#addresses">specification</ulink>.
</para>
<para>
Setting this variable overrides platform-specific ways of determining
the system bus address.
</para>
</formalpara>
<formalpara>
<title><envar>DBUS_SESSION_BUS_ADDRESS</envar></title>
<para>
This variable is consulted to find the address of the D-Bus session bus.
</para>
<para>
Setting this variable overrides platform-specific ways of determining
the session bus address.
</para>
</formalpara>
<formalpara>
<title><envar>DBUS_STARTER_BUS_TYPE</envar></title>
<para>
This variable is consulted to find out the 'starter' bus for an
application that has been started via D-Bus activation. The possible
values are 'system' or 'session'.
</para>
</formalpara>
<formalpara>
<title><envar>G_DBUS_DEBUG</envar></title>
<para>
This variable can be set to a list of debug options, which
cause GLib to print out different types of debugging
information when using the D-Bus routines.
<variablelist>
<varlistentry>
<term>transport</term>
<listitem><para>Show IO activity (e.g. reads and writes)</para></listitem>
</varlistentry>
<varlistentry>
<term>message</term>
<listitem><para>Show all sent and received D-Bus messages</para></listitem>
</varlistentry>
<varlistentry>
<term>payload</term>
<listitem><para>Show payload for all sent and received D-Bus messages (implies message)</para></listitem>
</varlistentry>
<varlistentry>
<term>call</term>
<listitem><para>Trace g_dbus_connection_call() and g_dbus_connection_call_sync() API usage</para></listitem>
</varlistentry>
<varlistentry>
<term>signal</term>
<listitem><para>Show when a D-Bus signal is received</para></listitem>
</varlistentry>
<varlistentry>
<term>incoming</term>
<listitem><para>Show when an incoming D-Bus method call is received</para></listitem>
</varlistentry>
<varlistentry>
<term>return</term>
<listitem><para>Show when a reply is returned via the #GDBusMethodInvocation API</para></listitem>
</varlistentry>
<varlistentry>
<term>emission</term>
<listitem><para>Trace g_dbus_connection_emit_signal() API usage</para></listitem>
</varlistentry>
<varlistentry>
<term>authentication</term>
<listitem><para>Show information about connection authentication</para></listitem>
</varlistentry>
<varlistentry>
<term>address</term>
<listitem><para>Show information about D-Bus address lookups and autolaunching</para></listitem>
</varlistentry>
</variablelist>
The special value <literal>all</literal> can be used to turn
on all debug options. The special value
<literal>help</literal> can be used to print a list of
supported options to standard output.
</para>
</formalpara>
<formalpara>
<title><envar>G_DBUS_COOKIE_SHA1_KEYRING_DIR</envar></title>
<para>
Can be used to override the directory used to store the
keyring used in the <literal>DBUS_COOKIE_SHA1</literal>
authentication mechanism. Normally the directory used is
<filename>.dbus-keyrings</filename> in the user's home
directory.
</para>
</formalpara>
<formalpara>
<title><envar>G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION</envar></title>
<para>
If set, the permissions of the directory used to store the
keyring used in the <literal>DBUS_COOKIE_SHA1</literal>
authentication mechanism won't be checked. Normally the
directory must be readable only by the user.
</para>
</formalpara>
</chapter>
<chapter id="extending-gio">
<title>Extending GIO</title>
<para>
A lot of the functionality that is accessible through GIO
is implemented in loadable modules, and modules provide a convenient
way to extend GIO. In addition to the #GIOModule API which supports
writing such modules, GIO has a mechanism to define extension points,
and register implementations thereof, see #GIOExtensionPoint.
</para>
<para>
The following extension points are currently defined by GIO:
</para>
<formalpara>
<title>G_VFS_EXTENSION_POINT_NAME</title>
<para>
Allows to override the functionality of the #GVfs class.
Implementations of this extension point must be derived from #GVfs.
GIO uses the implementation with the highest priority that is active,
see g_vfs_is_active().
</para>
<para>
GIO implements this extension point for local files, gvfs contains
an implementation that supports all the backends in gvfs.
</para>
</formalpara>
<formalpara>
<title>G_VOLUME_MONITOR_EXTENSION_POINT_NAME</title>
<para>
Allows to add more volume monitors.
Implementations of this extension point must be derived from
#GVolumeMonitor. GIO uses all registered extensions.
</para>
<para>
gvfs contains an implementation that works together with the #GVfs
implementation in gvfs.
</para>
</formalpara>
<formalpara>
<title>G_NATIVE_VOLUME_MONITOR_EXTENSION_POINT_NAME</title>
<para>
Allows to override the 'native' volume monitor.
Implementations of this extension point must be derived from
#GNativeVolumeMonitor. GIO uses the implementation with
the highest priority that is supported, as determined by the
is_supported() vfunc in #GVolumeMonitorClass.
</para>
<para>
GIO implements this extension point for local mounts,
gvfs contains a udisks2-based implementation.
</para>
</formalpara>
<formalpara>
<title>G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME</title>
<para>
Allows to override the file monitor implementation for
local files. Implementations of this extension point must
be derived from #GLocalFileMonitor. GIO uses the implementation
with the highest priority that is supported, as determined by the
is_supported() vfunc in #GLocalFileMonitorClass.
</para>
<para>
GIO uses this extension point internally, to switch between
its kqueue-based and inotify-based file monitoring implementations.
</para>
</formalpara>
<formalpara>
<title>G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME</title>
<para>
Unix-only. Allows to provide a way to associate default handlers
with URI schemes. Implementations of this extension point must
implement the #GDesktopAppInfoLookup interface. GIO uses the
implementation with the highest priority.
</para>
<para>
This extension point has been discontinued in GLib 2.28. It is
still available to keep API and ABI stability, but GIO is no
longer using it for default handlers. Instead, the mime handler
mechanism is used, together with x-scheme-handler pseudo-mimetypes.
</para>
</formalpara>
<formalpara>
<title>G_SETTINGS_BACKEND_EXTENSION_POINT_NAME</title>
<para>
Allows to provide an alternative storage for #GSettings.
Implementations of this extension point must derive from the
#GSettingsBackend type. GIO contains a keyfile-based
implementation of this extension point, another one is provided
by dconf.
</para>
</formalpara>
<formalpara>
<title>G_PROXY_EXTENSION_POINT_NAME</title>
<para>
Allows to provide implementations for network proxying.
Implementations of this extension point must provide the
#GProxy interface, and must be named after the network
protocol they are proxying.
</para>
<para>
glib-networking contains an implementation of this extension
point based on libproxy.
</para>
</formalpara>
<formalpara>
<title>G_TLS_BACKEND_EXTENSION_POINT_NAME</title>
<para>
Allows to provide implementations for TLS support.
Implementations of this extension point must implement
the #GTlsBackend interface.
</para>
<para>
glib-networking contains an implementation of this extension
point.
</para>
</formalpara>
<formalpara>
<title>G_NETWORK_MONITOR_EXTENSION_POINT_NAME</title>
<para>
Allows to provide implementations for network connectivity
monitoring.
Implementations of this extension point must implement
the #GNetworkMonitorInterface interface.
</para>
<para>
GIO contains an implementation of this extension point
that is using the netlink interface of the Linux kernel.
</para>
</formalpara>
</chapter>
</part>

View File

@ -0,0 +1,9 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
// SPDX-FileCopyrightText: 2023 Matthias Clasen
var baseURLs = [
[ 'GLib', 'https://docs.gtk.org/glib/' ],
[ 'GModule', 'https://docs.gtk.org/gmodule/' ],
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
[ 'Gio', 'https://docs.gtk.org/gio/' ],
[ 'Gtk', 'https://docs.gtk.org/gtk4/' ],
];

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,291 @@
Title: Automatic Cleanup
SPDX-License-Identifier: LGPL-2.1-or-later
SPDX-FileCopyrightText: 2023 Matthias Clasen
# Automatic Cleanup
GLib provides a set of macros that wrap the GCC extension for automatic
cleanup of variables when they go out of scope.
These macros can only be used with GCC and GCC-compatible C compilers.
## Variable declaration
`g_auto(TypeName)`
: Helper to declare a variable with automatic cleanup.
The variable is cleaned up in a way appropriate to its type when the
variable goes out of scope. The `TypeName` of the variable must support
this.
The way to clean up the type must have been defined using one of the macros
`G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC()` or `G_DEFINE_AUTO_CLEANUP_FREE_FUNC()`.
This feature is only supported on GCC and clang. This macro is not
defined on other compilers and should not be used in programs that
are intended to be portable to those compilers.
This macro meant to be used with stack-allocated structures and
non-pointer types. For the (more commonly used) pointer version, see
`g_autoptr()`.
This macro can be used to avoid having to do explicit cleanups of
local variables when exiting functions. It often vastly simplifies
handling of error conditions, removing the need for various tricks
such as `goto out` or repeating of cleanup code. It is also helpful
for non-error cases.
Consider the following example:
GVariant *
my_func(void)
{
g_auto(GQueue) queue = G_QUEUE_INIT;
g_auto(GVariantBuilder) builder;
g_auto(GStrv) strv;
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
strv = g_strsplit("a:b:c", ":", -1);
// ...
if (error_condition)
return NULL;
// ...
return g_variant_builder_end (&builder);
}
You must initialize the variable in some way — either by use of an
initialiser or by ensuring that an `_init` function will be called on
it unconditionally before it goes out of scope.
Since: 2.44
`g_autoptr(TypeName)`
: Helper to declare a pointer variable with automatic cleanup.
The variable is cleaned up in a way appropriate to its type when the
variable goes out of scope. The `TypeName` of the variable must support this.
The way to clean up the type must have been defined using the macro
`G_DEFINE_AUTOPTR_CLEANUP_FUNC()`.
This feature is only supported on GCC and clang. This macro is not
defined on other compilers and should not be used in programs that
are intended to be portable to those compilers.
This is meant to be used to declare pointers to types with cleanup
functions. The type of the variable is a pointer to `TypeName`. You
must not add your own `*`.
This macro can be used to avoid having to do explicit cleanups of
local variables when exiting functions. It often vastly simplifies
handling of error conditions, removing the need for various tricks
such as `goto out` or repeating of cleanup code. It is also helpful
for non-error cases.
Consider the following example:
gboolean
check_exists(GVariant *dict)
{
g_autoptr(GVariant) dirname, basename = NULL;
g_autofree gchar *path = NULL;
dirname = g_variant_lookup_value (dict, "dirname", G_VARIANT_TYPE_STRING);
if (dirname == NULL)
return FALSE;
basename = g_variant_lookup_value (dict, "basename", G_VARIANT_TYPE_STRING);
if (basename == NULL)
return FALSE;
path = g_build_filename (g_variant_get_string (dirname, NULL),
g_variant_get_string (basename, NULL),
NULL);
return g_access (path, R_OK) == 0;
}
You must initialise the variable in some way — either by use of an
initialiser or by ensuring that it is assigned to unconditionally
before it goes out of scope.
See also: `g_auto()`, `g_autofree()` and `g_steal_pointer()`.
Since: 2.44
`g_autofree`
: Macro to add an attribute to pointer variable to ensure automatic
cleanup using `g_free()`.
This macro differs from `g_autoptr()` in that it is an attribute supplied
before the type name, rather than wrapping the type definition. Instead
of using a type-specific lookup, this macro always calls `g_free()` directly.
This means it's useful for any type that is returned from `g_malloc()`.
Otherwise, this macro has similar constraints as `g_autoptr()`: only
supported on GCC and clang, the variable must be initialized, etc.
gboolean
operate_on_malloc_buf (void)
{
g_autofree guint8* membuf = NULL;
membuf = g_malloc (8192);
// Some computation on membuf
// membuf will be automatically freed here
return TRUE;
}
Since: 2.44
`g_autolist(TypeName)`
: Helper to declare a list variable with automatic deep cleanup.
The list is deeply freed, in a way appropriate to the specified type, when the
variable goes out of scope. The type must support this.
This feature is only supported on GCC and clang. This macro is not
defined on other compilers and should not be used in programs that
are intended to be portable to those compilers.
This is meant to be used to declare lists of a type with a cleanup
function. The type of the variable is a `GList *`. You
must not add your own `*`.
This macro can be used to avoid having to do explicit cleanups of
local variables when exiting functions. It often vastly simplifies
handling of error conditions, removing the need for various tricks
such as `goto out` or repeating of cleanup code. It is also helpful
for non-error cases.
See also: `g_autoslist()`, `g_autoptr()` and `g_steal_pointer()`.
Since: 2.56
`g_autoslist(TypeName)`
: Helper to declare a singly linked list variable with automatic deep cleanup.
The list is deeply freed, in a way appropriate to the specified type, when the
variable goes out of scope. The type must support this.
This feature is only supported on GCC and clang. This macro is not
defined on other compilers and should not be used in programs that
are intended to be portable to those compilers.
This is meant to be used to declare lists of a type with a cleanup
function. The type of the variable is a `GSList *`. You
must not add your own `*`.
This macro can be used to avoid having to do explicit cleanups of
local variables when exiting functions. It often vastly simplifies
handling of error conditions, removing the need for various tricks
such as `goto out` or repeating of cleanup code. It is also helpful
for non-error cases.
See also: `g_autolist()`, `g_autoptr()` and `g_steal_pointer()`.
Since: 2.56
`g_autoqueue(TypeName)`
: Helper to declare a double-ended queue variable with automatic deep cleanup.
The queue is deeply freed, in a way appropriate to the specified type, when the
variable goes out of scope. The type must support this.
This feature is only supported on GCC and clang. This macro is not
defined on other compilers and should not be used in programs that
are intended to be portable to those compilers.
This is meant to be used to declare queues of a type with a cleanup
function. The type of the variable is a `GQueue *`. You
must not add your own `*`.
This macro can be used to avoid having to do explicit cleanups of
local variables when exiting functions. It often vastly simplifies
handling of error conditions, removing the need for various tricks
such as `goto out` or repeating of cleanup code. It is also helpful
for non-error cases.
See also: `g_autolist()`, `g_autoptr()` and `g_steal_pointer()`.
Since: 2.62
## Type definition
`G_DEFINE_AUTOPTR_CLEANUP_FUNC(TypeName, func)`
: Defines the appropriate cleanup function for a pointer type.
The function will not be called if the variable to be cleaned up
contains `NULL`.
This will typically be the `_free()` or `_unref()` function for the given
type.
With this definition, it will be possible to use `g_autoptr()` with
the given `TypeName`.
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GObject, g_object_unref)
This macro should be used unconditionally; it is a no-op on compilers
where cleanup is not supported.
Since: 2.44
`G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(TypeName, func)`
: Defines the appropriate cleanup function for a type.
This will typically be the `_clear()` function for the given type.
With this definition, it will be possible to use `g_auto()` with
the given `TypeName`.
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GQueue, g_queue_clear)
This macro should be used unconditionally; it is a no-op on compilers
where cleanup is not supported.
Since: 2.44
`G_DEFINE_AUTO_CLEANUP_FREE_FUNC(TypeName, func, none_value)`
: Defines the appropriate cleanup function for a type.
With this definition, it will be possible to use `g_auto()` with the
given `TypeName`.
This function will be rarely used. It is used with pointer-based
typedefs and non-pointer types where the value of the variable
represents a resource that must be freed. Two examples are `GStrv`
and file descriptors.
`none_value` specifies the "none" value for the type in question. It
is probably something like `NULL` or `-1`.If the variable is found to
contain this value then the free function will not be called.
G_DEFINE_AUTO_CLEANUP_FREE_FUNC(GStrv, g_strfreev, NULL)
This macro should be used unconditionally; it is a no-op on compilers
where cleanup is not supported.
Since: 2.44

View File

@ -0,0 +1,174 @@
Title: Building GLib
# Building GLib
GLib uses the [Meson build system](https://mesonbuild.com). The normal
sequence for compiling and installing the GLib library is thus:
$ meson setup _build
$ meson compile -C _build
$ meson install -C _build
On FreeBSD, you will need something more complex:
$ env CPPFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib -Wl,--disable-new-dtags" \
> meson setup \
> -Dxattr=false \
> -Dinstalled_tests=true \
> -Db_lundef=false \
> _build
$ meson compile -C _build
The standard options provided by Meson may be passed to the `meson` command. Please see the Meson documentation or run:
meson configure --help
for information about the standard options.
GLib is compiled with
[strict aliasing](https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fstrict-aliasing)
disabled. It is strongly recommended that this is not re-enabled by overriding
the compiler flags, as GLib has not been tested with strict aliasing and cannot
be guaranteed to work.
## Dependencies
Before you can compile the GLib library, you need to have various other
tools and libraries installed on your system. If you are building from a
release archive, you will need a [compliant C
toolchain](https://gitlab.gnome.org/GNOME/glib/-/blob/main/docs/toolchain-requirements.md),
Meson, and pkg-config; the requirements are the same when building from a
Git repository clone of GLib.
- [`pkg-config`](https://www.freedesktop.org/wiki/Software/pkg-config/) is a
tool for tracking the compilation flags needed for libraries that are used
by the GLib library. (For each library, a small `.pc` text file is
installed in a standard location that contains the compilation flags
needed for that library along with version number information).
A UNIX build of GLib requires that the system implements at least the
original 1990 version of POSIX. Beyond this, it depends on a number of other
libraries.
- The [GNU libiconv library](http://www.gnu.org/software/libiconv/) is
needed to build GLib if your system doesn't have the `iconv()` function
for doing conversion between character encodings. Most modern systems
should have `iconv()`, however many older systems lack an `iconv()`
implementation. On such systems, you must install the libiconv library.
This can be found at: http://www.gnu.org/software/libiconv.
If your system has an `iconv()` implementation but you want to use libiconv
instead, make sure it is installed to the default compiler header/library
search path (for instance, in `/usr/local/`). The `iconv.h` that libiconv
installs hides the system iconv. Meson then detects this, recognizes that the
system iconv is unusable and the external one is mandatory, and automatically
forces it to be used.
If you are using the native iconv implementation on Solaris instead of
libiconv, you'll need to make sure that you have the converters between
locale encodings and UTF-8 installed. At a minimum you'll need the
SUNWuiu8 package. You probably should also install the SUNWciu8, SUNWhiu8,
SUNWjiu8, and SUNWkiu8 packages.
The native iconv on Compaq Tru64 doesn't contain support for UTF-8, so
you'll need to use GNU libiconv instead. (When using GNU libiconv for
GLib, you'll need to use GNU libiconv for GNU gettext as well.) This
probably applies to related operating systems as well.
- Python 3.5 or newer is required. Your system Python must conform to
[PEP 394](https://www.python.org/dev/peps/pep-0394/) For FreeBSD, this means
that the `lang/python3` port must be installed.
- The libintl library from the [GNU
gettext](http://www.gnu.org/software/gettext) package is needed if your
system doesn't have the `gettext()` functionality for handling message
translation databases.
- A thread implementation is needed. The thread support in GLib can be based
upon POSIX threads or win32 threads.
- GRegex uses the [PCRE library](http://www.pcre.org/) for regular
expression matching. The system version of PCRE is used, unless not available
(which is the case on Android), in which case a fallback subproject is used.
- The optional extended attribute support in GIO requires the `getxattr()`
family of functions that may be provided by the C library or by the
standalone libattr library. To build GLib without extended attribute
support, use the `-Dxattr=false` option.
- The optional SELinux support in GIO requires libselinux. To build GLib
without SELinux support, use the `-Dselinux=disabled` option.
- The optional support for DTrace requires the `sys/sdt.h` header, which is
provided by SystemTap on Linux. To build GLib without DTrace, use the
`-Ddtrace=false` option.
- The optional support for SystemTap can be disabled with the
`-Dsystemtap=false` option. Additionally, you can control the location
where GLib installs the SystemTap probes, using the
`-Dtapset_install_dir=DIR` option.
## Extra Configuration Options
In addition to the normal options, these additional ones are supported when
configuring the GLib library:
`--buildtype`
: This is a standard Meson option which specifies how much debugging and
optimization to enable. If the build type is `debug`, `G_ENABLE_DEBUG` will be
defined and GLib will be built with additional debug code enabled. You can
override this behavior using `-Dglib_debug`.
`-Dforce_posix_threads=true`
: Normally, Meson should be able to work out the correct thread implementation
to use. This option forces POSIX threads to be used even if the platform
provides another threading API (for example, on Windows).
`-Dbsymbolic_functions=false` and `-Dbsymbolic_functions=true`
: By default, GLib uses the `-Bsymbolic-functions` linker flag to avoid
intra-library PLT jumps. A side-effect of this is that it is no longer
possible to override internal uses of GLib functions with `LD_PRELOAD`.
Therefore, it may make sense to turn this feature off in some
situations. The `-Dbsymbolic_functions=false` option allows to do that.
`-Dgtk_doc=false` and `-Dgtk_doc=true`
: By default, GLib will detect whether the gtk-doc package is installed.
If it is, then it will use it to extract and build the documentation
for the GLib library. These options can be used to explicitly control
whether gtk-doc should be used or not. If it is not used, the
distributed, pre-generated HTML files will be installed instead of
building them on your machine.
`-Dman=false` and `-Dman=true`
: By default, GLib will detect whether `xsltproc` and the necessary DocBook
stylesheets are installed. If they are, then it will use them to rebuild
the included man pages from the XML sources. These options can be used to
explicitly control whether man pages should be rebuilt used or not. The
distribution includes pre-generated man pages.
`-Dxattr=false` and `-Dxattr=true`
: By default, GLib will detect whether the `getxattr()` family of functions is
available. If it is, then extended attribute support will be included in
GIO. These options can be used to explicitly control whether extended
attribute support should be included or not. `getxattr()` and friends can be
provided by glibc or by the standalone libattr library.
`-Dselinux=auto`, `-Dselinux=enabled` or `-Dselinux=disabled`
: By default, GLib will detect if libselinux is available and include SELinux
support in GIO if it is. These options can be used to explicitly control
whether SELinux support should be included.
`-Ddtrace=false` and `-Ddtrace=true`
: By default, GLib will detect if DTrace support is available, and use it.
These options can be used to explicitly control whether DTrace support is
compiled into GLib.
`-Dsystemtap=false` and `-Dsystemtap=true`
: This option requires DTrace support. If it is available, then GLib will also
check for the presence of SystemTap.
`-Db_coverage=true` and `-Db_coverage=false`
: Enable the generation of coverage reports for the GLib tests. This requires
the lcov frontend to gcov from the Linux Test Project. To generate a
coverage report, use `ninja coverage-html`. The report is placed in the
`meson-logs` directory.

View File

@ -1,339 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<refentry id="glib-building">
<refmeta>
<refentrytitle>Compiling the GLib package</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>GLib Library</refmiscinfo>
</refmeta>
<refnamediv>
<refname>Compiling the GLib Package</refname>
<refpurpose>How to compile GLib itself</refpurpose>
</refnamediv>
<refsect1 id="building">
<title>Building the Library on UNIX</title>
<para>
On UNIX, GLib uses the standard <application>Meson</application> build
system. The normal sequence for compiling and installing the GLib library
is thus:
<literallayout>
<userinput>meson setup _build</userinput>
<userinput>meson compile -C _build</userinput>
<userinput>meson install -C _build</userinput>
</literallayout>
On FreeBSD:
<literallayout>
<userinput>env CPPFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib -Wl,--disable-new-dtags" meson setup -Dxattr=false -Dinstalled_tests=true -Db_lundef=false _build</userinput>
<userinput>meson compile -C _build</userinput>
</literallayout>
</para>
<para>
The standard options provided by <application>Meson</application> may be
passed to the <command>meson</command> command. Please see the
<application>Meson</application> documentation or run
<command>meson configure --help</command> for information about
the standard options.
</para>
<para>
GLib is compiled with
<ulink url="https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fstrict-aliasing">strict aliasing</ulink>
disabled. It is strongly recommended that this is not re-enabled by
overriding the compiler flags, as GLib has not been tested with strict
aliasing and cannot be guaranteed to work.
</para>
<para>
The GTK documentation contains
<ulink url="https://developer.gnome.org/gtk3/stable/gtk-building.html">further details</ulink>
about the build process and ways to influence it.
</para>
</refsect1>
<refsect1 id="dependencies">
<title>Dependencies</title>
<para>
Before you can compile the GLib library, you need to have
various other tools and libraries installed on your system.
If you are building from a release archive, you will need
<ulink url="https://gitlab.gnome.org/GNOME/glib/-/blob/main/docs/toolchain-requirements.md">a compliant C toolchain</ulink>,
<application>Meson</application>, and <application>pkg-config</application>;
the requirements are the same when building from a Git repository clone
of GLib.
</para>
<itemizedlist>
<listitem>
<para>
<ulink url="https://www.freedesktop.org/wiki/Software/pkg-config/">pkg-config</ulink>
is a tool for tracking the compilation flags needed for
libraries that are used by the GLib library. (For each
library, a small <literal>.pc</literal> text file is
installed in a standard location that contains the compilation
flags needed for that library along with version number
information).
</para>
</listitem>
</itemizedlist>
<para>
A UNIX build of GLib requires that the system implements at
least the original 1990 version of POSIX. Beyond this, it
depends on a number of other libraries.
</para>
<itemizedlist>
<listitem>
<para>
The <ulink url="http://www.gnu.org/software/libiconv/">GNU
libiconv library</ulink> is needed to build GLib if your
system doesn't have the <function>iconv()</function>
function for doing conversion between character
encodings. Most modern systems should have
<function>iconv()</function>, however many older systems lack
an <function>iconv()</function> implementation. On such systems,
you must install the libiconv library. This can be found at:
<ulink url="http://www.gnu.org/software/libiconv">http://www.gnu.org/software/libiconv</ulink>.
</para>
<para>
If your system has an <function>iconv()</function> implementation but
you want to use libiconv instead, make sure it is installed to the
default compiler header/library search path (for instance, in
<filename>/usr/local/</filename>). The <filename>iconv.h</filename>
that libiconv installs hides the system iconv. Meson then detects
this, recognizes that the system iconv is unusable and the external
one is mandatory, and automatically forces it to be used.
</para>
<para>
If you are using the native iconv implementation on Solaris
instead of libiconv, you'll need to make sure that you have
the converters between locale encodings and UTF-8 installed.
At a minimum you'll need the SUNWuiu8 package. You probably
should also install the SUNWciu8, SUNWhiu8, SUNWjiu8, and
SUNWkiu8 packages.
</para>
<para>
The native iconv on Compaq Tru64 doesn't contain support for
UTF-8, so you'll need to use GNU libiconv instead. (When
using GNU libiconv for GLib, you'll need to use GNU libiconv
for GNU gettext as well.) This probably applies to related
operating systems as well.
</para>
</listitem>
<listitem>
<para>
Python 3.5 or newer is required. Your system Python must
conform to <ulink
url="https://www.python.org/dev/peps/pep-0394/">PEP 394
</ulink>
For FreeBSD, this means that the
<literal>lang/python3</literal> port must be installed.
</para>
</listitem>
<listitem>
<para>
The libintl library from the <ulink
url="http://www.gnu.org/software/gettext">GNU gettext
package</ulink> is needed if your system doesn't have the
<function>gettext()</function> functionality for handling
message translation databases.
</para>
</listitem>
<listitem>
<para>
A thread implementation is needed. The thread support in GLib
can be based upon POSIX threads or win32 threads.
</para>
</listitem>
<listitem>
<para>
GRegex uses the <ulink url="http://www.pcre.org/">PCRE library</ulink>
for regular expression matching. The system version of PCRE is used,
unless not available (which is the case on Android), in which case a
fallback subproject is used.
</para>
</listitem>
<listitem>
<para>
The optional extended attribute support in GIO requires the
<function>getxattr()</function> family of functions that may be
provided by the C library or by the standalone libattr library. To
build GLib without extended attribute support, use the
<option>-Dxattr=false</option> option.
</para>
</listitem>
<listitem>
<para>
The optional SELinux support in GIO requires libselinux.
To build GLib without SELinux support, use the
<option>-Dselinux=disabled</option> option.
</para>
</listitem>
<listitem>
<para>
The optional support for DTrace requires the
<filename>sys/sdt.h</filename> header, which is provided
by SystemTap on Linux. To build GLib without DTrace, use
the <option>-Ddtrace=false</option> option.
</para>
</listitem>
<listitem>
<para>
The optional support for
<ulink url="http://sourceware.org/systemtap/">SystemTap</ulink>
can be disabled with the <option>-Dsystemtap=false</option>
option. Additionally, you can control the location
where GLib installs the SystemTap probes, using the
<option>-Dtapset_install_dir=DIR</option> option.
</para>
</listitem>
</itemizedlist>
</refsect1>
<refsect1 id="extra-configuration-options">
<title>Extra Configuration Options</title>
<para>
In addition to the normal options, these additional ones are supported
when configuring the GLib library:
</para>
<formalpara>
<title><option>--buildtype</option></title>
<para>
This is a standard <application>Meson</application> option which
specifies how much debugging and optimization to enable. If the build
type is <literal>debug</literal>,
<literal>G_ENABLE_DEBUG</literal> will be defined and GLib will be built
with additional debug code enabled. You can override this behavior using
<option>-Dglib_debug</option>.
</para>
</formalpara>
<formalpara>
<title><option>-Dforce_posix_threads=true</option></title>
<para>
Normally, <application>Meson</application> should be able to work out
the correct thread implementation to use. This option forces POSIX
threads to be used even if the platform provides another threading API
(for example, on Windows).
</para>
</formalpara>
<formalpara>
<title><option>-Dbsymbolic_functions=false</option> and
<option>-Dbsymbolic_functions=true</option></title>
<para>
By default, GLib uses the <option>-Bsymbolic-functions</option>
linker flag to avoid intra-library PLT jumps. A side-effect
of this is that it is no longer possible to override
internal uses of GLib functions with
<envar>LD_PRELOAD</envar>. Therefore, it may make
sense to turn this feature off in some situations.
The <option>-Dbsymbolic_functions=false</option> option allows
to do that.
</para>
</formalpara>
<formalpara>
<title><option>-Dgtk_doc=false</option> and
<option>-Dgtk_doc=true</option></title>
<para>
By default, GLib will detect whether the
<application>gtk-doc</application> package is installed.
If it is, then it will use it to extract and build the
documentation for the GLib library. These options
can be used to explicitly control whether
<application>gtk-doc</application> should be
used or not. If it is not used, the distributed,
pre-generated HTML files will be installed instead of
building them on your machine.
</para>
</formalpara>
<formalpara>
<title><option>-Dman=false</option> and
<option>-Dman=true</option></title>
<para>
By default, GLib will detect whether <application>xsltproc</application>
and the necessary DocBook stylesheets are installed.
If they are, then it will use them to rebuild the included
man pages from the XML sources. These options can be used
to explicitly control whether man pages should be rebuilt
used or not. The distribution includes pre-generated man
pages.
</para>
</formalpara>
<formalpara>
<title><option>-Dxattr=false</option> and
<option>-Dxattr=true</option></title>
<para>
By default, GLib will detect whether the
<function>getxattr()</function>
family of functions is available. If it is, then extended
attribute support will be included in GIO. These options can
be used to explicitly control whether extended attribute
support should be included or not. <function>getxattr()</function>
and friends can be provided by glibc or by the standalone
libattr library.
</para>
</formalpara>
<formalpara>
<title><option>-Dselinux=auto</option>,
<option>-Dselinux=enabled</option> or
<option>-Dselinux=disabled</option></title>
<para>
By default, GLib will detect if libselinux is available and
include SELinux support in GIO if it is. These options can be
used to explicitly control whether SELinux support should
be included.
</para>
</formalpara>
<formalpara>
<title><option>-Ddtrace=false</option> and
<option>-Ddtrace=true</option></title>
<para>
By default, GLib will detect if DTrace support is available, and use it.
These options can be used to explicitly control whether DTrace support
is compiled into GLib.
</para>
</formalpara>
<formalpara>
<title><option>-Dsystemtap=false</option> and
<option>-Dsystemtap=true</option></title>
<para>
This option requires DTrace support. If it is available, then
GLib will also check for the presence of SystemTap.
</para>
</formalpara>
<formalpara>
<title><option>-Db_coverage=true</option> and
<option>-Db_coverage=false</option></title>
<para>
Enable the generation of coverage reports for the GLib tests.
This requires the lcov frontend to gcov from the
<ulink url="http://ltp.sourceforge.net">Linux Test Project</ulink>.
To generate a coverage report, use
<command>ninja coverage-html</command>. The report is placed in the
<filename>meson-logs</filename> directory.
</para>
</formalpara>
</refsect1>
</refentry>

View File

@ -0,0 +1,91 @@
Title: Character set conversions
SPDX-License-Identifier: LGPL-2.1-or-later
SPDX-FileCopyrightText: 2010, 2012, 2014 Matthias Clasen
# Character set conversions
The [`func@GLib.convert`] family of function wraps the functionality of
iconv(). In addition to pure character set conversions, GLib has functions
to deal with the extra complications of encodings for file names.
## File Name Encodings
Historically, UNIX has not had a defined encoding for file names: a file
name is valid as long as it does not have path separators in it ("/").
However, displaying file names may require conversion: from the character
set in which they were created, to the character set in which the
application operates. Consider the Spanish file name "Presentación.sxi". If
the application which created it uses ISO-8859-1 for its encoding,
```
Character: P r e s e n t a c i ó n . s x i
Hex code: 50 72 65 73 65 6e 74 61 63 69 f3 6e 2e 73 78 69
```
However, if the application use UTF-8, the actual file name on disk would
look like this:
```
Character: P r e s e n t a c i ó n . s x i
Hex code: 50 72 65 73 65 6e 74 61 63 69 c3 b3 6e 2e 73 78 69
```
Glib uses UTF-8 for its strings, and GUI toolkits like GTK that use GLib do
the same thing. If you get a file name from the file system, for example,
from `readdir()` or from [`method@GLib.Dir.read_name`], and you wish to
display the file name to the user, you will need to convert it into UTF-8.
The opposite case is when the user types the name of a file they wish to
save: the toolkit will give you that string in UTF-8 encoding, and you will
need to convert it to the character set used for file names before you can
create the file with `open()` or `fopen()`.
By default, GLib assumes that file names on disk are in UTF-8 encoding. This
is a valid assumption for file systems which were created relatively
recently: most applications use UTF-8 encoding for their strings, and that
is also what they use for the file names they create. However, older file
systems may still contain file names created in "older" encodings, such as
ISO-8859-1. In this case, for compatibility reasons, you may want to
instruct GLib to use that particular encoding for file names rather than
UTF-8. You can do this by specifying the encoding for file names in the
`G_FILENAME_ENCODING` environment variable. For example, if your installation
uses ISO-8859-1 for file names, you can put this in your `~/.profile`:
export G_FILENAME_ENCODING=ISO-8859-1
GLib provides the functions [`func@GLib.filename_to_utf8`] and
[`func@GLib.filename_from_utf8`] to perform the necessary conversions. These
functions convert file names from the encoding specified in
`G_FILENAME_ENCODING` to UTF-8 and vice-versa. This diagram illustrates how
these functions are used to convert between UTF-8 and the encoding for file
names in the file system.
## Conversion between file name encodings
![](file-name-encodings.png)
## Checklist for Application Writers
This section is a practical summary of the detailed things to do to make
sure your applications process file name encodings correctly.
1. If you get a file name from the file system from a function such as
`readdir()` or `gtk_file_chooser_get_filename()`, you do not need to do
any conversion to pass that file name to functions like `open()`,
`rename()`, or `fopen()` -- those are "raw" file names which the file
system understands.
2. If you need to display a file name, convert it to UTF-8 first by using
[`func@GLib.filename_to_utf8`]. If conversion fails, display a string
like "Unknown file name". Do not convert this string back into the
encoding used for file names if you wish to pass it to the file system;
use the original file name instead.
3. For example, the document window of a word processor could display
"Unknown file name" in its title bar but still let the user save the
file, as it would keep the raw file name internally. This can happen if
the user has not set the `G_FILENAME_ENCODING` environment variable even
though he has files whose names are not encoded in UTF-8.
4. If your user interface lets the user type a file name for saving or
renaming, convert it to the encoding used for file names in the file
system by using [`func@GLib.filename_from_utf8`]. Pass the converted file
name to functions like `fopen()`. If conversion fails, ask the user to
enter a different file name. This can happen if the user types Japanese
characters when `G_FILENAME_ENCODING` is set to ISO-8859-1, for example.

View File

@ -0,0 +1,71 @@
Title: Compiling GLib Applications
# Compiling GLib Applications
To compile a GLib application, you need to tell the compiler where to find
the GLib header files and libraries. This is done with the
[`pkg-config`](https://www.freedesktop.org/wiki/Software/pkg-config/)
utility.
The following interactive shell session demonstrates how pkg-config is used
(the actual output on your system may be different):
$ pkg-config --cflags glib-2.0
-I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
$ pkg-config --libs glib-2.0
-L/usr/lib -lm -lglib-2.0
See the `pkg-config` website for more information about `pkg-config`.
If your application uses or GObject features, it must be compiled and linked
with the options returned by the following `pkg-config` invocation:
$ pkg-config --cflags --libs gobject-2.0
If your application uses modules, it must be compiled and linked with the
options returned by one of the following pkg-config invocations:
$ pkg-config --cflags --libs gmodule-no-export-2.0
$ pkg-config --cflags --libs gmodule-2.0
The difference between the two is that `gmodule-2.0` adds `--export-dynamic`
to the linker flags, which is often not needed.
The simplest way to compile a program is to use the "backticks" feature of
the shell. If you enclose a command in backticks (not single quotes), then
its output will be substituted into the command line before execution. So to
compile a GLib Hello, World, you would type the following:
$ cc `pkg-config --cflags glib-2.0` hello.c -o hello `pkg-config --libs glib-2.0`
Deprecated GLib functions are annotated to make the compiler emit warnings
when they are used (e.g. with GCC, you need to use the
`-Wdeprecated-declarations option`). If these warnings are problematic, they
can be turned off by defining the preprocessor symbol
`GLIB_DISABLE_DEPRECATION_WARNINGS` by using the commandline option
`-DGLIB_DISABLE_DEPRECATION_WARNINGS`
GLib deprecation annotations are versioned; by defining the macros
`GLIB_VERSION_MIN_REQUIRED` and `GLIB_VERSION_MAX_ALLOWED`, you can specify the
range of GLib versions whose API you want to use. APIs that were deprecated
before or introduced after this range will trigger compiler warnings.
Since GLib 2.62, the older deprecation mechanism of hiding deprecated
interfaces entirely from the compiler by using the preprocessor symbol
`G_DISABLE_DEPRECATED` has been removed. All deprecations are now handled
using the above mechanism.
The recommended way of using GLib has always been to only include the
toplevel headers `glib.h`, `glib-object.h`, `gio.h`. Starting with 2.32, GLib
enforces this by generating an error when individual headers are directly
included.
Still, there are some exceptions; these headers have to be included
separately:
- `gmodule.h`
- `glib-unix.h`
- `glib/gi18n-lib.h` or `glib/gi18n.h` (see the section on
[Internationalization](i18n.html))
- `glib/gprintf.h` and `glib/gstdio.h` (we don't want to pull in all of
stdio)

View File

@ -1,125 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<refentry id="glib-compiling" revision="17 Jan 2002">
<refmeta>
<refentrytitle>Compiling GLib Applications</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>GLib Library</refmiscinfo>
</refmeta>
<refnamediv>
<refname>Compiling GLib Applications</refname>
<refpurpose>
How to compile your GLib application
</refpurpose>
</refnamediv>
<refsect1>
<title>Compiling GLib Applications on UNIX</title>
<para>
To compile a GLib application, you need to tell the compiler where to
find the GLib header files and libraries. This is done with the
<application>pkg-config</application> utility.
</para>
<para>
The following interactive shell session demonstrates how
<application>pkg-config</application> is used (the actual output on
your system may be different):
<programlisting>
$ pkg-config --cflags glib-2.0
-I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
$ pkg-config --libs glib-2.0
-L/usr/lib -lm -lglib-2.0
</programlisting>
</para>
<para>
See the <ulink url="http://www.freedesktop.org/wiki/Software/pkg-config">pkg-config website</ulink>
for more information about <application>pkg-config</application>.
</para>
<para>
If your application uses or <structname>GObject</structname>
features, it must be compiled and linked with the options returned
by the following <application>pkg-config</application> invocation:
<programlisting>
$ pkg-config --cflags --libs gobject-2.0
</programlisting>
</para>
<para>
If your application uses modules, it must be compiled and linked
with the options returned by one of the following
<application>pkg-config</application> invocations:
<programlisting>
$ pkg-config --cflags --libs gmodule-no-export-2.0
$ pkg-config --cflags --libs gmodule-2.0
</programlisting>
The difference between the two is that gmodule-2.0 adds
<option>--export-dynamic</option> to the linker flags,
which is often not needed.
</para>
<para>
The simplest way to compile a program is to use command substitution
feature of a shell. A command written in the format
<literal>$(command)</literal> gets substituted into the command line
before execution. So to compile a GLib Hello, World, you would type
the following:
<programlisting>
$ cc hello.c $(pkg-config --cflags --libs glib-2.0) -o hello
</programlisting>
</para>
<note><para>
Note that the name of the file must come before the other options
(such as <emphasis>pkg-config</emphasis>), or else you may get an
error from the linker.
</para></note>
<para>
Deprecated GLib functions are annotated to make the compiler
emit warnings when they are used (e.g. with gcc, you need to use
the -Wdeprecated-declarations option). If these warnings are
problematic, they can be turned off by defining the preprocessor
symbol %GLIB_DISABLE_DEPRECATION_WARNINGS by using the commandline
option <literal>-DGLIB_DISABLE_DEPRECATION_WARNINGS</literal>
</para>
<para>
GLib deprecation annotations are versioned; by defining the
macros %GLIB_VERSION_MIN_REQUIRED and %GLIB_VERSION_MAX_ALLOWED,
you can specify the range of GLib versions whose API you want
to use. APIs that were deprecated before or introduced after
this range will trigger compiler warnings.
</para>
<para>
Since GLib 2.62, the older deprecation mechanism of hiding deprecated interfaces
entirely from the compiler by using the preprocessor symbol
<literal>G_DISABLE_DEPRECATED</literal> has been removed. All deprecations
are now handled using the above mechanism.
</para>
<para>
The recommended way of using GLib has always been to only include the
toplevel headers <filename>glib.h</filename>,
<filename>glib-object.h</filename>, <filename>gio.h</filename>.
Starting with 2.32, GLib enforces this by generating an error
when individual headers are directly included.
</para>
<para>
Still, there are some exceptions; these headers have to be included
separately:
<filename>gmodule.h</filename>,
<filename>glib-unix.h</filename>,
<filename>glib/gi18n-lib.h</filename> or
<filename>glib/gi18n.h</filename> (see
the <link linkend="glib-I18N">Internationalization section</link>),
<filename>glib/gprintf.h</filename> and
<filename>glib/gstdio.h</filename>
(we don't want to pull in all of stdio).
</para>
</refsect1>
</refentry>

View File

@ -0,0 +1,281 @@
Title: Conversion Macros
# Conversion Macros
## Type Conversion
Many times GLib, GTK, and other libraries allow you to pass "user data" to a
callback, in the form of a void pointer. From time to time you want to pass
an integer instead of a pointer. You could allocate an integer, with
something like:
```c
int *ip = g_new (int, 1);
*ip = 42;
```
But this is inconvenient, and it's annoying to have to free the memory at
some later time.
Pointers are always at least 32 bits in size (on all platforms GLib intends
to support). Thus you can store at least 32-bit integer values in a pointer
value. Naively, you might try this, but it's incorrect:
```c
gpointer p;
int i;
p = (void*) 42;
i = (int) p;
```
Again, that example was not correct, don't copy it.
The problem is that on some systems you need to do this:
```c
gpointer p;
int i;
p = (void*) (long) 42;
i = (int) (long) p;
```
The GLib macros `GPOINTER_TO_INT()`, `GINT_TO_POINTER()`, etc. take care to
do the right thing on every platform.
**Warning**: You may not store pointers in integers. This is not portable in
any way, shape or form. These macros only allow storing integers in
pointers, and only preserve 32 bits of the integer; values outside the range
of a 32-bit integer will be mangled.
``GINT_TO_POINTER(value)``, ``GPOINTER_TO_INT(value)``
: Stuffs an integer into a pointer type, and vice versa. Remember, you may not
store pointers in integers. This is not portable in any way, shape or form.
These macros only allow storing integers in pointers, and only preserve 32
bits of the integer; values outside the range of a 32-bit integer will be
mangled.
``GUINT_TO_POINTER(value)``, ``GPOINTER_TO_UINT(value)``
: Stuffs an unsigned integer into a pointer type, and vice versa.
``GSIZE_TO_POINTER(value)``, ``GPOINTER_TO_SIZE(value)``
: Stuffs a `size_t` into a pointer type, and vice versa.
## Byte Order Conversion
These macros provide a portable way to determine the host byte order and to
convert values between different byte orders.
The byte order is the order in which bytes are stored to create larger data
types such as the #gint and #glong values. The host byte order is the byte
order used on the current machine.
Some processors store the most significant bytes (i.e. the bytes that hold
the largest part of the value) first. These are known as big-endian
processors. Other processors (notably the x86 family) store the most
significant byte last. These are known as little-endian processors.
Finally, to complicate matters, some other processors store the bytes in a
rather curious order known as PDP-endian. For a 4-byte word, the 3rd most
significant byte is stored first, then the 4th, then the 1st and finally the
2nd.
Obviously there is a problem when these different processors communicate
with each other, for example over networks or by using binary file formats.
This is where these macros come in. They are typically used to convert
values into a byte order which has been agreed on for use when communicating
between different processors. The Internet uses what is known as 'network
byte order' as the standard byte order (which is in fact the big-endian byte
order).
Note that the byte order conversion macros may evaluate their arguments
multiple times, thus you should not use them with arguments which have
side-effects.
`G_BYTE_ORDER`
: The host byte order. This can be either `G_LITTLE_ENDIAN` or `G_BIG_ENDIAN`.
`G_LITTLE_ENDIAN`
: Specifies the little endian byte order.
`G_BIG_ENDIAN`
: Specifies the big endian byte order.
`G_PDP_ENDIAN`
: Specifies the PDP endian byte order.
### Signed
`GINT_FROM_BE(value)`
: Converts an `int` value from big-endian to host byte order.
`GINT_FROM_LE(value)`
: Converts an `int` value from little-endian to host byte order.
`GINT_TO_BE(value)`
: Converts an `int` value from host byte order to big-endian.
`GINT_TO_LE(value)`
: Converts an `int` value from host byte order to little-endian.
`GLONG_FROM_BE(value)`
: Converts a `long` value from big-endian to the host byte order.
`GLONG_FROM_LE(value)`
: Converts a `long` value from little-endian to host byte order.
`GLONG_TO_BE(value)`
: Converts a `long` value from host byte order to big-endian.
`GLONG_TO_LE(value)`
: Converts a `long` value from host byte order to little-endian.
`GSSIZE_FROM_BE(value)`
: Converts a `ssize_t` value from big-endian to host byte order.
`GSSIZE_FROM_LE(value)`
: Converts a `ssize_t` value from little-endian to host byte order.
`GSSIZE_TO_BE(value)`
: Converts a `ssize_t` value from host byte order to big-endian.
`GSSIZE_TO_LE(value)`
: Converts a `ssize_t` value from host byte order to little-endian.
`GINT16_FROM_BE(value)`
: Converts an `int16_t` value from big-endian to host byte order.
`GINT16_FROM_LE(value)`
: Converts an `int16_t` value from little-endian to host byte order.
`GINT16_TO_BE(value)`
: Converts an `int16_t` value from host byte order to big-endian.
`GINT16_TO_LE(value)`
: Converts an `int16_t` value from host byte order to little-endian.
`GINT32_FROM_BE(value)`
: Converts an `int32_t` value from big-endian to host byte order.
`GINT32_FROM_LE(value)`
: Converts an `int32_t` value from little-endian to host byte order.
`GINT32_TO_BE(value)`
: Converts an `int32_t` value from host byte order to big-endian.
`GINT32_TO_LE(value)`
: Converts an `int32_t` value from host byte order to little-endian.
`GINT64_FROM_BE(value)`
: Converts an `int64_t` value from big-endian to host byte order.
`GINT64_FROM_LE(value)`
: Converts an `int64_t` value from little-endian to host byte order.
`GINT64_TO_BE(value)`
: Converts an `int64_t` value from host byte order to big-endian.
`GINT64_TO_LE(value)`
: Converts an `int64_t` value from host byte order to little-endian.
### Unsigned
`GUINT_FROM_BE(value)`
: Converts an `unsigned int` value from big-endian to host byte order.
`GUINT_FROM_LE(value)`
: Converts an `unsigned int` value from little-endian to host byte order.
`GUINT_TO_BE(value)`
: Converts an `unsigned int` value from host byte order to big-endian.
`GUINT_TO_LE(value)`
: Converts an `unsigned int` value from host byte order to little-endian.
`GULONG_FROM_BE(value)`
: Converts an `unsigned long` value from big-endian to host byte order.
`GULONG_FROM_LE(value)`
: Converts an `unsigned long` value from little-endian to host byte order.
`GULONG_TO_BE(value)`
: Converts an `unsigned long` value from host byte order to big-endian.
`GULONG_TO_LE(value)`
: Converts an `unsigned long` value from host byte order to little-endian.
`GSIZE_FROM_BE(value)`
: Converts a `size_t` value from big-endian to the host byte order.
`GSIZE_FROM_LE(value)`
: Converts a `size_t` value from little-endian to host byte order.
`GSIZE_TO_BE(value)`
: Converts a `size_t` value from host byte order to big-endian.
`GSIZE_TO_LE(value)`
: Converts a `size_t` value from host byte order to little-endian.
`GUINT16_FROM_BE(value)`
: Converts an `uint16_t` value from big-endian to host byte order.
`GUINT16_FROM_LE(value)`
: Converts an `uint16_t` value from little-endian to host byte order.
`GUINT16_TO_BE(value)`
: Converts an `uint16_t` value from host byte order to big-endian.
`GUINT16_TO_LE(value)`
: Converts an `uint16_t` value from host byte order to little-endian.
`GUINT32_FROM_BE(value)`
: Converts an `uint32_t` value from big-endian to host byte order.
`GUINT32_FROM_LE(value)`
: Converts an `uint32_t` value from little-endian to host byte order.
`GUINT32_TO_BE(value)`
: Converts an `uint32_t` value from host byte order to big-endian.
`GUINT32_TO_LE(value)`
: Converts an `uint32_t` value from host byte order to little-endian.
`GUINT64_FROM_BE(value)`
: Converts an `uint64_t` value from big-endian to host byte order.
`GUINT64_FROM_LE(value)`
: Converts an `uint64_t` value from little-endian to host byte order.
`GUINT64_TO_BE(value)`
: Converts an `uint64_t` value from host byte order to big-endian.
`GUINT64_TO_LE(value)`
: Converts an `uint64_t` value from host byte order to little-endian.
`GUINT16_SWAP_BE_PDP(value)`
: Converts an `uint16_t` value between big-endian and pdp-endian byte order.
The conversion is symmetric so it can be used both ways.
`GUINT16_SWAP_LE_BE(value)`
: Converts an `uint16_t` value between little-endian and big-endian byte order.
The conversion is symmetric so it can be used both ways.
`GUINT16_SWAP_LE_PDP(value)`
: Converts an `uint16_t` value between little-endian and pdp-endian byte order.
The conversion is symmetric so it can be used both ways.
`GUINT32_SWAP_BE_PDP(value)`
: Converts an `uint32_t` value between big-endian and pdp-endian byte order.
The conversion is symmetric so it can be used both ways.
`GUINT32_SWAP_LE_BE(value)`
: Converts an `uint32_t` value between little-endian and big-endian byte order.
The conversion is symmetric so it can be used both ways.
`GUINT32_SWAP_LE_PDP(value)`
: Converts an `uint32_t` value between little-endian and pdp-endian byte order.
The conversion is symmetric so it can be used both ways.
`GUINT64_SWAP_LE_BE(value)`
: Converts a `uint64_t` value between little-endian and big-endian byte order.
The conversion is symmetric so it can be used both ways.

View File

@ -0,0 +1,88 @@
Title: Cross-compiling the GLib package
# Cross-compiling the GLib Package
## Building the Library for a different architecture
Cross-compilation is the process of compiling a program or library on a
different architecture or operating system then it will be run upon. GLib is
slightly more difficult to cross-compile than many packages because much of
GLib is about hiding differences between different systems.
These notes cover things specific to cross-compiling GLib; for general
information about cross-compilation, see the [Meson
documentation](http://mesonbuild.com/Cross-compilation.html).
GLib tries to detect as much information as possible about the target system
by compiling and linking programs without actually running anything;
however, some information GLib needs is not available this way. This
information needs to be provided to meson via a cross file.
As an example of using a cross file, to cross compile for the MingW32
Win64 runtime environment on a Linux system, create a file `cross_file.txt`
with the following contents:
```
[host_machine]
system = 'windows'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'
[properties]
c_args = []
c_link_args = []
[binaries]
c = 'x86_64-w64-mingw32-gcc'
cpp = 'x86_64-w64-mingw32-g++'
ar = 'x86_64-w64-mingw32-ar'
ld = 'x86_64-w64-mingw32-ld'
objcopy = 'x86_64-w64-mingw32-objcopy'
strip = 'x86_64-w64-mingw32-strip'
pkgconfig = 'x86_64-w64-mingw32-pkg-config'
windres = 'x86_64-w64-mingw32-windres'
```
Then execute the following commands:
meson setup --cross-file cross_file.txt builddir
The complete list of cross properties follows. Most of these won't need to
be set in most cases.
## Cross properties
`have_[function]`
: When meson checks if a function is supported, the test can be overridden by
setting the `have_function` property to `true` or `false`. For example:
Checking for function "fsync" : YES
can be overridden by setting
have_fsync = false
`growing_stack=[true/false]`
: Whether the stack grows up or down. Most places will want `false`. A few
architectures, such as PA-RISC need `true`.
`have_strlcpy=[true/false]`
: Whether you have `strlcpy()` that matches OpenBSD. Defaults to `false`,
which is safe, since GLib uses a built-in version in that case.
`va_val_copy=[true/false]`
: Whether `va_list` can be copied as a pointer. If set to `false`, then
`memcopy()` will be used. Only matters if you don't have `va_copy()` or
`__va_copy()`. (So, doesn't matter for GCC.) Defaults to `true` which is
slightly more common than `false`.
`have_c99_vsnprintf=[true/false]`
: Whether you have a `vsnprintf()` with C99 semantics. (C99 semantics means
returning the number of bytes that would have been written had the output
buffer had enough space.) Defaults to `false`.
`have_c99_snprintf=[true/false]`
: Whether you have a `snprintf()` with C99 semantics. (C99 semantics means
returning the number of bytes that would have been written had the output
buffer had enough space.) Defaults to `false`.

View File

@ -1,147 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<refentry id="glib-cross-compiling" revision="7 Aug 2018">
<refmeta>
<refentrytitle>Cross-compiling the GLib package</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>GLib Library</refmiscinfo>
</refmeta>
<refnamediv>
<refname>Cross-compiling the GLib Package</refname>
<refpurpose>
How to cross-compile GLib
</refpurpose>
</refnamediv>
<refsect1 id="cross">
<title>Building the Library for a different architecture</title>
<para>
Cross-compilation is the process of compiling a program or
library on a different architecture or operating system then
it will be run upon. GLib is slightly more difficult to
cross-compile than many packages because much of GLib is
about hiding differences between different systems.
</para>
<para>
These notes cover things specific to cross-compiling GLib;
for general information about cross-compilation, see the
<ulink url="http://mesonbuild.com/Cross-compilation.html">meson</ulink>
info pages.
</para>
<para>
GLib tries to detect as much information as possible about
the target system by compiling and linking programs without
actually running anything; however, some information GLib
needs is not available this way. This information needs
to be provided to meson via a cross file.
</para>
<para>
As an example of using a cross file, to cross compile for
the MingW32 Win64 runtime environment on a Linux system,
create a file <filename>cross_file.txt</filename> with the following
contents:
</para>
<programlisting>
[host_machine]
system = 'windows'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'
[properties]
c_args = []
c_link_args = []
[binaries]
c = 'x86_64-w64-mingw32-gcc'
cpp = 'x86_64-w64-mingw32-g++'
ar = 'x86_64-w64-mingw32-ar'
ld = 'x86_64-w64-mingw32-ld'
objcopy = 'x86_64-w64-mingw32-objcopy'
strip = 'x86_64-w64-mingw32-strip'
pkgconfig = 'x86_64-w64-mingw32-pkg-config'
windres = 'x86_64-w64-mingw32-windres'
</programlisting>
<para>
Then execute the following commands:
</para>
<programlisting>
meson --cross-file cross_file.txt builddir
</programlisting>
<para>
The complete list of cross properties follows. Most
of these won't need to be set in most cases.
</para>
</refsect1>
<refsect1 id="cross-properties">
<title>Cross properties</title>
<formalpara>
<title>have_[function]</title>
<para>
When meson checks if a function is supported, the test can be
overridden by setting the
<literal>have_<replaceable>function</replaceable></literal> property
to <constant>true</constant> or <constant>false</constant>.
For example <programlisting>Checking for function "fsync" : YES</programlisting>
can be overridden by setting <programlisting>have_fsync = false</programlisting>
</para>
</formalpara>
<formalpara>
<title>growing_stack=[true/false]</title>
<para>
Whether the stack grows up or down. Most places will want
<constant>false</constant>.
A few architectures, such as PA-RISC need <constant>true</constant>.
</para>
</formalpara>
<formalpara>
<title>have_strlcpy=[true/false]</title>
<para>
Whether you have <function>strlcpy()</function> that matches
OpenBSD. Defaults to <constant>false</constant>, which is safe,
since GLib uses a built-in version in that case.
</para>
</formalpara>
<formalpara>
<title>va_val_copy=[true/false]</title>
<para>
Whether <type>va_list</type> can be copied as a pointer. If set
to <constant>false</constant>, then <function>memcopy()</function>
will be used. Only matters if you don't have
<function>va_copy()</function> or <function>__va_copy()</function>.
(So, doesn't matter for GCC.)
Defaults to <constant>true</constant> which is slightly more common
than <constant>false</constant>.
</para>
</formalpara>
<formalpara>
<title>have_c99_vsnprintf=[true/false]</title>
<para>
Whether you have a <function>vsnprintf()</function> with C99
semantics. (C99 semantics means returning the number of bytes
that would have been written had the output buffer had enough
space.) Defaults to <constant>false</constant>.
</para>
</formalpara>
<formalpara>
<title>have_c99_snprintf=[true/false]</title>
<para>
Whether you have a <function>snprintf()</function> with C99
semantics. (C99 semantics means returning the number of bytes
that would have been written had the output buffer had enough
space.) Defaults to <constant>false</constant>.
</para>
</formalpara>
</refsect1>
</refentry>

View File

@ -0,0 +1,487 @@
Title: Error Reporting
# Error Reporting
GLib provides a standard method of reporting errors from a called function
to the calling code. (This is the same problem solved by exceptions in other
languages.) It's important to understand that this method is both a data
type (the [`type@GLib.Error`] struct) and a set of rules. If you use
`GError` incorrectly, then your code will not properly interoperate with
other code that uses `GError`, and users of your API will probably get
confused. In most cases, using `GError` is preferred over numeric error
codes, but there are situations where numeric error codes are useful for
performance.
First and foremost: `GError` should only be used to report recoverable
runtime errors, never to report programming errors. If the programmer has
screwed up, then you should use `g_warning()`, `g_return_if_fail()`,
`g_assert()`, `g_error()`, or some similar facility. (Incidentally, remember
that the `g_error()` function should only be used for programming errors, it
should not be used to print any error reportable via `GError`.)
Examples of recoverable runtime errors are "file not found" or "failed to
parse input." Examples of programming errors are "NULL passed to `strcmp()`"
or "attempted to free the same pointer twice." These two kinds of errors are
fundamentally different: runtime errors should be handled or reported to the
user, programming errors should be eliminated by fixing the bug in the
program. This is why most functions in GLib and GTK do not use the `GError`
facility.
Functions that can fail take a return location for a `GError` as their last
argument. On error, a new `GError` instance will be allocated and returned
to the caller via this argument. For example:
```c
gboolean g_file_get_contents (const char *filename,
char **contents,
gsize *length,
GError **error);
```
If you pass a non-`NULL` value for the `error` argument, it should
point to a location where an error can be placed. For example:
```c
char *contents;
GError *err = NULL;
g_file_get_contents ("foo.txt", &contents, NULL, &err);
g_assert ((contents == NULL && err != NULL) || (contents != NULL && err == NULL));
if (err != NULL)
{
// Report error to user, and free error
g_assert (contents == NULL);
fprintf (stderr, "Unable to read file: %s\n", err->message);
g_error_free (err);
}
else
{
// Use file contents
g_assert (contents != NULL);
}
```
Note that `err != NULL` in this example is a reliable indicator of whether
`g_file_get_contents()` failed. Additionally, `g_file_get_contents()`
returns a boolean which indicates whether it was successful.
Because `g_file_get_contents()` returns `FALSE` on failure, if you
are only interested in whether it failed and don't need to display
an error message, you can pass `NULL` for the `error` argument:
```c
if (g_file_get_contents ("foo.txt", &contents, NULL, NULL)) // ignore errors
// no error occurred
;
else
// error
;
```
The `GError` object contains three fields: `domain` indicates the module the
error-reporting function is located in, `code` indicates the specific error
that occurred, and `message` is a user-readable error message with as many
details as possible. Several functions are provided to deal with an error
received from a called function: `g_error_matches()` returns `TRUE` if the
error matches a given domain and code, `g_propagate_error()` copies an error
into an error location (so the calling function will receive it), and
`g_clear_error()` clears an error location by freeing the error and
resetting the location to `NULL`. To display an error to the user, simply
display the `message`, perhaps along with additional context known only to
the calling function (the file being opened, or whatever - though in the
`g_file_get_contents()` case, the `message` already contains a filename).
Since error messages may be displayed to the user, they need to be valid
UTF-8 (all GTK widgets expect text to be UTF-8). Keep this in mind in
particular when formatting error messages with filenames, which are in the
'filename encoding', and need to be turned into UTF-8 using
`g_filename_to_utf8()`, `g_filename_display_name()` or
`g_utf8_make_valid()`.
Note, however, that many error messages are too technical to display to the
user in an application, so prefer to use `g_error_matches()` to categorize
errors from called functions, and build an appropriate error message for the
context within your application. Error messages from a `GError` are more
appropriate to be printed in system logs or on the command line. They are
typically translated.
## Reporting errors
When implementing a function that can report errors, the basic tool is
`g_set_error()`. Typically, if a fatal error occurs you want to
`g_set_error()`, then return immediately. `g_set_error()` does nothing if
the error location passed to it is `NULL`. Here's an example:
```c
int
foo_open_file (GError **error)
{
int fd;
int saved_errno;
g_return_val_if_fail (error == NULL || *error == NULL, -1);
fd = open ("file.txt", O_RDONLY);
saved_errno = errno;
if (fd < 0)
{
g_set_error (error,
FOO_ERROR, // error domain
FOO_ERROR_BLAH, // error code
"Failed to open file: %s", // error message format string
g_strerror (saved_errno));
return -1;
}
else
return fd;
}
```
Things are somewhat more complicated if you yourself call another function
that can report a `GError`. If the sub-function indicates fatal errors in
some way other than reporting a `GError`, such as by returning `TRUE` on
success, you can simply do the following:
```c
gboolean
my_function_that_can_fail (GError **err)
{
g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
if (!sub_function_that_can_fail (err))
{
// assert that error was set by the sub-function
g_assert (err == NULL || *err != NULL);
return FALSE;
}
// otherwise continue, no error occurred
g_assert (err == NULL || *err == NULL);
}
```
If the sub-function does not indicate errors other than by reporting a
`GError` (or if its return value does not reliably indicate errors) you need
to create a temporary `GError` since the passed-in one may be `NULL`.
`g_propagate_error()` is intended for use in this case.
```c
gboolean
my_function_that_can_fail (GError **err)
{
GError *tmp_error;
g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
tmp_error = NULL;
sub_function_that_can_fail (&tmp_error);
if (tmp_error != NULL)
{
// store tmp_error in err, if err != NULL,
// otherwise call g_error_free() on tmp_error
g_propagate_error (err, tmp_error);
return FALSE;
}
// otherwise continue, no error occurred
}
```
Error pileups are always a bug. For example, this code is incorrect:
```c
gboolean
my_function_that_can_fail (GError **err)
{
GError *tmp_error;
g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
tmp_error = NULL;
sub_function_that_can_fail (&tmp_error);
other_function_that_can_fail (&tmp_error);
if (tmp_error != NULL)
{
g_propagate_error (err, tmp_error);
return FALSE;
}
}
```
`tmp_error` should be checked immediately after
`sub_function_that_can_fail()`, and either cleared or propagated upward. The
rule is: after each error, you must either handle the error, or return it to
the calling function.
Note that passing `NULL` for the error location is the equivalent of
handling an error by always doing nothing about it. So the following code is
fine, assuming errors in `sub_function_that_can_fail()` are not fatal to
`my_function_that_can_fail()`:
```c
gboolean
my_function_that_can_fail (GError **err)
{
GError *tmp_error;
g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
sub_function_that_can_fail (NULL); // ignore errors
tmp_error = NULL;
other_function_that_can_fail (&tmp_error);
if (tmp_error != NULL)
{
g_propagate_error (err, tmp_error);
return FALSE;
}
}
```
Note that passing `NULL` for the error location ignores errors; it's
equivalent to:
```cpp
try { sub_function_that_can_fail (); } catch (...) {}
```
in C++. It does not mean to leave errors unhandled; it means to handle them
by doing nothing.
## Error domains
Error domains and codes are conventionally named as follows:
- The error domain is called `<NAMESPACE>_<MODULE>_ERROR`, for example
`G_SPAWN_ERROR` or `G_THREAD_ERROR`:
```c
#define G_SPAWN_ERROR g_spawn_error_quark ()
G_DEFINE_QUARK (g-spawn-error-quark, g_spawn_error)
```
- The quark function for the error domain is called
`<namespace>_<module>_error_quark`, for example `g_spawn_error_quark()` or
`g_thread_error_quark()`.
- The error codes are in an enumeration called `<Namespace><Module>Error`;
for example, `GThreadError` or `GSpawnError`.
- Members of the error code enumeration are called
`<NAMESPACE>_<MODULE>_ERROR_<CODE>`, for example `G_SPAWN_ERROR_FORK` or
`G_THREAD_ERROR_AGAIN`.
- If there's a "generic" or "unknown" error code for unrecoverable errors it
doesn't make sense to distinguish with specific codes, it should be called
`<NAMESPACE>_<MODULE>_ERROR_FAILED`, for example `G_SPAWN_ERROR_FAILED`.
In the case of error code enumerations that may be extended in future
releases, you should generally not handle this error code explicitly, but
should instead treat any unrecognized error code as equivalent to
`FAILED`.
## Comparison of `GError` and traditional error handling
`GError` has several advantages over traditional numeric error codes:
importantly, tools like [gobject-introspection](https://gi.readthedocs.org)
understand `GError`s and convert them to exceptions in bindings; the message
includes more information than just a code; and use of a domain helps
prevent misinterpretation of error codes.
`GError` has disadvantages though: it requires a memory allocation, and
formatting the error message string has a performance overhead. This makes
it unsuitable for use in retry loops where errors are a common case, rather
than being unusual. For example, using `G_IO_ERROR_WOULD_BLOCK` means
hitting these overheads in the normal control flow. String formatting
overhead can be eliminated by using `g_set_error_literal()` in some cases.
These performance issues can be compounded if a function wraps the `GError`s
returned by the functions it calls: this multiplies the number of
allocations and string formatting operations. This can be partially
mitigated by using `g_prefix_error()`.
## Rules for use of `GError`
Summary of rules for use of `GError`:
- Do not report programming errors via `GError`.
- The last argument of a function that returns an error should be a location
where a `GError` can be placed (i.e. `GError **error`). If `GError` is
used with varargs, the `GError**` should be the last argument before the
`...`.
- The caller may pass `NULL` for the `GError**` if they are not interested
in details of the exact error that occurred.
- If `NULL` is passed for the `GError**` argument, then errors should not be
returned to the caller, but your function should still abort and return if
an error occurs. That is, control flow should not be affected by whether
the caller wants to get a `GError`.
- If a `GError` is reported, then your function by definition had a fatal
failure and did not complete whatever it was supposed to do. If the
failure was not fatal, then you handled it and you should not report it.
If it was fatal, then you must report it and discontinue whatever you were
doing immediately.
- If a `GError` is reported, out parameters are not guaranteed to be set to
any defined value.
- A `GError*` must be initialized to `NULL` before passing its address to a
function that can report errors.
- `GError` structs must not be stack-allocated.
- "Piling up" errors is always a bug. That is, if you assign a new `GError`
to a `GError*` that is non-`NULL`, thus overwriting the previous error, it
indicates that you should have aborted the operation instead of
continuing. If you were able to continue, you should have cleared the
previous error with `g_clear_error()`. `g_set_error()` will complain if
you pile up errors.
- By convention, if you return a boolean value indicating success then
`TRUE` means success and `FALSE` means failure. Avoid creating functions
which have a boolean return value and a `GError` parameter, but where the
boolean does something other than signal whether the `GError` is set.
Among other problems, it requires C callers to allocate a temporary error.
Instead, provide a `gboolean *` out parameter. There are functions in
GLib itself such as `g_key_file_has_key()` that are hard to use because of
this. If `FALSE` is returned, the error must be set to a non-`NULL` value.
One exception to this is that in situations that are already considered to
be undefined behaviour (such as when a `g_return_val_if_fail()` check
fails), the error need not be set. Instead of checking separately whether
the error is set, callers should ensure that they do not provoke undefined
behaviour, then assume that the error will be set on failure.
- A `NULL` return value is also frequently used to mean that an error
occurred. You should make clear in your documentation whether `NULL` is a
valid return value in non-error cases; if `NULL` is a valid value, then
users must check whether an error was returned to see if the function
succeeded.
- When implementing a function that can report errors, you may want
to add a check at the top of your function that the error return
location is either `NULL` or contains a `NULL` error (e.g.
`g_return_if_fail (error == NULL || *error == NULL);`).
## Extended `GError` Domains
Since GLib 2.68 it is possible to extend the `GError` type. This is
done with the `G_DEFINE_EXTENDED_ERROR()` macro. To create an
extended `GError` type do something like this in the header file:
```c
typedef enum
{
MY_ERROR_BAD_REQUEST,
} MyError;
#define MY_ERROR (my_error_quark ())
GQuark my_error_quark (void);
int
my_error_get_parse_error_id (GError *error);
const char *
my_error_get_bad_request_details (GError *error);
```
and in the implementation:
```c
typedef struct
{
int parse_error_id;
char *bad_request_details;
} MyErrorPrivate;
static void
my_error_private_init (MyErrorPrivate *priv)
{
priv->parse_error_id = -1;
// No need to set priv->bad_request_details to NULL,
// the struct is initialized with zeros.
}
static void
my_error_private_copy (const MyErrorPrivate *src_priv, MyErrorPrivate *dest_priv)
{
dest_priv->parse_error_id = src_priv->parse_error_id;
dest_priv->bad_request_details = g_strdup (src_priv->bad_request_details);
}
static void
my_error_private_clear (MyErrorPrivate *priv)
{
g_free (priv->bad_request_details);
}
// This defines the my_error_get_private and my_error_quark functions.
G_DEFINE_EXTENDED_ERROR (MyError, my_error)
int
my_error_get_parse_error_id (GError *error)
{
MyErrorPrivate *priv = my_error_get_private (error);
g_return_val_if_fail (priv != NULL, -1);
return priv->parse_error_id;
}
const char *
my_error_get_bad_request_details (GError *error)
{
MyErrorPrivate *priv = my_error_get_private (error);
g_return_val_if_fail (priv != NULL, NULL);
g_return_val_if_fail (error->code != MY_ERROR_BAD_REQUEST, NULL);
return priv->bad_request_details;
}
static void
my_error_set_bad_request (GError **error,
const char *reason,
int error_id,
const char *details)
{
MyErrorPrivate *priv;
g_set_error (error, MY_ERROR, MY_ERROR_BAD_REQUEST, "Invalid request: %s", reason);
if (error != NULL && *error != NULL)
{
priv = my_error_get_private (error);
g_return_val_if_fail (priv != NULL, NULL);
priv->parse_error_id = error_id;
priv->bad_request_details = g_strdup (details);
}
}
```
An example of use of the error could be:
```c
gboolean
send_request (GBytes *request, GError **error)
{
ParseFailedStatus *failure = validate_request (request);
if (failure != NULL)
{
my_error_set_bad_request (error, failure->reason, failure->error_id, failure->details);
parse_failed_status_free (failure);
return FALSE;
}
return send_one (request, error);
}
```
Please note that if you are a library author and your library exposes an
existing error domain, then you can't make this error domain an extended one
without breaking ABI. This is because earlier it was possible to create an
error with this error domain on the stack and then copy it with
`g_error_copy()`. If the new version of your library makes the error domain
an extended one, then `g_error_copy()` called by code that allocated the
error on the stack will try to copy more data than it used to, which will
lead to undefined behavior. You must not stack-allocate errors with an
extended error domain, and it is bad practice to stack-allocate any other
`GError`s.
Extended error domains in unloadable plugins/modules are not supported.

View File

@ -24,11 +24,7 @@
General Public License (GNU LGPL).
</para>
<xi:include href="building.xml" />
<xi:include href="cross.xml" />
<xi:include href="programming.xml" />
<xi:include href="xml/compiling.xml" />
<xi:include href="running.xml" />
<xi:include href="changes.xml" />
<xi:include href="resources.xml" />
@ -118,8 +114,6 @@
<xi:include href="xml/datasets.xml" />
<xi:include href="xml/gvarianttype.xml"/>
<xi:include href="xml/gvariant.xml"/>
<xi:include href="gvariant-varargs.xml"/>
<xi:include href="gvariant-text.xml"/>
<xi:include href="xml/refcount.xml"/>
<xi:include href="xml/rcbox.xml"/>
<xi:include href="xml/arcbox.xml"/>

View File

@ -0,0 +1,99 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# Copyright 2023 Matthias Clasen
# Copyright 2023 Philip Withnall
[library]
name = "GLib"
version = "@VERSION@"
browse_url = "https://gitlab.gnome.org/GNOME/glib/"
repository_url = "https://gitlab.gnome.org/GNOME/glib.git"
website_url = "https://www.gtk.org"
docs_url = "https://docs.gtk.org/glib/"
authors = "GLib Development Team"
license = "LGPL-2.1-or-later"
description = "GLib is a general-purpose, portable utility library, which provides many useful data types, macros, type conversions, string utilities, file utilities, a mainloop abstraction, and so on."
related = [ "GModule-2.0", "GObject-2.0", "Gio-2.0" ]
devhelp = true
search_index = true
[related."GModule-2.0"]
name = "GModule"
description = "Portable API for dynamically loading modules"
docs_url = "https://docs.gtk.org/gmodule/"
[related."GObject-2.0"]
name = "GObject"
description = "The base type system library"
docs_url = "https://docs.gtk.org/gobject/"
[related."Gio-2.0"]
name = "GIO"
description = "GObject Interfaces and Objects, Networking, IPC, and I/O"
docs_url = "https://docs.gtk.org/gio/"
[theme]
name = "basic"
show_index_summary = true
show_class_hierarchy = true
[extra]
urlmap_file = "urlmap.js"
# The same order will be used when generating the index
content_files = [
"building.md",
"compiling.md",
"cross-compiling.md",
"running.md",
"gvariant-format-strings.md",
"gvariant-text-format.md",
"character-set.md",
"i18n.md",
"macros.md",
"conversion-macros.md",
"auto-cleanup.md",
"memory-slices.md",
"error-reporting.md",
"logging.md",
"main-loop.md",
"reference-counting.md",
"testing.md",
"threads.md",
"markup.md",
"goption.md",
]
content_images = [
"file-name-encodings.png",
"mainloop-states.gif",
"Sorted_binary_tree_breadth-first_traversal.svg",
"Sorted_binary_tree_inorder.svg",
"Sorted_binary_tree_postorder.svg",
"Sorted_binary_tree_preorder.svg",
]
[[object]]
pattern = "DEPRECATED_IN_2_*"
hidden = true
[[object]]
pattern = "DEPRECATED_MACRO_IN_2_*"
hidden = true
[[object]]
pattern = "DEPRECATED_ENUMERATOR_IN_2_*"
hidden = true
[[object]]
pattern = "DEPRECATED_TYPE_IN_2_*"
hidden = true
[[object]]
name = "test_assert_expected_messages_internal"
hidden = true
[[object]]
pattern = "macro__has_*"
hidden = true

View File

@ -0,0 +1,149 @@
Title: Commandline option parser
# Commandline option parser
The GOption commandline parser is intended to be a simpler replacement
for the popt library. It supports short and long commandline options,
as shown in the following example:
testtreemodel -r 1 --max-size 20 --rand --display=:1.0 -vb -- file1 file2
The example demonstrates a number of features of the GOption commandline parser:
- Options can be single letters, prefixed by a single dash.
- Multiple short options can be grouped behind a single dash.
- Long options are prefixed by two consecutive dashes.
- Options can have an extra argument, which can be a number, a string or
a filename. For long options, the extra argument can be appended with
an equals sign after the option name, which is useful if the extra
argument starts with a dash, which would otherwise cause it to be
interpreted as another option.
- Non-option arguments are returned to the application as rest arguments.
- An argument consisting solely of two dashes turns off further parsing,
any remaining arguments (even those starting with a dash) are returned
to the application as rest arguments.
Another important feature of GOption is that it can automatically
generate nicely formatted help output. Unless it is explicitly turned
off with [method@GLib.OptionContext.set_help_enabled], GOption will recognize
the `--help`, `-?`, `--help-all` and `--help-groupname` options (where `groupname`
is the name of a [struct@GLib.OptionGroup]) and write a text similar to the one shown
in the following example to stdout.
Usage:
testtreemodel [OPTION...] - test tree model performance
Help Options:
-h, --help Show help options
--help-all Show all help options
--help-gtk Show GTK Options
Application Options:
-r, --repeats=N Average over N repetitions
-m, --max-size=M Test up to 2^M items
--display=DISPLAY X display to use
-v, --verbose Be verbose
-b, --beep Beep when done
--rand Randomize the data
GOption groups options in [struct@GLib.OptionGroup]s, which makes it easy to
incorporate options from multiple sources. The intended use for this is
to let applications collect option groups from the libraries it uses,
add them to their #GOptionContext, and parse all options by a single call
to [method@GLib.OptionContext.parse].
If an option is declared to be of type string or filename, GOption takes
care of converting it to the right encoding; strings are returned in UTF-8,
filenames are returned in the GLib filename encoding. Note that this only
works if `setlocale()` has been called before [method@GLib.OptionContext.parse]
Here is a complete example of setting up GOption to parse the example
commandline above and produce the example help output.
```c
static gint repeats = 2;
static gint max_size = 8;
static gboolean verbose = FALSE;
static gboolean beep = FALSE;
static gboolean randomize = FALSE;
static GOptionEntry entries[] =
{
{ "repeats", 'r', 0, G_OPTION_ARG_INT, &repeats, "Average over N repetitions", "N" },
{ "max-size", 'm', 0, G_OPTION_ARG_INT, &max_size, "Test up to 2^M items", "M" },
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL },
{ "beep", 'b', 0, G_OPTION_ARG_NONE, &beep, "Beep when done", NULL },
{ "rand", 0, 0, G_OPTION_ARG_NONE, &randomize, "Randomize the data", NULL },
G_OPTION_ENTRY_NULL
};
int
main (int argc, char *argv[])
{
GError *error = NULL;
GOptionContext *context;
context = g_option_context_new ("- test tree model performance");
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
g_option_context_add_group (context, gtk_get_option_group (TRUE));
if (!g_option_context_parse (context, &argc, &argv, &error))
{
g_print ("option parsing failed: %s\n", error->message);
exit (1);
}
...
}
```
On UNIX systems, the argv that is passed to `main()` has no particular
encoding, even to the extent that different parts of it may have different
encodings. In general, normal arguments and flags will be in the current
locale and filenames should be considered to be opaque byte strings.
Proper use of `G_OPTION_ARG_FILENAME` vs `G_OPTION_ARG_STRING` is
therefore important.
Note that on Windows, filenames do have an encoding, but using
[struct@GLib.OptionContext] with the argv as passed to `main()` will result
in a program that can only accept commandline arguments with characters
from the system codepage.This can cause problems when attempting to
deal with filenames containing Unicode characters that fall outside
of the codepage.
A solution to this is to use `g_win32_get_command_line()` and
[method@GLib.OptionContext.parse_strv] which will properly handle full
Unicode filenames. If you are using #GApplication, this is done
automatically for you.
The following example shows how you can use #GOptionContext directly
in order to correctly deal with Unicode filenames on Windows:
```c
int
main (int argc, char **argv)
{
GError *error = NULL;
GOptionContext *context;
gchar **args;
#ifdef G_OS_WIN32
args = g_win32_get_command_line ();
#else
args = g_strdupv (argv);
#endif
// set up context
if (!g_option_context_parse_strv (context, &args, &error))
{
// error happened
}
...
g_strfreev (args);
...
}
```

View File

@ -0,0 +1,503 @@
Title: GVariant Format Strings
# GVariant Format Strings
## Variable Argument Conversions
This page attempts to document how to perform variable argument conversions
with [struct@GLib.Variant].
Conversions occur according to format strings. A format string is a two-way
mapping between a single `GVariant` value and one or more C values.
A conversion from C values into a `GVariant` value is made using the
[ctor@GLib.Variant.new] function. A conversion from a `GVariant` into C
values is made using the [method@GLib.Variant.get] function.
## Syntax
This section exhaustively describes all possibilities for GVariant format
strings. There are no valid forms of format strings other than those
described here. Please note that the format string syntax is likely to
expand in the future.
Valid format strings have one of the following forms:
- any type string
- a type string prefixed with a `@`
- `&s`, `&o`, `&g`, `^as`, `^a&s`, `^ao`, `^a&o`, `^ay`, `^&ay`, `^aay` or
`^a&ay`.
- any format string, prefixed with an `m`
- a sequence of zero or more format strings, concatenated and enclosed in
parentheses
- an opening brace, followed by two format strings, followed by a closing
brace (subject to the constraint that the first format string correspond
to a type valid for use as the key type of a dictionary)
## Symbols
The following table describes the rough meaning of symbols that may appear inside a GVariant format string. Each symbol is described in detail in its own section, including usage examples.
| Symbol | Meaning |
|--------|---------|
| `b`, `y`, `n`, `q`, `i`, `u`, `x`, `t`, `h`, `d` | Used for building or deconstructing boolean, byte and numeric types. See [Numeric Types](#numeric-types) below. |
| `s`, `o`, `g` | Used for building or deconstructing string types. See [Strings](#strings) below. |
| `v` | Used for building or deconstructing variant types. See [Variants](#variants) below. |
| `a` | Used for building or deconstructing arrays. See [Arrays](#arrays) below. |
| `m` | Used for building or deconstructing maybe types. See [Maybe Types](#maybe-types) below. |
| `()` | Used for building or deconstructing tuples. See [Tuples](#tuples) below. |
| `{}` | Used for building or deconstructing dictionary entries. See [Dictionaries](#dictionaries) below. |
| `@` | Used as a prefix for a `GVariant` type string (not a prefix for a format string, so `@as` is a valid format string but `@^as` is not). Denotes that a pointer to a GVariant should be used in place of the normal C type or types. For `g_variant_new()` this means that you must pass a non-`NULL` `(GVariant *)`; if it is a floating reference, ownership will be taken, as if by using `g_variant_ref_sink()`. For `g_variant_get()` this means that you must pass a pointer to a `(GVariant *)` for the value to be returned by reference or `NULL` to ignore the value. See [`GVariant *`](#gvariant) below. |
| `*`, `?`, `r` | Exactly equivalent to `@*`, `@?` and `@r`. Provided only for completeness so that all `GVariant` type strings can be used also as format strings. See [`GVariant *`](#gvariant) below. |
| `&` | Used as a prefix for a `GVariant` type string (not a prefix for a format string, so `&s` is a valid format string but `&@s` is not). Denotes that a C pointer to serialised data should be used in place of the normal C type. See [Pointers](#pointers) below. |
| `^` | Used as a prefix on some specific types of format strings. See [Convenience Conversions](#convenience-conversions) below. |
## Numeric Types
Characters: `b`, `y`, `n`, `q`, `i`, `u`, `x`, `t`, `h`, `d`
Variable argument conversions from numeric types work in the most obvious
way possible. Upon encountering one of these characters, `g_variant_new()`
takes the equivalent C type as an argument. `g_variant_get()` takes a pointer
to the equivalent C type (or `NULL` to ignore the value).
The equivalent C types are as follows:
| Character | Equivalent C type |
|-----------|-------------------|
| `b` | `gboolean` |
| `y` | `guchar` |
| `n` | `gint16` |
| `q` | `guint16` |
| `i` | `gint32` |
| `u` | `guint32` |
| `x` | `gint64` |
| `t` | `guint64` |
| `h` | `gint32` |
| `d` | `gdouble` |
Note that in C, small integer types in variable argument lists are promoted
up to `int` or `unsigned int` as appropriate, and read back accordingly. `int`
is 32 bits on every platform on which GLib is currently supported. This
means that you can use C expressions of type `int` with `g_variant_new()` and
format characters `b`, `y`, `n`, `q`, `i`, `u` and `h`. Specifically, you
can use integer literals with these characters.
When using the `x` and `t` characters, you must ensure that the value that
you provide is 64 bit. This means that you should use a cast or make use of
the `G_GINT64_CONSTANT` or `G_GUINT64_CONSTANT` macros.
No type promotion occurs when using `g_variant_get()` since it operates with
pointers. The pointers must always point to a memory region of exactly the
correct size.
### Examples
```c
GVariant *value1, *value2, *value3, *value4;
value1 = g_variant_new ("y", 200);
value2 = g_variant_new ("b", TRUE);
value3 = g_variant_new ("d", 37.5):
value4 = g_variant_new ("x", G_GINT64_CONSTANT (998877665544332211));
{
gdouble floating;
gboolean truth;
gint64 bignum;
g_variant_get (value1, "y", NULL); /* ignore the value. */
g_variant_get (value2, "b", &truth);
g_variant_get (value3, "d", &floating);
g_variant_get (value4, "x", &bignum);
}
```
## Strings
Characters: `s`, `o`, `g`
String conversions occur to and from standard nul-terminated C strings. Upon
encountering an `s`, `o` or `g` in a format string, `g_variant_new()` takes a
`(const gchar *)` and makes a copy of it. `NULL` is not a valid string; use
maybe types to encode that. If the `o` or `g` characters are used, care must
be taken to ensure that the passed string is a valid D-Bus object path or
D-Bus type signature, respectively.
Upon encountering `s`, `o` or `g`, `g_variant_get()` takes a pointer to a
`(gchar *)` (ie: `(gchar **)`) and sets it to a newly-allocated copy of the
string. It is appropriate to free this copy using `g_free()`. `NULL` may
also be passed to indicate that the value of the string should be ignored
(in which case no copy is made).
### Examples
```c
GVariant *value1, *value2, *value3;
value1 = g_variant_new ("s", "hello world!");
value2 = g_variant_new ("o", "/must/be/a/valid/path");
value3 = g_variant_new ("g", "iias");
#if 0
g_variant_new ("s", NULL); /* not valid: NULL is not a string. */
#endif
{
gchar *result;
g_variant_get (value1, "s", &result);
g_print ("It was '%s'\n", result);
g_free (result);
}
```
## Variants
Characters: `v`
Upon encountering a `v`, `g_variant_new()` takes a `(GVariant *)`. The value
of the `GVariant` is used as the contents of the variant value.
Upon encountering a `v`, `g_variant_get()` takes a pointer to a `(GVariant
*)` (ie: `(GVariant **)`). It is set to a new reference to a `GVariant`
instance containing the contents of the variant value. It is appropriate to
free this reference using `g_variant_unref()`. `NULL` may also be passed to
indicate that the value should be ignored (in which case no new reference is
created).
### Examples
```c
GVariant *x, *y;
/* the following two lines are equivalent: */
x = g_variant_new ("v", y);
x = g_variant_new_variant (y);
/* as are these: */
g_variant_get (x, "v", &y);
y = g_variant_get_variant (x);
```
## Arrays
Characters: `a`
Upon encountering an `a` character followed by a type string,
`g_variant_new()` will take a `(GVariantBuilder *)` that has been created as
an array builder for an array of the type given in the type string. The
builder will have `g_variant_builder_end()` called on it and the result will
be used as the value. As a special exception, if the given type string is a
definite type, then `NULL` may be given to mean an empty array of that type.
Upon encountering an `a` character followed by a type string,
`g_variant_get()` will take a pointer to a `(GVariantIter *)` (ie:
`(GVariantIter **)`). A new heap-allocated iterator is created and returned,
initialised for iterating over the elements of the array. This iterator
should be freed when you are done with it, using `g_variant_iter_free()`.
`NULL` may also be given to indicate that the value of the array should be
ignored.
### Examples
```c
GVariantBuilder *builder;
GVariant *value;
builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
g_variant_builder_add (builder, "s", "when");
g_variant_builder_add (builder, "s", "in");
g_variant_builder_add (builder, "s", "the");
g_variant_builder_add (builder, "s", "course");
value = g_variant_new ("as", builder);
g_variant_builder_unref (builder);
{
GVariantIter *iter;
gchar *str;
g_variant_get (value, "as", &iter);
while (g_variant_iter_loop (iter, "s", &str))
g_print ("%s\n", str);
g_variant_iter_free (iter);
}
g_variant_unref (value);
```
## Maybe Types
Characters: `m`
Maybe types are handled in two separate ways depending on the format string
that follows the `m`. The method that is used currently depends entirely on
the character immediately following the `m`.
The first way is used with format strings starting with `a`, `s`, `o`, `g`,
`v`, `@`, `*`, `?`, `r`, `&`, or `^`. In all of these cases, for non-maybe
types, `g_variant_new()` takes a pointer to a non-`NULL` value and
`g_variant_get()` returns (by reference) a non-`NULL` pointer. When any of
these format strings are prefixed with an `m`, the type of arguments that
are collected does not change in any way, but `NULL` becomes a permissible
value, to indicate the Nothing case.
Note that the "special exception" introduced in the array section for
constructing empty arrays is ignored here. Using a `NULL` pointer with the
format string `mas` constructs the Nothing value -- not an empty array.
The second way is used with all other format strings. For `g_variant_new()`
an additional gboolean argument is collected and for `g_variant_get()` an
additional `(gboolean *)`. Following this argument, the arguments that are
normally collected for the equivalent non-maybe type will be collected.
If `FALSE` is given to `g_variant_new()` then the Nothing value is
constructed and the collected arguments are ignored. Otherwise (if `TRUE`
was given), the arguments are used in the normal way to create the Just
value.
If `NULL` is given to `g_variant_get()` then the value is ignored. If a
non-`NULL` pointer is given then it is used to return by reference whether
the value was Just. In the case that the value was Just, the `gboolean` will
be set to `TRUE` and the value will be stored in the arguments in the usual
way. In the case that the value was Nothing, the `gboolean` will be set to
`FALSE` and the arguments will be collected in the normal way but have their
values set to binary zero.
### Examples
```c
GVariant *value1, *value2, *value3, *value4, *value5, *value6;
value1 = g_variant_new ("ms", "Hello world");
value2 = g_variant_new ("ms", NULL);
value3 = g_variant_new ("(m(ii)s)", TRUE, 123, 456, "Done");
value4 = g_variant_new ("(m(ii)s)", FALSE, -1, -1, "Done"); /* both '-1' are ignored. */
value5 = g_variant_new ("(m@(ii)s)", NULL, "Done");
{
GVariant *contents;
const gchar *cstr;
gboolean just;
gint32 x, y;
gchar *str;
g_variant_get (value1, "ms", &str);
if (str != NULL)
g_print ("str: %s\n", str);
else
g_print ("it was null\n");
g_free (str);
g_variant_get (value2, "m&s", &cstr);
if (cstr != NULL)
g_print ("str: %s\n", cstr);
else
g_print ("it was null\n");
/* don't free 'cstr' */
/* NULL passed for the gboolean *, but two 'gint32 *' still collected */
g_variant_get (value3, "(m(ii)s)", NULL, NULL, NULL, &str);
g_print ("string is %s\n", str);
g_free (str);
/* note: &s used, so g_free() not needed */
g_variant_get (value4, "(m(ii)&s)", &just, &x, &y, &cstr);
if (just)
g_print ("it was (%d, %d)\n", x, y);
else
g_print ("it was null\n");
g_print ("string is %s\n", cstr);
/* don't free 'cstr' */
g_variant_get (value5, "(m*s)", &contents, NULL); /* ignore the string. */
if (contents != NULL)
{
g_variant_get (contents, "(ii)", &x, &y);
g_print ("it was (%d, %d)\n", x, y);
g_variant_unref (contents);
}
else
g_print ("it was null\n");
}
```
## Tuples
Characters: `()`
Tuples are handled by handling each item in the tuple, in sequence. Each
item is handled in the usual way.
### Examples
```c
GVariant *value1, *value2;
value1 = g_variant_new ("(s(ii))", "Hello", 55, 77);
value2 = g_variant_new ("()");
{
gchar *string;
gint x, y;
g_variant_get (value1, "(s(ii))", &string, &x, &y);
g_print ("%s, %d, %d\n", string, x, y);
g_free (string);
g_variant_get (value2, "()"); /* do nothing... */
}
```
## `GVariant *`
Characters: `@`, `*`, `?`, `r`
Upon encountering a `@` in front of a type string, `g_variant_new()` takes a
non-`NULL` pointer to a `GVariant` and uses its value directly instead of
collecting arguments to create the value. The provided `GVariant` must have
a type that matches the type string following the `@`. `*` is the same as
`@*` (ie: take a `GVariant` of any type). `?` is the same as `@?` (ie: take
a `GVariant` of any basic type). `r` is the same as `@r` (ie: take a
`GVariant` of any tuple type).
Upon encountering a `@` in front of a type string, `g_variant_get()` takes a
pointer to a `(GVariant *)` (ie: a `(GVariant **)`) and sets it to a new
reference to a `GVariant` containing the value (instead of deconstructing
the value into C types in the usual way). `NULL` can be given to ignore the
value. `*`, `?` and `r` are handled in a way analogous to what is stated
above.
You can always use `*` as an alternative to `?`, `r` or any use of `@`.
Using the other characters where possible is recommended, however, due to
the improvements in type safety and code self-documentation.
### Examples
```c
GVariant *value1, *value2;
value1 = g_variant_new ("(i@ii)", 44, g_variant_new_int32 (55), 66);
/* note: consumes floating reference count on 'value1' */
value2 = g_variant_new ("(@(iii)*)", value1, g_variant_new_string ("foo"));
{
const gchar *string;
GVariant *tmp;
gsize length;
gint x, y, z;
g_variant_get (value2, "((iii)*)", &x, &y, &z, &tmp);
string = g_variant_get_string (tmp, &length);
g_print ("it is %d %d %d %s (length=%d)\n", x, y, z, string, (int) length);
g_variant_unref (tmp);
/* quick way to skip all the values in a tuple */
g_variant_get (value2, "(rs)", NULL, &string); /* or "(@(iii)s)" */
g_print ("i only got the string: %s\n", string);
g_free (string);
}
```
## Dictionaries
Characters: `{}`
Dictionary entries are handled by handling first the key, then the value. Each is handled in the usual way.
### Examples
```c
GVariantBuilder *b;
GVariant *dict;
b = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (b, "{sv}", "name", g_variant_new_string ("foo"));
g_variant_builder_add (b, "{sv}", "timeout", g_variant_new_int32 (10));
dict = g_variant_builder_end (b);
```
To extract data from nested dictionaries you can go through a vardict.
### Examples
```c
GVariant *data;
gint value = 1;
gint max = 3;
/* type (oa{sa{sv}) */
data = g_variant_new_parsed ("(%o, {'brightness': {'value': <%i>, 'max': <%i>}})",
"/object/path", value, max);
{
GVariant *params;
GVariant *p_brightness;
gchar *obj
gint p_max;
g_variant_get (data, "(o@a{?*})", &obj, &params);
g_print ("object_path: %s\n", obj);
p_brightness = g_variant_lookup_value (params, "brightness", G_VARIANT_TYPE_VARDICT);
g_variant_lookup (p_brightness, "max", "i", &p_max);
g_print ("max: %d\n", p_max);
}
```
## Pointers
Characters: `&`
The `&` character is used to indicate that serialised data should be
directly exchanged via a pointer.
Currently, the only use for this character is when it is applied to a string
(ie: `&s`, `&o` or `&g`). For `g_variant_new()` this has absolutely no
effect. The string is collected and duplicated normally. For
`g_variant_get()` it means that instead of creating a newly allocated copy
of the string, a pointer to the serialised data is returned. This pointer
should not be freed. Validity checks are performed to ensure that the string
data will always be properly nul-terminated.
### Examples
```c
{
const gchar *str;
GVariant *value;
value = g_variant_new ("&s", "hello world");
g_variant_get (value, "&s", &str);
g_print ("string is: %s\n", str);
/* no need to free str */
}
```
## Convenience Conversions
Characters: `^`
The `^` character currently supports conversion to and from bytestrings or
to and from arrays of strings or bytestrings. It does not support byte
arrays. It has a number of forms.
In all forms, when used with `g_variant_new()` one pointer value is
collected from the variable arguments and passed to a function (as given in
the table below). The result of that function is used as the value for this
position. When used with `g_variant_get()` one pointer value is produced by
using the function (given in the table) and returned by reference.
| Conversion | Used with `g_variant_new()` | Used with `g_variant_get()` |
|------------|----------------------------------------------------------|------------------------------------------------------------|
| `^as` | equivalent to [`ctor@GLib.Variant.new_strv`] | equivalent to [`method@GLib.Variant.dup_strv`] |
| `^a&s` | | equivalent to [`method@GLib.Variant.get_strv`] |
| `^ao` | equivalent to [`ctor@GLib.Variant.new_objv`] | equivalent to [`method@GLib.Variant.dup_objv`] |
| `^a&o` | | equivalent to [`method@GLib.Variant.get_objv`] |
| `^ay` | equivalent to [`ctor@GLib.Variant.new_bytestring`] | equivalent to [`method@GLib.Variant.dup_bytestring`] |
| `^&ay` | | equivalent to [`method@GLib.Variant.get_bytestring`] |
| `^aay` | equivalent to [`ctor@GLib.Variant.new_bytestring_array`] | equivalent to [`method@GLib.Variant.dup_bytestring_array`] |
| `^a&ay` | | equivalent to [`method@GLib.Variant.get_bytestring_array`] |

View File

@ -0,0 +1,346 @@
Title: GVariant Text Format
# GVariant Text Format
This page attempts to document the `GVariant` text format as produced by
[`method@GLib.Variant.print`] and parsed by the [`func@GLib.Variant.parse`]
family of functions. In most cases the style closely resembles the
formatting of literals in Python but there are some additions and
exceptions.
The functions that deal with `GVariant` text format absolutely always deal
in UTF-8. Conceptually, `GVariant` text format is a string of Unicode
characters, not bytes. Non-ASCII but otherwise printable Unicode characters
are not treated any differently from normal ASCII characters.
The parser makes two passes. The purpose of the first pass is to determine
the type of the value being parsed. The second pass does the actual parsing.
Based on the fact that all elements in an array have to have the same type,
`GVariant` is able to make some deductions that would not otherwise be
possible. As an example:
[[1, 2, 3], [4, 5, 6]]
is parsed as an array of arrays of integers (type `aai`), but
[[1, 2, 3], [4, 5, 6.0]]
is parsed as an array of arrays of doubles (type `aad`).
As another example, `GVariant` is able to determine that
["hello", nothing]
is an array of maybe strings (type `ams`).
What the parser accepts as valid input is dependent on context. The API
permits for out-of-band type information to be supplied to the parser (which
will change its behaviour). This can be seen in the GSettings and GDBus
command line utilities where the type information is available from the
schema or the remote introspection information. The additional information
can cause parses to succeed when they would not otherwise have been able to
(by resolving ambiguous type information) or can cause them to fail (due to
conflicting type information). Unless stated otherwise, the examples given
in this section assume that no out-of-band type data has been given to the
parser.
## Syntax Summary
The following table describes the rough meaning of symbols that may appear
inside GVariant text format. Each symbol is described in detail in its own
section, including usage examples.
| Symbol | Meaning |
|--------|---------|
| `true`, `false` | [Booleans](#booleans). |
| `""`, `''` | String literal. See [Strings](#strings) below. |
| numbers | See [Numbers](#numbers) below. |
| `()` | [Tuples](#tuples). |
| `[]` | [Arrays](#arrays). |
| `{}` | [Dictionaries and Dictionary Entries](#dictionaries-and-dictionary-entries). |
| `<>` | [Variants](#variants). |
| `just`, `nothing` | [Maybe Types](#maybe-types). |
| `@` | [Type Annotations](#type-annotations). |
| `boolean`, `byte`, `int16`, `uint16`, `int32`, `uint32`, `handle`, `int64`, `uint64`, `double`, `string`, `objectpath`, `signature` | [Type Annotations](#type-annotations) |
| `b""`, `b''` | [Bytestrings](#bytestrings). |
| `%` | [Positional Parameters](#positional-parameters). |
## Booleans
The strings `true` and `false` are parsed as booleans. This is the only way
to specify a boolean value.
## Strings
Strings literals must be quoted using `""` or `''`. The two are completely
equivalent (except for the fact that each one is unable to contain itself
unescaped).
Strings are Unicode strings with no particular encoding. For example, to
specify the character `é`, you just write `'é'`. You could also give the
Unicode codepoint of that character (`U+E9`) as the escape sequence
`'\u00e9'`. Since the strings are pure Unicode, you should not attempt to
encode the UTF-8 byte sequence corresponding to the string using escapes; it
won't work and you'll end up with the individual characters corresponding to
each byte.
Unicode escapes of the form `\uxxxx` and `\Uxxxxxxxx` are supported, in
hexadecimal. The usual control sequence escapes `\a`, `\b`, `\f`, `\n`,
`\r`, `\t` and `\v` are supported. Additionally, a `\` before a newline
character causes the newline to be ignored. Finally, any other character
following `\` is copied literally (for example, `\"` or `\\`) but for
forwards compatibility with future additions you should only use this
feature when necessary for escaping backslashes or quotes.
The usual octal and hexadecimal escapes `\0nnn` and `\xnn` are not supported
here. Those escapes are used to encode byte values and `GVariant` strings
are Unicode.
Single-character strings are not interpreted as bytes. Bytes must be
specified by their numerical value.
## Numbers
Numbers are given by default as decimal values. Octal and hex values can be
given in the usual way (by prefixing with `0` or `0x`). Note that `GVariant`
considers bytes to be unsigned integers and will print them as a two digit
hexadecimal number by default.
Floating point numbers can also be given in the usual ways, including
scientific and hexadecimal notations.
For lack of additional information, integers will be parsed as `int32`
values by default. If the number has a point or an `e` in it, then it will
be parsed as a double precision floating point number by default. If type
information is available (either explicitly or inferred) then that type will
be used instead.
Some examples:
`5` parses as the `int32` value five.
`37.5` parses as a floating point value.
`3.75e1` parses the same as the value above.
`uint64 7` parses seven as a `uint64`. See [Type Annotations](#type-annotations).
## Tuples
Tuples are formed using the same syntax as Python. Here are some examples:
`()` parses as the empty tuple.
`(5,)` is a tuple containing a single value.
`("hello", 42)` is a pair. Note that values of different types are
permitted.
## Arrays
Arrays are formed using the same syntax as Python uses for lists (which is
arguably the term that `GVariant` should have used). Note that, unlike Python
lists, `GVariant` arrays are statically typed. This has two implications.
First, all items in the array must have the same type. Second, the type of
the array must be known, even in the case that it is empty. This means that
(unless there is some other way to infer it) type information will need to
be given explicitly for empty arrays.
The parser is able to infer some types based on the fact that all items in
an array must have the same type. See the examples below:
`[1]` parses (without additional type information) as a one-item array of
signed integers.
`[1, 2, 3]` parses (similarly) as a three-item array.
`[1, 2, 3.0]` parses as an array of doubles. This is the most simple case of
the type inferencing in action.
`[(1, 2), (3, 4.0)]` causes the 2 to also be parsed as a double (but the 1
and 3 are still integers).
`["", nothing]` parses as an array of maybe strings. The presence of
"nothing" clearly implies that the array elements are nullable.
`[[], [""]]` will parse properly because the type of the first (empty) array
can be inferred to be equal to the type of the second array (both are arrays
of strings).
`[b'hello', []]` looks odd but will parse properly. See
[Bytestrings](#bytestrings).
And some examples of errors:
`["hello", 42]` fails to parse due to conflicting types.
`[]` will fail to parse without additional type information.
## Dictionaries and Dictionary Entries
Dictionaries and dictionary entries are both specified using the `{}`
characters.
The dictionary syntax is more commonly used. This is what the printer elects
to use in the normal case of dictionary entries appearing in an array (AKA
"a dictionary"). The separate syntax for dictionary entries is typically
only used for when the entries appear on their own, outside of an array
(which is valid but unusual). Of course, you are free to use the dictionary
entry syntax within arrays but there is no good reason to do so (and the
printer itself will never do so). Note that, as with arrays, the type of
empty dictionaries must be established (either explicitly or through
inference).
The dictionary syntax is the same as Python's syntax for dictionaries. Some
examples:
`@a{sv} {}` parses as the empty dictionary of everyone's favourite type.
`@a{sv} []` is the same as above (owing to the fact that dictionaries are
really arrays).
`{1: "one", 2: "two", 3: "three"}` parses as a dictionary mapping integers
to strings.
The dictionary entry syntax looks just like a pair (2-tuple) that uses
braces instead of parens. The presence of a comma immediately following the
key differentiates it from the dictionary syntax (which features a colon
after the first key). Some examples:
`{1, "one"}` is a free-standing dictionary entry that can be parsed on its
own or as part of another container value.
`[{1, "one"}, {2, "two"}, {3, "three"}]` is exactly equivalent to the
dictionary example given above.
## Variants
Variants are denoted using angle brackets (aka "XML brackets"), `<>`. They
may not be omitted.
Using `<>` effectively disrupts the type inferencing that occurs between
array elements. This can have positive and negative effects.
`[<"hello">, <42>]` will parse whereas `["hello", 42]` would not.
`[<['']>, <[]>]` will fail to parse even though `[[''], []]` parses
successfully. You would need to specify `[<['']>, <@as []>]`.
`{"title": <"frobit">, "enabled": <true>, "width": <800>}` is an example of
perhaps the most pervasive use of both dictionaries and variants.
## Maybe Types
The syntax for specifying maybe types is inspired by Haskell.
The null case is specified using the keyword nothing and the non-null case
is explicitly specified using the keyword just. GVariant allows just to be
omitted in every case that it is able to unambiguously determine the
intention of the writer. There are two cases where it must be specified:
- when using nested maybes, in order to specify the just nothing case
- to establish the nullability of the type of a value without explicitly
specifying its full type
Some examples:
`just 'hello'` parses as a non-null nullable string.
`@ms 'hello'` is the same (demonstrating how just can be dropped if the type is already known).
`nothing` will not parse without extra type information.
`@ms nothing` parses as a null nullable string.
`[just 3, nothing]` is an array of nullable integers
`[3, nothing]` is the same as the above (demonstrating another place were just can be dropped).
`[3, just nothing]` parses as an array of maybe maybe integers (type `ammi`).
## Type Annotations
Type annotations allow additional type information to be given to the
parser. Depending on the context, this type information can change the
output of the parser, cause an error when parsing would otherwise have
succeeded or resolve an error when parsing would have otherwise failed.
Type annotations come in two forms: type codes and type keywords.
Type keywords can be seen as more verbose (and more legible) versions of a
common subset of the type codes. The type keywords `boolean`, `byte`,
`int16`, `uint16`, `int32`, `uint32`, `handle`, `int64`, `uint64`, `double`,
`string`, `objectpath` and literal signature are each exactly equivalent to
their corresponding type code.
Type codes are an `@` ("at" sign) followed by a definite `GVariant` type
string. Some examples:
`uint32 5` causes the number to be parsed unsigned instead of signed (the
default).
`@u 5` is the same
`objectpath "/org/gnome/xyz"` creates an object path instead of a normal
string
`@au []` specifies the type of the empty array (which would not parse
otherwise)
`@ms ""` indicates that a string value is meant to have a maybe type
## Bytestrings
The bytestring syntax is a piece of syntactic sugar meant to complement the
bytestring APIs in GVariant. It constructs arrays of non-`NUL` bytes (type
`ay`) with a `NUL` terminator at the end. These are normal C strings with no
particular encoding enforced, so the bytes may not be valid UTF-8.
Bytestrings are a special case of byte arrays; byte arrays (also type 'ay'),
in the general case, can contain a `NUL` byte at any position, and need not
end with a `NUL` byte.
Bytestrings are specified with either `b""` or `b''`. As with strings, there
is no fundamental difference between the two different types of quotes.
Bytestrings support the full range of escapes that you would expect (ie:
those supported by [`func@GLib.strcompress`]. This includes the normal control
sequence escapes (as mentioned in the section on strings) as well as octal
and hexadecimal escapes of the forms `\0nnn` and `\xnn`.
`b'abc'` is equivalent to `[byte 0x61, 0x62, 0x63, 0]`.
When formatting arrays of bytes, the printer will choose to display the
array as a bytestring if it contains a nul character at the end and no other
nul bytes within. Otherwise, it is formatted as a normal array.
## Positional Parameters
Positional parameters are not a part of the normal `GVariant` text format,
but they are mentioned here because they can be used with
[`ctor@GLib.Variant.new_parsed`].
A positional parameter is indicated with a `%` followed by any valid
[GVariant Format String](gvariant-format-strings.html). Variable arguments
are collected as specified by the format string and the resulting value is
inserted at the current position.
This feature is best explained by example:
```c
char *t = "xyz";
gboolean en = false;
GVariant *value;
value = g_variant_new_parsed ("{'title': <%s>, 'enabled': <%b>}", t, en);
```
This constructs a dictionary mapping strings to variants (type `a{sv}`) with
two items in it. The key names are parsed from the string and the values for
those keys are taken as variable arguments parameters.
The arguments are always collected in the order that they appear in the
string to be parsed. Format strings that collect multiple arguments are
permitted, so you may require more varargs parameters than the number of `%`
signs that appear. You can also give format strings that collect no
arguments, but there's no good reason to do so.

View File

@ -1,622 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<refentry id='gvariant-text'>
<refmeta>
<refentrytitle>GVariant Text Format</refentrytitle>
</refmeta>
<refnamediv>
<refname>GVariant Text Format</refname>
<refpurpose>textual representation of GVariants</refpurpose>
</refnamediv>
<refsect1>
<title>GVariant Text Format</title>
<para>
This page attempts to document the GVariant text format as produced by
<link linkend='g-variant-print'><function>g_variant_print()</function></link> and parsed by the
<link linkend='g-variant-parse'><function>g_variant_parse()</function></link> family of functions. In most
cases the style closely resembles the formatting of literals in Python but there are some additions and
exceptions.
</para>
<para>
The functions that deal with GVariant text format absolutely always deal in utf-8. Conceptually, GVariant
text format is a string of Unicode characters -- not bytes. Non-ASCII but otherwise printable Unicode
characters are not treated any differently from normal ASCII characters.
</para>
<para>
The parser makes two passes. The purpose of the first pass is to determine the type of the value being
parsed. The second pass does the actual parsing. Based on the fact that all elements in an array have to
have the same type, GVariant is able to make some deductions that would not otherwise be possible. As an
example:
<informalexample><programlisting>[[1, 2, 3], [4, 5, 6]]</programlisting></informalexample>
is parsed as an array of arrays of integers (type '<literal>aai</literal>'), but
<informalexample><programlisting>[[1, 2, 3], [4, 5, 6.0]]</programlisting></informalexample>
is parsed as an array of arrays of doubles (type '<literal>aad</literal>').
</para>
<para>
As another example, GVariant is able to determine that
<informalexample><programlisting>["hello", nothing]</programlisting></informalexample>
is an array of maybe strings (type '<literal>ams</literal>').
</para>
<para>
What the parser accepts as valid input is dependent on context. The API permits for out-of-band type
information to be supplied to the parser (which will change its behaviour). This can be seen in the
GSettings and GDBus command line utilities where the type information is available from the schema or the
remote introspection information. The additional information can cause parses to succeed when they would not
otherwise have been able to (by resolving ambiguous type information) or can cause them to fail (due to
conflicting type information). Unless stated otherwise, the examples given in this section assume that no
out-of-band type data has been given to the parser.
</para>
</refsect1>
<refsect1>
<title>Syntax Summary</title>
<para>
The following table describes the rough meaning of symbols that may appear inside GVariant text format.
Each symbol is described in detail in its own section, including usage examples.
</para>
<informaltable>
<tgroup cols='2'>
<colspec colname='col_0'/>
<colspec colname='col_1'/>
<tbody>
<row rowsep='1'>
<entry colsep='1' rowsep='1'>
<para>
<emphasis role='strong'>Symbol</emphasis>
</para>
</entry>
<entry colsep='1' rowsep='1'>
<para>
<emphasis role='strong'>Meaning</emphasis>
</para>
</entry>
</row>
<row rowsep='1'>
<entry colsep='1' rowsep='1'>
<para>
<emphasis role='strong'><literal>true</literal></emphasis>,
<emphasis role='strong'><literal>false</literal></emphasis>
</para>
</entry>
<entry colsep='1' rowsep='1'>
<para>
<link linkend='gvariant-text-booleans'>Booleans</link>.
</para>
</entry>
</row>
<row rowsep='1'>
<entry colsep='1' rowsep='1'>
<para>
<emphasis role='strong'><literal>""</literal></emphasis>,
<emphasis role='strong'><literal>''</literal></emphasis>
</para>
</entry>
<entry colsep='1' rowsep='1'>
<para>
String literal. See <link linkend='gvariant-text-strings'>Strings</link> below.
</para>
</entry>
</row>
<row rowsep='1'>
<entry colsep='1' rowsep='1'>
<para>
numbers
</para>
</entry>
<entry colsep='1' rowsep='1'>
<para>
See <link linkend='gvariant-text-numbers'>Numbers</link> below.
</para>
</entry>
</row>
<row rowsep='1'>
<entry colsep='1' rowsep='1'>
<para>
<emphasis role='strong'><literal>()</literal></emphasis>
</para>
</entry>
<entry colsep='1' rowsep='1'>
<para>
<link linkend='gvariant-text-tuples'>Tuples</link>.
</para>
</entry>
</row>
<row rowsep='1'>
<entry colsep='1' rowsep='1'>
<para>
<emphasis role='strong'><literal>[]</literal></emphasis>
</para>
</entry>
<entry colsep='1' rowsep='1'>
<para>
<link linkend='gvariant-text-arrays'>Arrays</link>.
</para>
</entry>
</row>
<row rowsep='1'>
<entry colsep='1' rowsep='1'>
<para>
<emphasis role='strong'><literal>{}</literal></emphasis>
</para>
</entry>
<entry colsep='1' rowsep='1'>
<para>
<link linkend='gvariant-text-dictionaries'>Dictionaries and Dictionary Entries</link>.
</para>
</entry>
</row>
<row rowsep='1'>
<entry colsep='1' rowsep='1'>
<para>
<emphasis role='strong'><literal>&lt;&gt;</literal></emphasis>
</para>
</entry>
<entry colsep='1' rowsep='1'>
<para>
<link linkend='gvariant-text-variants'>Variants</link>.
</para>
</entry>
</row>
<row rowsep='1'>
<entry colsep='1' rowsep='1'>
<para>
<emphasis role='strong'><literal>just</literal></emphasis>,
<emphasis role='strong'><literal>nothing</literal></emphasis>
</para>
</entry>
<entry colsep='1' rowsep='1'>
<para>
<link linkend='gvariant-text-maybe-types'>Maybe Types</link>.
</para>
</entry>
</row>
<row rowsep='1'>
<entry colsep='1' rowsep='1'>
<para>
<emphasis role='strong'><literal>@</literal></emphasis>
</para>
</entry>
<entry colsep='1' rowsep='1'>
<para>
<link linkend='gvariant-text-type-annotations'>Type Annotations</link>.
</para>
</entry>
</row>
<row rowsep='1'>
<entry colsep='1' rowsep='1'>
<para>
type keywords
</para>
</entry>
<entry colsep='1' rowsep='1'>
<para>
<literal>boolean</literal>,
<literal>byte</literal>,
<literal>int16</literal>,
<literal>uint16</literal>,
<literal>int32</literal>,
<literal>uint32</literal>,
<literal>handle</literal>,
<literal>int64</literal>,
<literal>uint64</literal>,
<literal>double</literal>,
<literal>string</literal>,
<literal>objectpath</literal>,
<literal>signature</literal>
</para>
<para>
See <link linkend='gvariant-text-type-annotations'>Type Annotations</link> below.
</para>
</entry>
</row>
<row rowsep='1'>
<entry colsep='1' rowsep='1'>
<para>
<emphasis role='strong'><literal>b""</literal></emphasis>,
<emphasis role='strong'><literal>b''</literal></emphasis>
</para>
</entry>
<entry colsep='1' rowsep='1'>
<para>
<link linkend='gvariant-text-bytestrings'>Bytestrings</link>.
</para>
</entry>
</row>
<row rowsep='1'>
<entry colsep='1' rowsep='1'>
<para>
<emphasis role='strong'><literal>%</literal></emphasis>
</para>
</entry>
<entry colsep='1' rowsep='1'>
<para>
<link linkend='gvariant-text-positional'>Positional Parameters</link>.
</para>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<refsect2 id='gvariant-text-booleans'>
<title>Booleans</title>
<para>
The strings <literal>true</literal> and <literal>false</literal> are parsed as booleans. This is the only
way to specify a boolean value.
</para>
</refsect2>
<refsect2 id='gvariant-text-strings'>
<title>Strings</title>
<para>
Strings literals must be quoted using <literal>""</literal> or <literal>''</literal>. The two are
completely equivalent (except for the fact that each one is unable to contain itself unescaped).
</para>
<para>
Strings are Unicode strings with no particular encoding. For example, to specify the character
<literal>é</literal>, you just write <literal>'é'</literal>. You could also give the Unicode codepoint of
that character (U+E9) as the escape sequence <literal>'\u00e9'</literal>. Since the strings are pure
Unicode, you should not attempt to encode the utf-8 byte sequence corresponding to the string using escapes;
it won't work and you'll end up with the individual characters corresponding to each byte.
</para>
<para>
Unicode escapes of the form <literal>\uxxxx</literal> and <literal>\Uxxxxxxxx</literal> are supported, in
hexadecimal. The usual control sequence escapes <literal>\a</literal>, <literal>\b</literal>,
<literal>\f</literal>, <literal>\n</literal>, <literal>\r</literal>, <literal>\t</literal> and
<literal>\v</literal> are supported. Additionally, a <literal>\</literal> before a newline character causes
the newline to be ignored. Finally, any other character following <literal>\</literal> is copied literally
(for example, <literal>\"</literal> or <literal>\\</literal>) but for forwards compatibility with future
additions you should only use this feature when necessary for escaping backslashes or quotes.
</para>
<para>
The usual octal and hexadecimal escapes <literal>\0nnn</literal> and <literal>\xnn</literal> are not
supported here. Those escapes are used to encode byte values and GVariant strings are Unicode.
</para>
<para>
Single-character strings are not interpreted as bytes. Bytes must be specified by their numerical value.
</para>
</refsect2>
<refsect2 id='gvariant-text-numbers'>
<title>Numbers</title>
<para>
Numbers are given by default as decimal values. Octal and hex values can be given in the usual way (by
prefixing with <literal>0</literal> or <literal>0x</literal>). Note that GVariant considers bytes to be
unsigned integers and will print them as a two digit hexadecimal number by default.
</para>
<para>
Floating point numbers can also be given in the usual ways, including scientific and hexadecimal notations.
</para>
<para>
For lack of additional information, integers will be parsed as int32 values by default. If the number has a
point or an 'e' in it, then it will be parsed as a double precision floating point number by default. If
type information is available (either explicitly or inferred) then that type will be used instead.
</para>
<para>
Some examples:
</para>
<para>
<literal>5</literal> parses as the int32 value five.
</para>
<para>
<literal>37.5</literal> parses as a floating point value.
</para>
<para>
<literal>3.75e1</literal> parses the same as the value above.
</para>
<para>
<literal>uint64 7</literal> parses seven as a uint64.
See <link linkend='gvariant-text-type-annotations'>Type Annotations</link>.
</para>
</refsect2>
<refsect2 id='gvariant-text-tuples'>
<title>Tuples</title>
<para>
Tuples are formed using the same syntax as Python. Here are some examples:
</para>
<para>
<literal>()</literal> parses as the empty tuple.
</para>
<para>
<literal>(5,)</literal> is a tuple containing a single value.
</para>
<para>
<literal>("hello", 42)</literal> is a pair. Note that values of different types are permitted.
</para>
</refsect2>
<refsect2 id='gvariant-text-arrays'>
<title>Arrays</title>
<para>
Arrays are formed using the same syntax as Python uses for lists (which is arguably the term that GVariant
should have used). Note that, unlike Python lists, GVariant arrays are statically typed. This has two
implications.
</para>
<para>
First, all items in the array must have the same type. Second, the type of the array must be known, even in
the case that it is empty. This means that (unless there is some other way to infer it) type information
will need to be given explicitly for empty arrays.
</para>
<para>
The parser is able to infer some types based on the fact that all items in an array must have the same type.
See the examples below:
</para>
<para>
<literal>[1]</literal> parses (without additional type information) as a one-item array of signed integers.
</para>
<para>
<literal>[1, 2, 3]</literal> parses (similarly) as a three-item array.
</para>
<para>
<literal>[1, 2, 3.0]</literal> parses as an array of doubles. This is the most simple case of the type
inferencing in action.
</para>
<para>
<literal>[(1, 2), (3, 4.0)]</literal> causes the 2 to also be parsed as a double (but the 1 and 3 are still
integers).
</para>
<para>
<literal>["", nothing]</literal> parses as an array of maybe strings. The presence of
"<literal>nothing</literal>" clearly implies that the array elements are nullable.
</para>
<para>
<literal>[[], [""]]</literal> will parse properly because the type of the first (empty) array can be
inferred to be equal to the type of the second array (both are arrays of strings).
</para>
<para>
<literal>[b'hello', []]</literal> looks odd but will parse properly.
See <link linkend='gvariant-text-bytestrings'>Bytestrings</link>
</para>
<para>
And some examples of errors:
</para>
<para>
<literal>["hello", 42]</literal> fails to parse due to conflicting types.
</para>
<para>
<literal>[]</literal> will fail to parse without additional type information.
</para>
</refsect2>
<refsect2 id='gvariant-text-dictionaries'>
<title>Dictionaries and Dictionary Entries</title>
<para>
Dictionaries and dictionary entries are both specified using the <literal>{}</literal> characters.
</para>
<para>
The dictionary syntax is more commonly used. This is what the printer elects to use in the normal case of
dictionary entries appearing in an array (aka "a dictionary"). The separate syntax for dictionary entries
is typically only used for when the entries appear on their own, outside of an array (which is valid but
unusual). Of course, you are free to use the dictionary entry syntax within arrays but there is no good
reason to do so (and the printer itself will never do so). Note that, as with arrays, the type of empty
dictionaries must be established (either explicitly or through inference).
</para>
<para>
The dictionary syntax is the same as Python's syntax for dictionaries. Some examples:
</para>
<para>
<literal>@a{sv} {}</literal> parses as the empty dictionary of everyone's favourite type.
</para>
<para>
<literal>@a{sv} []</literal> is the same as above (owing to the fact that dictionaries are really arrays).
</para>
<para>
<literal>{1: "one", 2: "two", 3: "three"}</literal> parses as a dictionary mapping integers to strings.
</para>
<para>
The dictionary entry syntax looks just like a pair (2-tuple) that uses braces instead of parens. The
presence of a comma immediately following the key differentiates it from the dictionary syntax (which
features a colon after the first key). Some examples:
</para>
<para>
<literal>{1, "one"}</literal> is a free-standing dictionary entry that can be parsed on its own or as part
of another container value.
</para>
<para>
<literal>[{1, "one"}, {2, "two"}, {3, "three"}]</literal> is exactly equivalent to the dictionary example
given above.
</para>
</refsect2>
<refsect2 id='gvariant-text-variants'>
<title>Variants</title>
<para>
Variants are denoted using angle brackets (aka "XML brackets"), <literal>&lt;&gt;</literal>. They may not
be omitted.
</para>
<para>
Using <literal>&lt;&gt;</literal> effectively disrupts the type inferencing that occurs between array
elements. This can have positive and negative effects.
</para>
<para>
<literal>[&lt;"hello"&gt;, &lt;42&gt;]</literal> will parse whereas <literal>["hello", 42]</literal> would
not.
</para>
<para>
<literal>[&lt;['']&gt;, &lt;[]&gt;]</literal> will fail to parse even though <literal>[[''], []]</literal>
parses successfully. You would need to specify <literal>[&lt;['']&gt;, &lt;@as []&gt;]</literal>.
</para>
<para>
<literal>{"title": &lt;"frobit"&gt;, "enabled": &lt;true&gt;, "width": &lt;800&gt;}</literal> is an example of
perhaps the most pervasive use of both dictionaries and variants.
</para>
</refsect2>
<refsect2 id='gvariant-text-maybe-types'>
<title>Maybe Types</title>
<para>
The syntax for specifying maybe types is inspired by Haskell.
</para>
<para>
The null case is specified using the keyword <literal>nothing</literal> and the non-null case is explicitly
specified using the keyword <literal>just</literal>. GVariant allows <literal>just</literal> to be omitted
in every case that it is able to unambiguously determine the intention of the writer. There are two cases
where it must be specified:
</para>
<itemizedlist>
<listitem>
<para>when using nested maybes, in order to specify the <literal>just nothing</literal> case</para>
</listitem>
<listitem>
<para>
to establish the nullability of the type of a value without explicitly specifying its full type
</para>
</listitem>
</itemizedlist>
<para>
Some examples:
</para>
<para>
<literal>just 'hello'</literal> parses as a non-null nullable string.
</para>
<para>
<literal>@ms 'hello'</literal> is the same (demonstrating how <literal>just</literal> can be dropped if the type is already
known).
</para>
<para>
<literal>nothing</literal> will not parse wtihout extra type information.
</para>
<para>
<literal>@ms nothing</literal> parses as a null nullable string.
</para>
<para>
<literal>[just 3, nothing]</literal> is an array of nullable integers
</para>
<para>
<literal>[3, nothing]</literal> is the same as the above (demonstrating another place were
<literal>just</literal> can be dropped).
</para>
<para>
<literal>[3, just nothing]</literal> parses as an array of maybe maybe integers (type
<literal>'ammi'</literal>).
</para>
</refsect2>
<refsect2 id='gvariant-text-type-annotations'>
<title>Type Annotations</title>
<para>
Type annotations allow additional type information to be given to the parser. Depending on the context,
this type information can change the output of the parser, cause an error when parsing would otherwise have
succeeded or resolve an error when parsing would have otherwise failed.
</para>
<para>
Type annotations come in two forms: type codes and type keywords.
</para>
<para>
Type keywords can be seen as more verbose (and more legible) versions of a common subset of the type codes.
The type keywords <literal>boolean</literal>, <literal>byte</literal>, <literal>int16</literal>,
<literal>uint16</literal>, <literal>int32</literal>, <literal>uint32</literal>, <literal>handle</literal>,
<literal>int64</literal>, <literal>uint64</literal>, <literal>double</literal>, <literal>string</literal>,
<literal>objectpath</literal> and literal <literal>signature</literal> are each exactly equivalent to their
corresponding type code.
</para>
<para>
Type codes are an <literal>@</literal> ("at" sign) followed by a definite GVariant type string. Some
examples:
</para>
<para>
<literal>uint32 5</literal> causes the number to be parsed unsigned instead of signed (the default).
</para>
<para>
<literal>@u 5</literal> is the same
</para>
<para>
<literal>objectpath "/org/gnome/xyz"</literal> creates an object path instead of a normal string
</para>
<para>
<literal>@au []</literal> specifies the type of the empty array (which would not parse otherwise)
</para>
<para>
<literal>@ms ""</literal> indicates that a string value is meant to have a maybe type
</para>
</refsect2>
<refsect2 id='gvariant-text-bytestrings'>
<title>Bytestrings</title>
<para>
The bytestring syntax is a piece of syntactic sugar meant to complement the bytestring APIs in GVariant. It
constructs arrays of non-nul bytes (type '<literal>ay</literal>') with a nul terminator at the end. These are
normal C strings with no particular encoding enforced, so the bytes may not be valid UTF-8.
Bytestrings are a special case of byte arrays; byte arrays (also type '<literal>ay</literal>'), in the general
case, can contain nul at any position, and need not end with nul.
</para>
<para>
Bytestrings are specified with either <literal>b""</literal> or <literal>b''</literal>. As with strings,
there is no fundamental difference between the two different types of quotes.
</para>
<para>
Bytestrings support the full range of escapes that you would expect (ie: those supported by
<link linkend='g-strcompress'><function>g_strcompress()</function></link>. This includes the normal control
sequence escapes (as mentioned in the section on strings) as well as octal and hexadecimal escapes of the
forms <literal>\0nnn</literal> and <literal>\xnn</literal>.
</para>
<para>
<literal>b'abc'</literal> is equivalent to <literal>[byte 0x61, 0x62, 0x63, 0]</literal>.
</para>
<para>
When formatting arrays of bytes, the printer will choose to display the array as a bytestring if it contains
a nul character at the end and no other nul bytes within. Otherwise, it is formatted as a normal array.
</para>
</refsect2>
<refsect2 id='gvariant-text-positional'>
<title>Positional Parameters</title>
<para>
Positional parameters are not a part of the normal GVariant text format, but they are mentioned here because
they can be used with <link linkend='g-variant-new-parsed'><function>g_variant_new_parsed()</function></link>.
</para>
<para>
A positional parameter is indicated with a <literal>%</literal> followed by any valid
<link linkend='gvariant-format-strings'>GVariant Format String</link>. Variable arguments are collected as
specified by the format string and the resulting value is inserted at the current position.
</para>
<para>
This feature is best explained by example:
</para>
<informalexample><programlisting><![CDATA[char *t = "xyz";
gboolean en = false;
GVariant *value;
value = g_variant_new_parsed ("{'title': <%s>, 'enabled': <%b>}", t, en);]]></programlisting></informalexample>
<para>
This constructs a dictionary mapping strings to variants (type '<literal>a{sv}</literal>') with two items in
it. The key names are parsed from the string and the values for those keys are taken as variable arguments
parameters.
</para>
<para>
The arguments are always collected in the order that they appear in the string to be parsed. Format strings
that collect multiple arguments are permitted, so you may require more varargs parameters than the number of
<literal>%</literal> signs that appear. You can also give format strings that collect no arguments, but
there's no good reason to do so.
</para>
</refsect2>
</refsect1>
</refentry>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
Title: Internationalization
# Internationalization
GLib doesn't force any particular localization method upon its users. But
since GLib itself is localized using the `gettext()` mechanism, it seems
natural to offer the de-facto standard `gettext()` support macros in an
easy-to-use form.
In order to use these macros in an application, you must include
`<glib/gi18n.h>`. For use in a library, you must include `<glib/gi18n-lib.h>`
after defining the `GETTEXT_PACKAGE` macro suitably for your library:
```c
#define GETTEXT_PACKAGE "gtk4"
#include <glib/gi18n-lib.h>
```
For an application, note that you also have to call `bindtextdomain()`,
`bind_textdomain_codeset()`, `textdomain()` and `setlocale()` early on in your
`main()` to make `gettext()` work. For example:
```c
#include <glib/gi18n.h>
#include <locale.h>
int
main (int argc, char **argv)
{
setlocale (LC_ALL, "");
bindtextdomain (GETTEXT_PACKAGE, DATADIR "/locale");
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
// Rest of your application.
}
```
where `DATADIR` is as typically provided by Automake or Meson.
For a library, you only have to call `bindtextdomain()` and
`bind_textdomain_codeset()` in your initialization function. If your library
doesn't have an initialization function, you can call the functions before
the first translated message.
The [gettext
manual](http://www.gnu.org/software/gettext/manual/gettext.html#Maintainers)
covers details of how to integrate gettext into a projects build system and
workflow.

View File

@ -0,0 +1,137 @@
Title: Message Logging
# Message Logging
The `g_return` family of macros (`g_return_if_fail()`,
`g_return_val_if_fail()`, `g_return_if_reached()`,
`g_return_val_if_reached()`) should only be used for programming errors, a
typical use case is checking for invalid parameters at the beginning of a
public function. They should not be used if you just mean "if (error)
return", they should only be used if you mean "if (bug in program) return".
The program behavior is generally considered undefined after one of these
checks fails. They are not intended for normal control flow, only to give a
perhaps-helpful warning before giving up.
Structured logging output is supported using `g_log_structured()`. This
differs from the traditional `g_log()` API in that log messages are handled
as a collection of keyvalue pairs representing individual pieces of
information, rather than as a single string containing all the information
in an arbitrary format.
The convenience macros `g_info()`, `g_message()`, `g_debug()`, `g_warning()`
and `g_error()` will use the traditional `g_log()` API unless you define the
symbol `G_LOG_USE_STRUCTURED` before including `glib.h`. But note that even
messages logged through the traditional `g_log()` API are ultimatively
passed to `g_log_structured()`, so that all log messages end up in same
destination. If `G_LOG_USE_STRUCTURED` is defined, `g_test_expect_message()`
will become ineffective for the wrapper macros `g_warning()` and friends
(see [Testing for Messages](#testing-for-messages).)
The support for structured logging was motivated by the following needs
(some of which were supported previously; others werent):
- Support for multiple logging levels.
- Structured log support with the ability to add `MESSAGE_ID`s (see
`g_log_structured()`).
- Moving the responsibility for filtering log messages from the program to
the log viewer — instead of libraries and programs installing log handlers
(with `g_log_set_handler()`) which filter messages before output, all log
messages are outputted, and the log viewer program (such as
[`journalctl`](https://www.freedesktop.org/software/systemd/man/journalctl.html))
must filter them. This is based on the idea that bugs are sometimes hard
to reproduce, so it is better to log everything possible and then use
tools to analyse the logs than it is to not be able to reproduce a bug to
get additional log data. Code which uses logging in performance-critical
sections should compile out the `g_log_structured()` calls in release
builds, and compile them in in debugging builds.
- A single writer function which handles all log messages in a process, from
all libraries and program code; rather than multiple log handlers with
poorly defined interactions between them. This allows a program to easily
change its logging policy by changing the writer function, for example to
log to an additional location or to change what logging output fallbacks
are used. The log writer functions provided by GLib are exposed publicly
so they can be used from programs log writers. This allows log writer
policy and implementation to be kept separate.
- If a library wants to add standard information to all of its log messages
(such as library state) or to redact private data (such as passwords or
network credentials), it should use a wrapper function around its
`g_log_structured()` calls or implement that in the single log writer
function.
- If a program wants to pass context data from a `g_log_structured()` call
to its log writer function so that, for example, it can use the correct
server connection to submit logs to, that user data can be passed as a
zero-length `GLogField` to `g_log_structured_array()`.
- Color output needed to be supported on the terminal, to make reading
through logs easier.
## Using Structured Logging
To use structured logging (rather than the old-style logging), either use
the `g_log_structured()` and `g_log_structured_array()` functions; or define
`G_LOG_USE_STRUCTURED` before including any GLib header, and use the
`g_message()`, `g_debug()`, `g_error()` (etc.) macros.
You do not need to define `G_LOG_USE_STRUCTURED` to use
`g_log_structured()`, but it is a good idea to avoid confusion.
## Log Domains
Log domains may be used to broadly split up the origins of log messages.
Typically, there are one or a few log domains per application or library.
`G_LOG_DOMAIN` should be used to define the default log domain for the current
compilation unit — it is typically defined at the top of a source file, or
in the preprocessor flags for a group of source files.
Log domains must be unique, and it is recommended that they are the
application or library name, optionally followed by a hyphen and a
sub-domain name. For example, `bloatpad` or `bloatpad-io`.
## Debug Message Output
The default log functions (`g_log_default_handler()` for the old-style API
and `g_log_writer_default()` for the structured API) both drop debug and
informational messages by default, unless the log domains of those messages
are listed in the `G_MESSAGES_DEBUG` environment variable (or it is set to
`all`).
It is recommended that custom log writer functions re-use the
`G_MESSAGES_DEBUG` environment variable, rather than inventing a custom one,
so that developers can re-use the same debugging techniques and tools across
projects. Since GLib 2.68, this can be implemented by dropping messages for
which `g_log_writer_default_would_drop()` returns `TRUE`.
## Testing for Messages
With the old `g_log()` API, `g_test_expect_message()` and
`g_test_assert_expected_messages()` could be used in simple cases to check
whether some code under test had emitted a given log message. These
functions have been deprecated with the structured logging API, for several
reasons:
- They relied on an internal queue which was too inflexible for many use
cases, where messages might be emitted in several orders, some messages
might not be emitted deterministically, or messages might be emitted by
unrelated log domains.
- They do not support structured log fields.
- Examining the log output of code is a bad approach to testing it, and
while it might be necessary for legacy code which uses `g_log()`, it
should be avoided for new code using `g_log_structured()`.
They will continue to work as before if `g_log()` is in use (and
`G_LOG_USE_STRUCTURED` is not defined). They will do nothing if used with
the structured logging API.
Examining the log output of code is discouraged: libraries should not emit
to stderr during defined behaviour, and hence this should not be tested. If
the log emissions of a library during undefined behaviour need to be tested,
they should be limited to asserting that the library aborts and prints a
suitable error message before aborting. This should be done with
`g_test_trap_assert_stderr()`.
If it is really necessary to test the structured log messages emitted by a
particular piece of code and the code cannot be restructured to be more
suitable to more conventional unit testing you should write a custom log
writer function (see `g_log_set_writer_func()`) which appends all log
messages to a queue. When you want to check the log messages, examine and
clear the queue, ignoring irrelevant log messages (for example, from log
domains other than the one under test).

View File

@ -0,0 +1,870 @@
Title: Macros
# Macros
GLib provides a set of C pre-processor macros and symbols for commonly-used
language and platform features.
## Platform
`G_OS_WIN32`
: This macro is defined only on Windows, so you can bracket Windows-specific
code using `#ifdef G_OS_WIN32 ... #endif`.
`G_OS_UNIX`
: This macro is defined only on UNIX and UNIX-like systems, so you can bracket
UNIX-specific code in `#ifdef G_OS_UNIX ... #endif`. To detect whether to
compile features that require a specific kernel or operating system, check
for the appropriate OS-specific predefined macros instead, for example:
- Linux kernel (any libc, including glibc, musl or Android): `#ifdef __linux__`
- Linux kernel and GNU user-space: `#if defined(__linux__) && defined(__GLIBC__)`
- FreeBSD kernel (any libc, including glibc): `#ifdef __FreeBSD_kernel__`
- FreeBSD kernel and user-space: `#ifdef __FreeBSD__`
- Apple operating systems (macOS, iOS, tvOS), regardless of whether
Cocoa/Carbon toolkits are available: `#ifdef __APPLE__`
See <https://sourceforge.net/p/predef/wiki/OperatingSystems/> for more.
`G_DIR_SEPARATOR`
: The directory separator character. This is `'/'` on UNIX machines and `'\'` under Windows.
`G_DIR_SEPARATOR_S`
: The directory separator as a string. This is `"/"` on UNIX machines and `"\"` under Windows.
`G_IS_DIR_SEPARATOR(ch)`
: Checks whether a character is a directory separator. It returns true for `'/'` on UNIX machines and for `'\'` or `'/'` under Windows. Available since 2.6.
`G_SEARCHPATH_SEPARATOR`
: The search path separator character. This is `':'` on UNIX machines and `';'` under Windows.
`G_SEARCHPATH_SEPARATOR_S`
: The search path separator as a string. This is `":"` on UNIX machines and `";"` under Windows.
## Values
`TRUE`
: Defines the true value for the `gboolean` type.
`FALSE`
: Defines the false value for the `gboolean` type.
`NULL`
: Defines the standard `NULL` pointer.
## Maths
`MIN(a, b)`
: Calculates the minimum of `a` and `b`.
`MAX(a, b)`
: Calculates the maximum of `a` and `b`.
`ABS(value)`
: Calculates the absolute value of a given numerical value. The absolute value
is simply the number with any negative sign taken away.
For example,
- `ABS(-10)` is 10.
- `ABS(10)` is also 10.
`CLAMP(value, low, high)`
: Ensures that a value is between the limits set by `low` and `high`. If `low` is
greater than `high` the result is undefined.
For example,
- `CLAMP(5, 10, 15)` is 10.
- `CLAMP(15, 5, 10)` is 10.
- `CLAMP(20, 15, 25)` is 20.
`G_APPROX_VALUE(a, b, epsilon)`
: Evaluates to true if the absolute difference between the given numerical
values `a` and `b` is smaller than `epsilon`, and to false otherwise.
For example,
- `G_APPROX_VALUE (5, 6, 2)` evaluates to true
- `G_APPROX_VALUE (3.14, 3.15, 0.001)` evaluates to false
- `G_APPROX_VALUE (n, 0.f, FLT_EPSILON)` evaluates to true if `n` is within
the single precision floating point epsilon from zero
Available since: 2.58
## Structure Access
`G_STRUCT_MEMBER(member_type, struct_pointer, offset)`
: Returns a member of a structure at a given offset, using the given type.
`G_STRUCT_MEMBER_P(struct_pointer, offset)`
: Returns an untyped pointer to a given offset of a struct.
`G_STRUCT_OFFSET(struct_type, member_name)`
: Returns the offset, in bytes, of a member of a struct.
Consider using standard C `offsetof()`, available since at least C89
and C++98, in new code (but note that `offsetof()` returns a `size_t`
rather than a `long`).
## Array Utilties
`G_N_ELEMENTS(array)`
: Determines the number of elements in an array. The array must be
declared so the compiler knows its size at compile-time; this
macro will not work on an array allocated on the heap, only static
arrays or arrays on the stack.
## Miscellaneous Macros
These macros provide more specialized features which are not needed so often
by application programmers.
`G_STMT_START`
: Starts a multi-statement macro block so that it can be used in places
where only one statement is expected by the compiler.
`G_STMT_END`
: Ends a multi-statement macro block so that it can be used in places
where only one statement is expected by the compiler.
`G_BEGIN_DECLS`
: Used (along with `G_END_DECLS`) to bracket C header files that may be
included by C++ sources. If the compiler in use is a C++ compiler, starts
an `extern "C"` around the header.
`G_END_DECLS`
: Used (along with `G_BEGIN_DECLS`) to bracket C header files that may be
included by C++ sources, or compiled by a C++ compiler. If the compiler
in use is a C++ compiler, ends the `extern "C"` block around the header.
`G_VA_COPY(ap1, ap2)`
: Portable way to copy `va_list` variables.
In order to use this function, you must include `string.h` yourself,
because this macro may use `memmove()` and GLib does not include
`string.h` for you.
Each invocation of `G_VA_COPY (ap1, ap2)` must be matched with a
corresponding `va_end (ap1)` call in the same function.
This is equivalent to standard C `va_copy()`, available since C99
and C++11, which should be preferred in new code.
`G_STRINGIFY(macro_or_string)`
: Accepts a macro or a string and converts it into a string after
preprocessor argument expansion. For example, the following code:
#define AGE 27
const gchar *greeting = G_STRINGIFY (AGE) " today!";
is transformed by the preprocessor into (code equivalent to):
const gchar *greeting = "27 today!";
`G_PASTE(identifier1, identifier2)`
: Yields a new preprocessor pasted identifier `identifier1identifier2` from its expanded
arguments `identifier1` and `identifier2`. For example,the following code:
#define GET(traveller,method) G_PASTE(traveller_get_, method) (traveller)
const char *name = GET (traveller, name);
const char *quest = GET (traveller, quest);
Color *favourite = GET (traveller, favourite_colour);
is transformed by the preprocessor into:
const char *name = traveller_get_name (traveller);
const char *quest = traveller_get_quest (traveller);
Color *favourite = traveller_get_favourite_colour (traveller);
Available since: 2.20
`G_STATIC_ASSERT(expr)`
: The `G_STATIC_ASSERT()` macro lets the programmer check a condition at
compile time. The condition needs to be compile time computable. The
macro can be used in any place where a `typedef` is valid.
A `typedef` is generally allowed in exactly the same places that
a variable declaration is allowed. For this reason, you should
not use `G_STATIC_ASSERT()` in the middle of blocks of code.
The macro should only be used once per source code line.
Since: 2.20
`G_STATIC_ASSERT_EXPR(expr)`
: The `G_STATIC_ASSERT_EXPR()` macro lets the programmer check a condition
at compile time. The condition needs to be compile time computable.
Unlike `G_STATIC_ASSERT()`, this macro evaluates to an expression
and, as such, can be used in the middle of other expressions.
Its value should be ignored. This can be accomplished by placing
it as the first argument of a comma expression.
#define ADD_ONE_TO_INT(x) \
(G_STATIC_ASSERT_EXPR(sizeof (x) == sizeof (int)), ((x) + 1))
Since: 2.30
## Compiler
`G_GNUC_EXTENSION`
: Expands to `__extension__` when GCC is used as the compiler. This simply
tells GCC not to warn about the following non-standard code when compiling
with the `-pedantic` option.
`G_GNUC_CONST`
: Expands to the GNU C `const` function attribute if the compiler is GCC.
Declaring a function as `const` enables better optimization of calls to
the function. A `const` function doesn't examine any values except its
parameters, and has no effects except its return value.
Place the attribute after the declaration, just before the semicolon.
gchar g_ascii_tolower (gchar c) G_GNUC_CONST;
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute) for more details.
A function that has pointer arguments and examines the data pointed to
must not be declared `const`. Likewise, a function that calls a non-`const`
function usually must not be `const`. It doesn't make sense for a `const`
function to return `void`.
`G_GNUC_PURE`
: Expands to the GNU C `pure` function attribute if the compiler is GCC.
Declaring a function as `pure` enables better optimization of calls to
the function. A `pure` function has no effects except its return value
and the return value depends only on the parameters and/or global
variables.
Place the attribute after the declaration, just before the semicolon.
gboolean g_type_check_value (const GValue *value) G_GNUC_PURE;
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute) for more details.
`G_GNUC_UNUSED`
: Expands to the GNU C `unused` function attribute if the compiler is gcc.
It is used for declaring functions and arguments which may never be used.
It avoids possible compiler warnings.
For functions, place the attribute after the declaration, just before the
semicolon. For arguments, place the attribute at the beginning of the
argument declaration.
void my_unused_function (G_GNUC_UNUSED gint unused_argument,
gint other_argument) G_GNUC_UNUSED;
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-unused-function-attribute) for more details.
`G_GNUC_MALLOC`
: Expands to the GNU C `malloc` function attribute if the compiler is GCC.
Declaring a function as `malloc` enables better optimization of the function,
but must only be done if the allocation behaviour of the function is fully
understood, otherwise miscompilation can result.
A function can have the `malloc` attribute if it returns a pointer which is
guaranteed to not alias with any other pointer valid when the function
returns, and moreover no pointers to valid objects occur in any storage
addressed by the returned pointer.
In practice, this means that `G_GNUC_MALLOC` can be used with any function
which returns unallocated or zeroed-out memory, but not with functions which
return initialised structures containing other pointers, or with functions
that reallocate memory. This definition changed in GLib 2.58 to match the
stricter definition introduced around GCC 5.
Place the attribute after the declaration, just before the semicolon.
gpointer g_malloc (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-functions-that-behave-like-malloc)
for more details.
Since: 2.6
`G_GNUC_DEPRECATED`
: Expands to the GNU C `deprecated` attribute if the compiler is GCC.
It can be used to mark `typedef`s, variables and functions as deprecated.
When called with the `-Wdeprecated-declarations` option,
gcc will generate warnings when deprecated interfaces are used.
Place the attribute after the declaration, just before the semicolon.
int my_mistake (void) G_GNUC_DEPRECATED;
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-deprecated-function-attribute) for more details.
See also: `G_DEPRECATED`
Since: 2.2
`G_GNUC_DEPRECATED_FOR(func)`
: Like `G_GNUC_DEPRECATED`, but names the intended replacement for the
deprecated symbol if the version of gcc in use is new enough to support
custom deprecation messages.
Place the attribute after the declaration, just before the semicolon.
int my_mistake (void) G_GNUC_DEPRECATED_FOR(my_replacement);
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-deprecated-function-attribute) for more details.
Note that if `func` is a macro, it will be expanded in the warning message.
You can enclose it in quotes to prevent this. (The quotes will show up
in the warning, but it's better than showing the macro expansion.)
Since: 2.26
`G_GNUC_NORETURN`
: Expands to the GNU C `noreturn` function attribute if the compiler is GCC.
It is used for declaring functions which never return. It enables
optimization of the function, and avoids possible compiler warnings.
Since 2.68, it is recommended that code uses `G_NORETURN` instead of
`G_GNUC_NORETURN`, as that works on more platforms and compilers (in
particular, MSVC and C++11) than `G_GNUC_NORETURN`, which works with GCC and
Clang only. `G_GNUC_NORETURN` continues to work, so has not been deprecated
yet.
Place the attribute after the declaration, just before the semicolon.
void g_abort (void) G_GNUC_NORETURN;
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noreturn-function-attribute) for more details.
`G_GNUC_FALLTHROUGH`
: Expands to the GNU C `fallthrough` statement attribute if the compiler supports it.
This allows declaring case statement to explicitly fall through in switch
statements. To enable this feature, use `-Wimplicit-fallthrough` during
compilation.
Put the attribute right before the case statement you want to fall through to.
switch (foo)
{
case 1:
g_message ("it's 1");
G_GNUC_FALLTHROUGH;
case 2:
g_message ("it's either 1 or 2");
break;
}
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#index-fallthrough-statement-attribute) for more details.
Since: 2.60
`G_GNUC_FORMAT(idx)`
: Expands to the GNU C `format_arg` function attribute if the compiler
is GCC. This function attribute specifies that a function takes a
format string for a `printf()`, `scanf()`, `strftime()` or `strfmon()`
style function and modifies it, so that the result can be passed to
a `printf()`, `scanf()`, `strftime()` or `strfmon()` style function
(with the remaining arguments to the format function the same as they
would have been for the unmodified string).
Place the attribute after the function declaration, just before the
semicolon.
gchar *g_dgettext (gchar *domain_name, gchar *msgid) G_GNUC_FORMAT (2);
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-Wformat-nonliteral-1) for more details.
`G_GNUC_NULL_TERMINATED`
: Expands to the GNU C `sentinel` function attribute if the compiler is GCC.
This function attribute only applies to variadic functions and instructs
the compiler to check that the argument list is terminated with an
explicit `NULL`.
Place the attribute after the declaration, just before the semicolon.
gchar *g_strconcat (const gchar *string1,
...) G_GNUC_NULL_TERMINATED;
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-sentinel-function-attribute) for more details
Since: 2.8
`G_GNUC_WARN_UNUSED_RESULT`
: Expands to the GNU C `warn_unused_result` function attribute if the compiler
is GCC. This function attribute makes the compiler emit a warning if the
result of a function call is ignored.
Place the attribute after the declaration, just before the semicolon.
GList *g_list_append (GList *list,
gpointer data) G_GNUC_WARN_UNUSED_RESULT;
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-warn_005funused_005fresult-function-attribute) for more details.
Since: 2.10
`G_GNUC_NO_INLINE`
: Expands to the GNU C `noinline` function attribute if the compiler is GCC.
Declaring a function as `noinline` prevents the function from being
considered for inlining.
This macro is provided for retro-compatibility and will be eventually
deprecated; `G_NO_INLINE` should be used instead.
The attribute may be placed before the declaration or definition,
right before the `static` keyword.
G_GNUC_NO_INLINE
static int
do_not_inline_this (void)
{
// ...
}
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noinline-function-attribute)
for more details.
See also: `G_NO_INLINE`, `G_ALWAYS_INLINE`.
Since: 2.58
`G_GNUC_NO_INSTRUMENT`
: Expands to the GNU C `no_instrument_function` function attribute if the
compiler is GCC. Functions with this attribute will not be instrumented
for profiling, when the compiler is called with the
`-finstrument-functions` option.
Place the attribute after the declaration, just before the semicolon.
int do_uninteresting_things (void) G_GNUC_NO_INSTRUMENT;
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-no_005finstrument_005ffunction-function-attribute) for more details.
`G_GNUC_MAY_ALIAS`
: Expands to the GNU C `may_alias` type attribute if the compiler is GCC.
Types with this attribute will not be subjected to type-based alias
analysis, but are assumed to alias with any other type, just like `char`.
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-may_005falias-type-attribute) for details.
Since: 2.14
`G_GNUC_FUNCTION`
: Expands to `""` on all modern compilers, and to `__FUNCTION__` on GCC version 2.x. Don't use it.
Deprecated: 2.16: Use `G_STRFUNC()` instead
`G_GNUC_PRETTY_FUNCTION`
: Expands to `""` on all modern compilers, and to `__PRETTY_FUNCTION__` on GCC version 2.x. Don't use it.
Deprecated: 2.16: Use `G_STRFUNC()` instead
`G_GNUC_CHECK_VERSION(major, minor)`
: Expands to a check for a compiler with `__GNUC__` defined and a version
greater than or equal to the major and minor numbers provided. For example,
the following would only match on compilers such as GCC 4.8 or newer.
#if G_GNUC_CHECK_VERSION(4, 8)
// ...
#endif
Since: 2.42
`G_GNUC_BEGIN_IGNORE_DEPRECATIONS`
: Tells GCC (if it is a new enough version) to temporarily stop emitting
warnings when functions marked with `G_GNUC_DEPRECATED` or
`G_GNUC_DEPRECATED_FOR` are called. This is useful for when you have
one deprecated function calling another one, or when you still have
regression tests for deprecated functions.
Use `G_GNUC_END_IGNORE_DEPRECATIONS` to resume warning again. (If you
are not compiling with `-Wdeprecated-declarations` then neither macro
has any effect.)
This macro can be used either inside or outside of a function body,
but must appear on a line by itself.
static void
test_deprecated_function (void)
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_cmpint (my_mistake (), ==, 42);
G_GNUC_END_IGNORE_DEPRECATIONS
}
Both this macro and the corresponding `G_GNUC_END_IGNORE_DEPRECATIONS`
are considered statements, so they should not be used around branching
or loop conditions; for instance, this use is invalid:
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
if (check == some_deprecated_function ())
G_GNUC_END_IGNORE_DEPRECATIONS
{
do_something ();
}
and you should move the deprecated section outside the condition
// Solution A
some_data_t *res;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
res = some_deprecated_function ();
G_GNUC_END_IGNORE_DEPRECATIONS
if (check == res)
{
do_something ();
}
// Solution B
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
if (check == some_deprecated_function ())
{
do_something ();
}
G_GNUC_END_IGNORE_DEPRECATIONS
Since: 2.32
`G_GNUC_END_IGNORE_DEPRECATIONS`
: Undoes the effect of `G_GNUC_BEGIN_IGNORE_DEPRECATIONS`, telling
GCC to resume outputting warnings again (assuming those warnings
had been enabled to begin with).
This macro can be used either inside or outside of a function body,
but must appear on a line by itself.
Since: 2.32
`G_C_STD_VERSION`
: The C standard version the code is compiling against, it's normally
defined with the same value of `__STDC_VERSION__` for C standard
compatible compilers, while it uses the lowest standard version
in pure MSVC, given that in such compiler the definition depends on
a compilation flag.
This is granted to be undefined when compiling with a C++ compiler.
See also: `G_C_STD_CHECK_VERSION` and `G_CXX_STD_VERSION`
Since: 2.76
`G_C_STD_CHECK_VERSION(version)`
: Macro to check if the current compiler supports a specified version
of the C standard. Such value must be numeric and can be provided both
in the short form for the well-known versions (e.g. `90`, `99`...) or in
the complete form otherwise (e.g. `199000L`, `199901L`, `205503L`...).
When a C++ compiler is used, the macro is defined and evaluates to false.
This value is compared against `G_C_STD_VERSION`.
#if G_C_STD_CHECK_VERSION(17)
// ...
#endif
See also: `G_CXX_STD_CHECK_VERSION`
Since: 2.76
`G_CXX_STD_VERSION`
: The C++ standard version the code is compiling against, it's defined
with the same value of `__cplusplus` for C++ standard compatible
compilers, while it uses `_MSVC_LANG` in MSVC, given that the
standard definition depends on a compilation flag in such compiler.
This is granted to be undefined when not compiling with a C++ compiler.
See also: `G_CXX_STD_CHECK_VERSION` and `G_C_STD_VERSION`
Since: 2.76
`G_CXX_STD_CHECK_VERSION(version)`
: Macro to check if the current compiler supports a specified @version
of the C++ standard. Such value must be numeric and can be provided both
in the short form for the well-known versions (e.g. `11`, `17`...) or in
the complete form otherwise (e.g. `201103L`, `201703L`, `205503L`...).
When a C compiler is used, the macro evaluates to false.
This value is compared against `G_CXX_STD_VERSION`.
#if G_CXX_STD_CHECK_VERSION(20)
// ...
#endif
See also: `G_C_STD_CHECK_VERSION`
Since: 2.76
`G_LIKELY(expr)`
: Hints the compiler that the expression is likely to evaluate to
a true value. The compiler may use this information for optimizations.
if (G_LIKELY (random () != 1))
g_print ("not one");
Since: 2.2
`G_UNLIKELY(expr)`
: Hints the compiler that the expression is unlikely to evaluate to
a true value. The compiler may use this information for optimizations.
if (G_UNLIKELY (random () == 1))
g_print ("a random one");
Since: 2.2
`G_ALIGNOF(type)`
: Evaluates to the minimal alignment required by the platform ABI for values
of the given type. The address of a variable or struct member of the given
type must always be a multiple of this alignment. For example, most
platforms require int variables to be aligned at a 4-byte boundary, so
`G_ALIGNOF (int)` is 4 on most platforms.
Note this is not necessarily the same as the value returned by GCCs
`__alignof__` operator, which returns the preferred alignment for a type.
The preferred alignment may be a stricter alignment than the minimal
alignment.
Since: 2.60
`G_SIZEOF_MEMBER(struct_type, member_name)`
: Evaluates to the size in bytes of `member_name` in the struct definition
without having a declared instance of `struct_type`.
Since: 2.64
`G_NORETURN`
: Expands to the GNU C or MSVC `noreturn` function attribute depending on
the compiler. It is used for declaring functions which never return.
Enables optimization of the function, and avoids possible compiler warnings.
Note that `G_NORETURN` supersedes the previous `G_GNUC_NORETURN` macro, which
will eventually be deprecated. `G_NORETURN` supports more platforms.
Place the attribute before the function declaration as follows:
G_NORETURN void g_abort (void);
Since: 2.68
`G_NORETURN_FUNCPTR`
: Expands to the GNU C or MSVC `noreturn` function attribute depending on
the compiler. It is used for declaring function pointers which never return.
Enables optimization of the function, and avoids possible compiler warnings.
Place the attribute before the function declaration as follows:
G_NORETURN_FUNCPTR void (*funcptr) (void);
Note that if the function is not a function pointer, you can simply use
the `G_NORETURN` macro as follows:
G_NORETURN void g_abort (void);
Since: 2.68
`G_ALWAYS_INLINE`
: Expands to the GNU C `always_inline` or MSVC `__forceinline` function
attribute depending on the compiler. It is used for declaring functions
as always inlined, ignoring the compiler optimization levels.
The attribute may be placed before the declaration or definition,
right before the `static` keyword.
G_ALWAYS_INLINE
static int
do_inline_this (void)
{
// ...
}
See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-always_005finline-function-attribute)
and the [MSVC documentation](https://docs.microsoft.com/en-us/visualstudio/misc/inline-inline-forceinline)
for more details.
Since: 2.74
`G_NO_INLINE`
: Expands to the GNU C or MSVC `noinline` function attribute
depending on the compiler. It is used for declaring functions
preventing from being considered for inlining.
Note that `G_NO_INLINE` supersedes the previous `G_GNUC_NO_INLINE`
macro, which will eventually be deprecated. `G_NO_INLINE` supports
more platforms.
The attribute may be placed before the declaration or definition,
right before the `static` keyword.
G_NO_INLINE
static int
do_not_inline_this (void)
{
// ...
}
Since: 2.74
`G_STRLOC`
: Expands to a string identifying the current code position.
`G_STRFUNC`
: Expands to a string identifying the current function. Since: 2.4
`G_GNUC_INTERNAL`
: This attribute can be used for marking library functions as being used
internally to the library only, which may allow the compiler to handle
function calls more efficiently. Note that static functions do not need
to be marked as internal in this way. See the GNU C documentation for
details.
When using a compiler that supports the GNU C hidden visibility attribute,
this macro expands to `__attribute__((visibility("hidden")))`.
When using the Sun Studio compiler, it expands to `__hidden`.
Note that for portability, the attribute should be placed before the
function declaration. While GCC allows the macro after the declaration,
Sun Studio does not.
G_GNUC_INTERNAL
void _g_log_fallback_handler (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer unused_data);
Since: 2.6
`G_HAVE_GNUC_VISIBILITY`
: Defined to 1 if GCC-style visibility handling is supported.
## Deprecation
`G_DEPRECATED`
: This macro is similar to `G_GNUC_DEPRECATED`, and can be used to mark
functions declarations as deprecated. Unlike `G_GNUC_DEPRECATED`, it is
meant to be portable across different compilers and must be placed
before the function declaration.
G_DEPRECATED
int my_mistake (void);
Since: 2.32
`G_DEPRECATED_FOR(f)`
: This macro is similar to `G_GNUC_DEPRECATED_FOR`, and can be used to mark
functions declarations as deprecated. Unlike `G_GNUC_DEPRECATED_FOR`, it
is meant to be portable across different compilers and must be placed
before the function declaration.
G_DEPRECATED_FOR(my_replacement)
int my_mistake (void);
Since: 2.32
`G_UNAVAILABLE(major, minor)`
: This macro can be used to mark a function declaration as unavailable.
It must be placed before the function declaration. Use of a function
that has been annotated with this macros will produce a compiler warning.
Since: 2.32
`GLIB_DISABLE_DEPRECATION_WARNINGS`
: A macro that should be defined before including the `glib.h` header.
If it is defined, no compiler warnings will be produced for uses
of deprecated GLib APIs.

View File

@ -0,0 +1,107 @@
Title: The Main Event Loop
# The Main Event Loop
The main event loop manages all the available sources of events for GLib and
GTK applications. These events can come from any number of different types
of sources such as file descriptors (plain files, pipes or sockets) and
timeouts. New types of event sources can also be added using
`g_source_attach()`.
To allow multiple independent sets of sources to be handled in different
threads, each source is associated with a `GMainContext`. A `GMainContext`
can only be running in a single thread, but sources can be added to it and
removed from it from other threads. All functions which operate on a
`GMainContext` or a built-in `GSource` are thread-safe.
Each event source is assigned a priority. The default priority,
`G_PRIORITY_DEFAULT`, is 0. Values less than 0 denote higher priorities.
Values greater than 0 denote lower priorities. Events from high priority
sources are always processed before events from lower priority sources.
Idle functions can also be added, and assigned a priority. These will be run
whenever no events with a higher priority are ready to be processed.
The `GMainLoop` data type represents a main event loop. A GMainLoop is
created with `g_main_loop_new()`. After adding the initial event sources,
`g_main_loop_run()` is called. This continuously checks for new events from
each of the event sources and dispatches them. Finally, the processing of an
event from one of the sources leads to a call to `g_main_loop_quit()` to
exit the main loop, and `g_main_loop_run()` returns.
It is possible to create new instances of `GMainLoop` recursively. This is
often used in GTK applications when showing modal dialog boxes. Note that
event sources are associated with a particular `GMainContext`, and will be
checked and dispatched for all main loops associated with that GMainContext.
Libraries may contain wrappers of some of these functions, e.g.
`gtk_main()`, `gtk_main_quit()` and `gtk_events_pending()`.
## Creating new source types
One of the unusual features of the `GMainLoop` functionality is that new
types of event source can be created and used in addition to the builtin
type of event source. A new event source type is used for handling GDK
events. A new source type is created by "deriving" from the `GSource`
structure. The derived type of source is represented by a structure that has
the `GSource` structure as a first element, and other elements specific to
the new source type. To create an instance of the new source type, call
`g_source_new()` passing in the size of the derived structure and a table of
functions. These `GSourceFuncs` determine the behavior of the new source
type.
New source types basically interact with the main context in two ways. Their
prepare function in `GSourceFuncs` can set a timeout to determine the
maximum amount of time that the main loop will sleep before checking the
source again. In addition, or as well, the source can add file descriptors
to the set that the main context checks using `g_source_add_poll()`.
## Customizing the main loop iteration
Single iterations of a `GMainContext` can be run with
`g_main_context_iteration()`. In some cases, more detailed control of
exactly how the details of the main loop work is desired, for instance, when
integrating the `GMainLoop` with an external main loop. In such cases, you
can call the component functions of `g_main_context_iteration()` directly.
These functions are `g_main_context_prepare()`, `g_main_context_query()`,
`g_main_context_check()` and `g_main_context_dispatch()`.
## State of a Main Context
The operation of these functions can best be seen in terms of a state
diagram, as shown in this image.
![](mainloop-states.gif)
On UNIX, the GLib mainloop is incompatible with `fork()`. Any program using
the mainloop must either `exec()` or `exit()` from the child without
returning to the mainloop.
## Memory management of sources
There are two options for memory management of the user data passed to a
`GSource` to be passed to its callback on invocation. This data is provided
in calls to `g_timeout_add()`, `g_timeout_add_full()`, `g_idle_add()`, etc.
and more generally, using `g_source_set_callback()`. This data is typically
an object which owns the timeout or idle callback, such as a widget or a
network protocol implementation. In many cases, it is an error for the
callback to be invoked after this owning object has been destroyed, as that
results in use of freed memory.
The first, and preferred, option is to store the source ID returned by
functions such as `g_timeout_add()` or `g_source_attach()`, and explicitly
remove that source from the main context using `g_source_remove()` when the
owning object is finalized. This ensures that the callback can only be
invoked while the object is still alive.
The second option is to hold a strong reference to the object in the
callback, and to release it in the callbacks `GDestroyNotify`. This ensures
that the object is kept alive until after the source is finalized, which is
guaranteed to be after it is invoked for the final time. The
`GDestroyNotify` is another callback passed to the full variants of
`GSource` functions (for example, `g_timeout_add_full()`). It is called when
the source is finalized, and is designed for releasing references like this.
One important caveat of this second approach is that it will keep the object
alive indefinitely if the main loop is stopped before the `GSource` is
invoked, which may be undesirable.

View File

@ -0,0 +1,50 @@
Title: Simple XML Subset Parser
SPDX-License-Identifier: LGPL-2.1-or-later
SPDX-FileCopyrightText: 2011, 2014 Matthias Clasen
SPDX-FileCopyrightText: 2012 David King
# Simple XML Subset Parser
The "GMarkup" parser is intended to parse a simple markup format
that's a subset of XML. This is a small, efficient, easy-to-use
parser. It should not be used if you expect to interoperate with
other applications generating full-scale XML, and must not be used if you
expect to parse untrusted input. However, it's very useful for application
data files, config files, etc. where you know your application will be the
only one writing the file.
Full-scale XML parsers should be able to parse the subset used by
GMarkup, so you can easily migrate to full-scale XML at a later
time if the need arises.
GMarkup is not guaranteed to signal an error on all invalid XML;
the parser may accept documents that an XML parser would not.
However, XML documents which are not well-formed (which is a
weaker condition than being valid. See the
[XML specification](http://www.w3.org/TR/REC-xml/)
for definitions of these terms.) are not considered valid GMarkup
documents.
## Simplifications to XML
The simplifications compared to full XML include:
- Only UTF-8 encoding is allowed
- No user-defined entities
- Processing instructions, comments and the doctype declaration
are "passed through" but are not interpreted in any way
- No DTD or validation
The markup format does support:
- Elements
- Attributes
- 5 standard entities: `&amp;` `&lt;` `&gt;` `&quot;` `&apos;`
- Character references
- Sections marked as CDATA
## An example parser
Here is an example for a markup parser:
[markup-example.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/glib/tests/markup-example.c)

View File

@ -0,0 +1,58 @@
Title: Memory Slices
# Memory Slices
GSlice was a space-efficient and multi-processing scalable way to allocate
equal sized pieces of memory. Since GLib 2.76, its implementation has been
removed and it calls `g_malloc()` and `g_free()`, because the performance of the
system-default allocators has improved on all platforms since GSlice was
written.
The GSlice APIs have not been deprecated, as they are widely in use and doing
so would be very disruptive for little benefit.
New code should be written using [`func@GLib.new`]/[`func@GLib.malloc`] and
[`func@GLib.free`]. There is no particular benefit in porting existing code away
from `g_slice_new()`/`g_slice_free()` unless its being rewritten anyway.
Here is an example for using the slice allocator:
```c
gchar *mem[10000];
gint i;
// Allocate 10000 blocks.
for (i = 0; i < 10000; i++)
{
mem[i] = g_slice_alloc (50);
// Fill in the memory with some junk.
for (j = 0; j < 50; j++)
mem[i][j] = i * j;
}
// Now free all of the blocks.
for (i = 0; i < 10000; i++)
g_slice_free1 (50, mem[i]);
```
And here is an example for using the using the slice allocator with data
structures:
```c
GRealArray *array;
// Allocate one block, using the g_slice_new() macro.
array = g_slice_new (GRealArray);
// We can now use array just like a normal pointer to a structure.
array->data = NULL;
array->len = 0;
array->alloc = 0;
array->zero_terminated = (zero_terminated ? 1 : 0);
array->clear = (clear ? 1 : 0);
array->elt_size = elt_size;
// We can free the block, so it can be reused.
g_slice_free (GRealArray, array);
```

View File

@ -71,22 +71,15 @@ if get_option('gtk_doc')
'--ignore-headers=' + ' '.join(ignore_headers),
],
content_files : [
'cross.xml',
'running.xml',
'building.xml',
'changes.xml',
'compiling.xml',
'programming.xml',
'resources.xml',
'regex-syntax.xml',
'glib-gettextize.xml',
'gtester.xml',
'gtester-report.xml',
'gvariant-varargs.xml',
'gvariant-text.xml',
],
expand_content_files : [
'compiling.xml',
],
html_assets : [
'file-name-encodings.png',
@ -100,7 +93,7 @@ if get_option('gtk_doc')
'--html-dir=' + docpath,
],
install: true,
check: true)
check: false)
endif
if get_option('man')
@ -149,3 +142,43 @@ if get_option('gtk_doc')
)
endif
endif
# gi-docgen version
expand_content_files = [
'building.md',
'character-set.md',
'compiling.md',
'cross-compiling.md',
'error-reporting.md',
'gvariant-format-strings.md',
'gvariant-text-format.md',
'i18n.md',
'logging.md',
'main-loop.md',
'memory-slices.md',
'reference-counting.md',
'running.md',
'testing.md',
'threads.md',
'markup.md',
'goption.md',
]
glib_gir = meson.current_source_dir() / 'GLib-2.0.gir'
glib_toml = configure_file(input: 'glib.toml.in', output: 'glib.toml', configuration: toml_conf)
custom_target('glib-docs',
input: [ glib_toml, glib_gir ],
output: 'glib',
command: [
gidocgen,
'generate',
gidocgen_common_args,
'--config=@INPUT0@',
'--output-dir=@OUTPUT@',
'--content-dir=@0@'.format(meson.current_source_dir()),
'@INPUT1@',
],
build_by_default: true,
depend_files: expand_content_files,
)

View File

@ -0,0 +1,164 @@
Title: Reference Counting
## Reference counting types
Reference counting is a garbage collection mechanism that is based on
assigning a counter to a data type, or any memory area; the counter is
increased whenever a new reference to that data type is acquired, and
decreased whenever the reference is released. Once the last reference is
released, the resources associated to that data type are freed.
GLib uses reference counting in many of its data types, and provides the
`grefcount` and `gatomicrefcount` types to implement safe and atomic
reference counting semantics in new data types.
It is important to note that `grefcount` and `gatomicrefcount` should be
considered completely opaque types; you should always use the provided API
to increase and decrease the counters, and you should never check their
content directly, or compare their content with other values.
## Reference counted data
A "reference counted box", or "RcBox", is an opaque wrapper data type that
is guaranteed to be as big as the size of a given data type, and which
augments the given data type with reference counting semantics for its
memory management.
RcBox is useful if you have a plain old data type, like a structure
typically placed on the stack, and you wish to provide additional API to use
it on the heap; or if you want to implement a new type to be passed around
by reference without necessarily implementing copy/free semantics or your
own reference counting.
The typical use is:
```c
typedef struct {
char *name;
char *address;
char *city;
char *state;
int age;
} Person;
Person *
person_new (void)
{
return g_rc_box_new0 (Person);
}
```
Every time you wish to acquire a reference on the memory, you should call
`g_rc_box_acquire()`; similarly, when you wish to release a reference you
should call `g_rc_box_release()`:
```c
// Add a Person to the Database; the Database acquires ownership
// of the Person instance
void
add_person_to_database (Database *db, Person *p)
{
db->persons = g_list_prepend (db->persons, g_rc_box_acquire (p));
}
// Removes a Person from the Database; the reference acquired by
// add_person_to_database() is released here
void
remove_person_from_database (Database *db, Person *p)
{
db->persons = g_list_remove (db->persons, p);
g_rc_box_release (p);
}
```
If you have additional memory allocated inside the structure, you can use
`g_rc_box_release_full()`, which takes a function pointer, which will be
called if the reference released was the last:
```c
void
person_clear (Person *p)
{
g_free (p->name);
g_free (p->address);
g_free (p->city);
g_free (p->state);
}
void
remove_person_from_database (Database *db, Person *p)
{
db->persons = g_list_remove (db->persons, p);
g_rc_box_release_full (p, (GDestroyNotify) person_clear);
}
```
If you wish to transfer the ownership of a reference counted data
type without increasing the reference count, you can use `g_steal_pointer()`:
```c
Person *p = g_rc_box_new (Person);
// fill_person_details() is defined elsewhere
fill_person_details (p);
// add_person_to_database_no_ref() is defined elsewhere; it adds
// a Person to the Database without taking a reference
add_person_to_database_no_ref (db, g_steal_pointer (&p));
```
## Thread safety
The reference counting operations on data allocated using
`g_rc_box_alloc()`, `g_rc_box_new()`, and `g_rc_box_dup()` are not thread
safe; it is your code's responsibility to ensure that references are
acquired are released on the same thread.
If you need thread safe reference counting, you should use the
`g_atomic_rc_*` API:
| Operation | Atomic equivalent |
|---------------------------|----------------------------------|
| `g_rc_box_alloc()` | `g_atomic_rc_box_alloc()` |
| `g_rc_box_new()` | `g_atomic_rc_box_new()` |
| `g_rc_box_dup()` | `g_atomic_rc_box_dup()` |
| `g_rc_box_acquire()` | `g_atomic_rc_box_acquire()` |
| `g_rc_box_release()` | `g_atomic_rc_box_release()` |
| `g_rc_box_release_full()` | `g_atomic_rc_box_release_full()` |
The reference counting operations on data allocated using
`g_atomic_rc_box_alloc()`, `g_atomic_rc_box_new()`, and
`g_atomic_rc_box_dup()` are guaranteed to be atomic, and thus can be safely
be performed by different threads. It is important to note that only the
reference acquisition and release are atomic; changes to the content of the
data are your responsibility.
It is a programmer error to mix the atomic and non-atomic reference counting
operations.
## Automatic pointer clean up
If you want to add `g_autoptr()` support to your plain old data type through
reference counting, you can use the `G_DEFINE_AUTOPTR_CLEANUP_FUNC()` and
`g_rc_box_release()`:
```c
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, g_rc_box_release)
```
If you need to clear the contents of the data, you will need to use an
ancillary function that calls `g_rc_box_release_full()`:
```c
static void
my_data_struct_release (MyDataStruct *data)
{
// my_data_struct_clear() is defined elsewhere
g_rc_box_release_full (data, (GDestroyNotify) my_data_struct_clear);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, my_data_struct_release)
```
The `g_rc_box*` and `g_atomic_rc_box*` APIs were introduced in GLib 2.58.

View File

@ -0,0 +1,189 @@
Title: Running GLib Applications
# Running GLib Applications
## Environment variables
The runtime behaviour of GLib applications can be influenced by a number of
environment variables.
Standard variables
: GLib reads standard environment variables like `LANG`, `PATH`, `HOME`,
`TMPDIR`, `TZ` and `LOGNAME`.
XDG directories
: GLib consults the environment variables `XDG_DATA_HOME`,
`XDG_DATA_DIRS`, `XDG_CONFIG_HOME`, `XDG_CONFIG_DIRS`, `XDG_CACHE_HOME` and
`XDG_RUNTIME_DIR` for the various XDG directories. For more information, see
the [XDG basedir specification](https://specifications.freedesktop.org/basedir-spec/latest/).
`G_FILENAME_ENCODING`
: This environment variable can be set to a comma-separated list of character
set names. GLib assumes that filenames are encoded in the first character
set from that list rather than in UTF-8. The special token "@locale" can be
used to specify the character set for the current locale.
`G_BROKEN_FILENAMES`
: If this environment variable is set, GLib assumes that filenames are in the
locale encoding rather than in UTF-8. `G_FILENAME_ENCODING` takes priority
over `G_BROKEN_FILENAMES`.
`G_MESSAGES_PREFIXED`
: A list of log levels for which messages should be prefixed by the program
name and PID of the application. The default is to prefix everything except
`G_LOG_LEVEL_MESSAGE` and `G_LOG_LEVEL_INFO`. The possible values are error,
warning, critical, message, info and debug. You can also use the special
values all and help. This environment variable only affects the default log
handler, `g_log_default_handler()`.
`G_MESSAGES_DEBUG`
: A space-separated list of log domains for which informational and debug
messages should be printed. By default, these messages are not printed. You
can also use the special value all. This environment variable only affects
the default log handler, `g_log_default_handler()`.
`G_DEBUG`
: This environment variable can be set to a list of debug options, which cause
GLib to print out different types of debugging information.
- `fatal-warnings`: Causes GLib to abort the program at the first call to
`g_warning()` or `g_critical()`. Use of this flag is not recommended
except when debugging.
- `fatal-criticals`: Causes GLib to abort the program at the first call
to `g_critical()`. This flag can be useful during debugging and
testing.
- `gc-friendly`: Newly allocated memory that isn't directly initialized,
as well as memory being freed will be reset to 0. The point here is to
allow memory checkers and similar programs that use Boehm GC alike
algorithms to produce more accurate results.
- `resident-modules`: All modules loaded by GModule will be made
resident. This can be useful for tracking memory leaks in modules which
are later unloaded; but it can also hide bugs where code is accessed
after the module would have normally been unloaded.
- `bind-now-modules`: All modules loaded by GModule will bind their
symbols at load time, even when the code uses `G_MODULE_BIND_LAZY`.
The special value `all` can be used to turn on all debug options. The special
value `help` can be used to print all available options.
`G_SLICE`
: This environment variable allowed reconfiguration of the GSlice memory
allocator. Since GLib 2.76, GSlice uses the system `malloc()` implementation
internally, so this variable is ignored.
`G_RANDOM_VERSION`
: If this environment variable is set to '2.0', the outdated pseudo-random
number seeding and generation algorithms from GLib 2.0 are used instead of
the newer, better ones. You should only set this variable if you have
sequences of numbers that were generated with Glib 2.0 that you need to
reproduce exactly.
`LIBCHARSET_ALIAS_DIR`
: Allows to specify a nonstandard location for the `charset.aliases` file
that is used by the character set conversion routines. The default
location is the `libdir` specified at compilation time.
`TZDIR`
: Allows to specify a nonstandard location for the timezone data files that
are used by the `GDateTime` API. The default location is under
`/usr/share/zoneinfo`. For more information, also look at the `tzset` manual
page.
`G_ENABLE_DIAGNOSTIC`
: If set to a non-zero value, this environment variable enables diagnostic
messages, like deprecation messages for GObject properties and signals.
`G_DEBUGGER`
: When running on Windows, if set to a non-empty string, GLib will try to
interpret the contents of this environment variable as a command line to a
debugger, and run it if the process crashes. The debugger command line
should contain `%p` and `%e` substitution tokens, which GLib will replace
with the process ID of the crashing process and a handle to an event that
the debugger should signal to let GLib know that the debugger successfully
attached to the process. If `%e` is absent, or if the debugger is not able
to signal events, GLib will resume execution after 60 seconds. If `%p` is
absent, the debugger won't know which process to attach to, and GLib will
also resume execution after 60 seconds. Additionally, even if `G_DEBUGGER`
is not set, GLib would still try to print basic exception information (code
and address) into `stderr`. By default the debugger gets a new console
allocated for it. Set the `G_DEBUGGER_OLD_CONSOLE` environment variable to
any non-empty string to make the debugger inherit the console of the
crashing process. Normally this is only used by the GLib testsuite. The
exception handler is written with the aim of making it as simple as
possible, to minimize the risk of it invoking buggy functions or running
buggy code, which would result in exceptions being raised recursively.
Because of that it lacks most of the amenities that one would expect of
GLib. Namely, it does not support Unicode, so it is highly advisable to
only use ASCII characters in `G_DEBUGGER`. See also `G_VEH_CATCH`.
`G_VEH_CATCH`
: Catching some exceptions can break the program, since Windows will
sometimes use exceptions for execution flow control and other purposes
other than signalling a crash. The `G_VEH_CATCH` environment variable
augments Vectored Exception Handling on Windows (see `G_DEBUGGER`),
allowing GLib to catch more exceptions. Set this variable to a
comma-separated list of hexadecimal exception codes that should
additionally be caught. By default GLib will only catch Access Violation,
Stack Overflow and Illegal Instruction exceptions.
## Locale
A number of interfaces in GLib depend on the current locale in which an
application is running. Therefore, most GLib-using applications should call
`setlocale (LC_ALL, "")` to set up the current locale.
On Windows, in a C program there are several locale concepts that not
necessarily are synchronized. On one hand, there is the system default ANSI
code-page, which determines what encoding is used for file names handled by
the C library's functions and the Win32 API. (We are talking about the
"narrow" functions here that take character pointers, not the "wide" ones.)
On the other hand, there is the C library's current locale. The character
set (code-page) used by that is not necessarily the same as the system
default ANSI code-page. Strings in this character set are returned by
functions like `strftime()`.
## Debugging with GDB
GLib ships with a set of Python macros for the GDB debugger. These includes
pretty printers for lists, hashtables and GObject types. It also has a
backtrace filter that makes backtraces with signal emissions easier to read.
To use this you need a version of GDB that supports Python scripting;
anything from 7.0 should be fine. You then need to install GLib in the same
prefix as GDB so that the Python GDB autoloaded files get installed in the
right place for GDB to pick up.
General pretty printing should just happen without having to do anything
special. To get the signal emission filtered backtrace you must use the
"new-backtrace" command instead of the standard one.
There is also a new command called gforeach that can be used to apply a
command on each item in a list. E.g. you can do
`gforeach i in some_list_variable: print *(GtkWidget *)l`
Which would print the contents of each widget in a list of widgets.
## SystemTap
SystemTap is a dynamic whole-system analysis toolkit. GLib ships with a file
`libglib-2.0.so.*.stp` which defines a set of probe points, which you can hook
into with custom SystemTap scripts. See the files `libglib-2.0.so.*.stp`,
`libgobject-2.0.so.*.stp` and `libgio-2.0.so.*.stp` which are in your shared
SystemTap scripts directory.
## Memory statistics
`g_mem_profile()` will output a summary `g_malloc()` memory usage, if memory
profiling has been enabled by calling:
```
g_mem_set_vtable (glib_mem_profiler_table);
```
upon startup.
If GLib has been configured with full debugging support, then
`g_slice_debug_tree_statistics()` can be called in a debugger to output details
about the memory usage of the slice allocator.

View File

@ -1,371 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<refentry id="glib-running">
<refmeta>
<refentrytitle>Running GLib Applications</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>GLib Library</refmiscinfo>
</refmeta>
<refnamediv>
<refname>Running GLib Applications</refname>
<refpurpose>
How to run and debug your GLib application
</refpurpose>
</refnamediv>
<refsect1>
<title>Running and debugging GLib Applications</title>
<refsect2>
<title>Environment variables</title>
<para>
The runtime behaviour of GLib applications can be influenced by a
number of environment variables.
</para>
<formalpara>
<title>Standard variables</title>
<para>
GLib reads standard environment variables like <envar>LANG</envar>,
<envar>PATH</envar>, <envar>HOME</envar>, <envar>TMPDIR</envar>,
<envar>TZ</envar> and <envar>LOGNAME</envar>.
</para>
</formalpara>
<formalpara>
<title>XDG directories</title>
<para>
GLib consults the environment variables <envar>XDG_DATA_HOME</envar>,
<envar>XDG_DATA_DIRS</envar>, <envar>XDG_CONFIG_HOME</envar>,
<envar>XDG_CONFIG_DIRS</envar>, <envar>XDG_CACHE_HOME</envar> and
<envar>XDG_RUNTIME_DIR</envar> for the various XDG directories.
For more information, see the <ulink url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html">XDG basedir spec</ulink>.
</para>
</formalpara>
<formalpara id="G_FILENAME_ENCODING">
<title><envar>G_FILENAME_ENCODING</envar></title>
<para>
This environment variable can be set to a comma-separated list of character
set names. GLib assumes that filenames are encoded in the first character
set from that list rather than in UTF-8. The special token "@locale" can be
used to specify the character set for the current locale.
</para>
</formalpara>
<formalpara id="G_BROKEN_FILENAMES">
<title><envar>G_BROKEN_FILENAMES</envar></title>
<para>
If this environment variable is set, GLib assumes that filenames are in
the locale encoding rather than in UTF-8. G_FILENAME_ENCODING takes
priority over G_BROKEN_FILENAMES.
</para>
</formalpara>
<formalpara id="G_MESSAGES_PREFIXED">
<title><envar>G_MESSAGES_PREFIXED</envar></title>
<para>
A list of log levels for which messages should be prefixed by the
program name and PID of the application. The default is to prefix
everything except <literal>G_LOG_LEVEL_MESSAGE</literal> and
<literal>G_LOG_LEVEL_INFO</literal>.
The possible values are
<literal>error</literal>,
<literal>warning</literal>,
<literal>critical</literal>,
<literal>message</literal>,
<literal>info</literal> and
<literal>debug</literal>.
You can also use the special values
<literal>all</literal> and
<literal>help</literal>.
</para>
<para>
This environment variable only affects the default log handler,
g_log_default_handler().
</para>
</formalpara>
<formalpara id="G_MESSAGES_DEBUG">
<title><envar>G_MESSAGES_DEBUG</envar></title>
<para>
A space-separated list of log domains for which informational
and debug messages should be printed. By default, these
messages are not printed.
</para>
<para>
You can also use the special value <literal>all</literal>.
</para>
<para>
This environment variable only affects the default log handler,
g_log_default_handler().
</para>
</formalpara>
<formalpara id="G-DEBUG:CAPS">
<title><envar>G_DEBUG</envar></title>
<para>
This environment variable can be set to a list of debug options,
which cause GLib to print out different types of debugging information.
<variablelist>
<varlistentry>
<term>fatal-warnings</term>
<listitem><para>Causes GLib to abort the program at the first call
to g_warning() or g_critical(). Use of this flag is not
recommended except when debugging.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>fatal-criticals</term>
<listitem><para>Causes GLib to abort the program at the first call
to g_critical(). This flag can be useful during debugging and
testing.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>gc-friendly</term>
<listitem><para>Newly allocated memory that isn't directly initialized,
as well as memory being freed will be reset to 0. The point here is
to allow memory checkers and similar programs that use Boehm GC alike
algorithms to produce more accurate results.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>resident-modules</term>
<listitem><para>All modules loaded by GModule will be made resident.
This can be useful for tracking memory leaks in modules which are
later unloaded; but it can also hide bugs where code is accessed
after the module would have normally been unloaded.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>bind-now-modules</term>
<listitem><para>All modules loaded by GModule will bind their symbols
at load time, even when the code uses %G_MODULE_BIND_LAZY.</para>
</listitem>
</varlistentry>
</variablelist>
The special value <literal>all</literal> can be used to turn on all debug options.
The special value <literal>help</literal> can be used to print all available options.
</para>
</formalpara>
<formalpara id="G_SLICE">
<title><envar>G_SLICE</envar></title>
<para>
This environment variable allowed reconfiguration of the GSlice
memory allocator. Since GLib 2.76, GSlice uses the system
<literal>malloc()</literal> implementation internally, so this variable is
ignored.
</para>
</formalpara>
<formalpara id="G_RANDOM_VERSION">
<title><envar>G_RANDOM_VERSION</envar></title>
<para>
If this environment variable is set to '2.0', the outdated
pseudo-random number seeding and generation algorithms from
GLib 2.0 are used instead of the newer, better ones. You should
only set this variable if you have sequences of numbers that were
generated with Glib 2.0 that you need to reproduce exactly.
</para>
</formalpara>
<formalpara id="LIBCHARSET_ALIAS_DIR">
<title><envar>LIBCHARSET_ALIAS_DIR</envar></title>
<para>
Allows to specify a nonstandard location for the
<filename>charset.aliases</filename> file that is used by the
character set conversion routines. The default location is the
<replaceable>libdir</replaceable> specified at compilation time.
</para>
</formalpara>
<formalpara id="TZDIR">
<title><envar>TZDIR</envar></title>
<para>
Allows to specify a nonstandard location for the timezone data files
that are used by the #GDateTime API. The default location is under
<filename>/usr/share/zoneinfo</filename>. For more information,
also look at the <command>tzset</command> manual page.
</para>
</formalpara>
<formalpara id="G_ENABLE_DIAGNOSTIC">
<title><envar>G_ENABLE_DIAGNOSTIC</envar></title>
<para>
If set to a non-zero value, this environment variable enables
diagnostic messages, like deprecation messages for GObject properties
and signals.
</para>
</formalpara>
<formalpara id="G_DEBUGGER">
<title><envar>G_DEBUGGER</envar></title>
<para>
When running on Windows, if set to a non-empty string, GLib will
try to interpret the contents of this environment variable as
a command line to a debugger, and run it if the process crashes.
The debugger command line should contain <literal>%p</literal> and <literal>%e</literal> substitution
tokens, which GLib will replace with the process ID of the crashing
process and a handle to an event that the debugger should signal
to let GLib know that the debugger successfully attached to the
process. If <literal>%e</literal> is absent, or if the debugger is not able to
signal events, GLib will resume execution after 60 seconds.
If <literal>%p</literal> is absent, the debugger won't know which process to attach to,
and GLib will also resume execution after 60 seconds.
</para>
<para>
Additionally, even if <envar>G_DEBUGGER</envar> is not set, GLib would still
try to print basic exception information (code and address) into
stderr.
</para>
<para>
By default the debugger gets a new console allocated for it.
Set the <envar>G_DEBUGGER_OLD_CONSOLE</envar> environment variable to any
non-empty string to make the debugger inherit the console of
the crashing process. Normally this is only used by the GLib
testsuite.
</para>
<para>
The exception handler is written with the aim of making it as
simple as possible, to minimize the risk of it invoking
buggy functions or running buggy code, which would result
in exceptions being raised recursively. Because of that
it lacks most of the amenities that one would expect of GLib.
Namely, it does not support Unicode, so it is highly advisable
to only use ASCII characters in <envar>G_DEBUGGER</envar>.
</para>
<para>
See also <link linkend="G_VEH_CATCH"><envar>G_VEH_CATCH</envar></link>.
</para>
</formalpara>
<formalpara id="G_VEH_CATCH">
<title><envar>G_VEH_CATCH</envar></title>
<para>
Catching some exceptions can break the program, since Windows
will sometimes use exceptions for execution flow control and
other purposes other than signalling a crash.
</para>
<para>
The <envar>G_VEH_CATCH</envar> environment variable augments
<ulink url="https://docs.microsoft.com/en-us/windows/desktop/debug/vectored-exception-handling">Vectored Exception Handling</ulink>
on Windows (see <link linkend="G_DEBUGGER"><envar>G_DEBUGGER</envar></link>), allowing GLib to catch more
exceptions. Set this variable to a comma-separated list of
hexadecimal exception codes that should additionally be caught.
</para>
<para>
By default GLib will only catch Access Violation, Stack Overflow and
Illegal Instruction <ulink url="https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_exception_record">exceptions</ulink>.
</para>
</formalpara>
</refsect2>
<refsect2 id="setlocale">
<title>Locale</title>
<para>
A number of interfaces in GLib depend on the current locale in which
an application is running. Therefore, most GLib-using applications should
call <function>setlocale (LC_ALL, "")</function> to set up the current
locale.
</para>
<para>
On Windows, in a C program there are several locale concepts
that not necessarily are synchronized. On one hand, there is the
system default ANSI code-page, which determines what encoding is used
for file names handled by the C library's functions and the Win32
API. (We are talking about the "narrow" functions here that take
character pointers, not the "wide" ones.)
</para>
<para>
On the other hand, there is the C library's current locale. The
character set (code-page) used by that is not necessarily the same as
the system default ANSI code-page. Strings in this character set are
returned by functions like <function>strftime()</function>.
</para>
</refsect2>
<para>
GLib ships with a set of Python macros for the GDB debugger. These includes pretty
printers for lists, hashtables and GObject types. It also has a backtrace filter
that makes backtraces with signal emissions easier to read.
</para>
<para>
To use this you need a version of GDB that supports Python scripting; anything
from 7.0 should be fine. You then need to install GLib in the same prefix as
GDB so that the Python GDB autoloaded files get installed in the right place
for GDB to pick up.
</para>
<para>
General pretty printing should just happen without having to do anything special.
To get the signal emission filtered backtrace you must use the "new-backtrace" command
instead of the standard one.
</para>
<para>
There is also a new command called gforeach that can be used to apply a command
on each item in a list. E.g. you can do
<programlisting>
gforeach i in some_list_variable: print *(GtkWidget *)l
</programlisting>
Which would print the contents of each widget in a list of widgets.
</para>
<refsect2>
<title>SystemTap</title>
<para>
<ulink url="http://sourceware.org/systemtap/">SystemTap</ulink> is a dynamic whole-system
analysis toolkit. GLib ships with a file <filename>libglib-2.0.so.*.stp</filename> which defines a
set of probe points, which you can hook into with custom SystemTap scripts.
See the files <filename>libglib-2.0.so.*.stp</filename>, <filename>libgobject-2.0.so.*.stp</filename>
and <filename>libgio-2.0.so.*.stp</filename> which
are in your shared SystemTap scripts directory.
</para>
</refsect2>
<refsect2>
<title>Memory statistics</title>
<para>
g_mem_profile() will output a summary g_malloc() memory usage, if memory
profiling has been enabled by calling
<literal>g_mem_set_vtable (glib_mem_profiler_table)</literal> upon startup.
</para>
<para>
If GLib has been configured with <option>--enable-debug=yes</option>,
then g_slice_debug_tree_statistics() can be called in a debugger to
output details about the memory usage of the slice allocator.
</para>
</refsect2>
</refsect1>
</refentry>

View File

@ -0,0 +1,183 @@
Title: Testing Framework
# Testing Framework
GLib provides a framework for writing and maintaining unit tests in parallel
to the code they are testing. The API is designed according to established
concepts found in the other test frameworks (JUnit, NUnit, RUnit), which in
turn is based on smalltalk unit testing concepts.
- Test case: Tests (test methods) are grouped together with their fixture
into test cases.
- Fixture: A test fixture consists of fixture data and setup and teardown
methods to establish the environment for the test functions. We use fresh
fixtures, i.e. fixtures are newly set up and torn down around each test
invocation to avoid dependencies between tests.
- Test suite: Test cases can be grouped into test suites, to allow subsets
of the available tests to be run. Test suites can be grouped into other
test suites as well.
The API is designed to handle creation and registration of test suites and
test cases implicitly. A simple call like:
```c
g_test_add_func ("/misc/assertions", test_assertions);
```
creates a test suite called "misc" with a single test case named
"assertions", which consists of running the `test_assertions` function.
In addition to the traditional `g_assert_true()`, the test framework
provides an extended set of assertions for comparisons:
`g_assert_cmpfloat()`, `g_assert_cmpfloat_with_epsilon()`,
`g_assert_cmpint()`, `g_assert_cmpuint()`, `g_assert_cmphex()`,
`g_assert_cmpstr()`, `g_assert_cmpmem()` and `g_assert_cmpvariant()`. The
advantage of these variants over plain `g_assert_true()` is that the
assertion messages can be more elaborate, and include the values of the
compared entities.
Note that `g_assert()` should **not** be used in unit tests, since it is a
no-op when compiling with `G_DISABLE_ASSERT`. Use `g_assert()` in production
code, and `g_assert_true()` in unit tests.
A full example of creating a test suite with two tests using fixtures:
```c
#include <glib.h>
#include <locale.h>
typedef struct {
MyObject *obj;
OtherObject *helper;
} MyObjectFixture;
static void
my_object_fixture_set_up (MyObjectFixture *fixture,
gconstpointer user_data)
{
fixture->obj = my_object_new ();
my_object_set_prop1 (fixture->obj, "some-value");
my_object_do_some_complex_setup (fixture->obj, user_data);
fixture->helper = other_object_new ();
}
static void
my_object_fixture_tear_down (MyObjectFixture *fixture,
gconstpointer user_data)
{
g_clear_object (&fixture->helper);
g_clear_object (&fixture->obj);
}
static void
test_my_object_test1 (MyObjectFixture *fixture,
gconstpointer user_data)
{
g_assert_cmpstr (my_object_get_property (fixture->obj), ==, "initial-value");
}
static void
test_my_object_test2 (MyObjectFixture *fixture,
gconstpointer user_data)
{
my_object_do_some_work_using_helper (fixture->obj, fixture->helper);
g_assert_cmpstr (my_object_get_property (fixture->obj), ==, "updated-value");
}
int
main (int argc, char *argv[])
{
setlocale (LC_ALL, "");
g_test_init (&argc, &argv, NULL);
// Define the tests.
g_test_add ("/my-object/test1", MyObjectFixture, "some-user-data",
my_object_fixture_set_up, test_my_object_test1,
my_object_fixture_tear_down);
g_test_add ("/my-object/test2", MyObjectFixture, "some-user-data",
my_object_fixture_set_up, test_my_object_test2,
my_object_fixture_tear_down);
return g_test_run ();
}
```
### Integrating GTest in your project
#### Using Meson
If you are using the Meson build system, you will typically use the provided
`test()` primitive to call the test binaries, e.g.:
```
test(
'foo',
executable('foo', 'foo.c', dependencies: deps),
env: [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
],
protocol: 'tap',
)
test(
'bar',
executable('bar', 'bar.c', dependencies: deps),
env: [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
],
protocol: 'tap',
)
```
#### Using Autotools
If you are using Autotools, you're strongly encouraged to use the Automake
TAP harness; GLib provides template files for easily integrating with it:
- [`glib-tap.mk`](https://gitlab.gnome.org/GNOME/glib/blob/glib-2-58/glib-tap.mk)
- [`tap-test`](https://gitlab.gnome.org/GNOME/glib/blob/glib-2-58/tap-test)
- [`tap-driver.sh`](https://gitlab.gnome.org/GNOME/glib/blob/glib-2-58/tap-driver.sh)
You can copy these files in your own project's root directory, and then set
up your `Makefile.am` file to reference them, for instance:
```
include $(top_srcdir)/glib-tap.mk
# test binaries
test_programs = \
foo \
bar
# data distributed in the tarball
dist_test_data = \
foo.data.txt \
bar.data.txt
# data not distributed in the tarball
test_data = \
blah.data.txt
```
Make sure to distribute the TAP files, using something like the following in
your top-level `Makefile.am`:
```
EXTRA_DIST += \
tap-driver.sh \
tap-test
```
`glib-tap.mk` will be distributed implicitly due to being included in a
`Makefile.am`. All three files should be added to version control.
If you don't have access to the Autotools TAP harness, you can use the
gtester and gtester-report tools, and use the
[`glib.mk`](https://gitlab.gnome.org/GNOME/glib/blob/glib-2-58/glib.mk)
Automake template provided by GLib. Note, however, that since GLib 2.62,
gtester and gtester-report have been deprecated in favour of using TAP. The
`--tap` argument to tests is enabled by default as of GLib 2.62.

View File

@ -0,0 +1,91 @@
Title: Threads
SPDX-License-Identifier: LGPL-2.1-or-later
SPDX-FileCopyrightText: 2010 Allison Lortie
SPDX-FileCopyrightText: 2011, 2012, 2014 Matthias Clasen
SPDX-FileCopyrightText: 2014 Collabora, Ltd.
# Threads
Threads act almost like processes, but unlike processes all threads of one
process share the same memory. This is good, as it provides easy
communication between the involved threads via this shared memory, and it is
bad, because strange things (so called "Heisenbugs") might happen if the
program is not carefully designed. In particular, due to the concurrent
nature of threads, no assumptions on the order of execution of code running
in different threads can be made, unless order is explicitly forced by the
programmer through synchronization primitives.
The aim of the thread-related functions in GLib is to provide a portable
means for writing multi-threaded software. There are primitives for mutexes
to protect the access to portions of memory (`GMutex`, `GRecMutex` and
`GRWLock`). There is a facility to use individual bits for locks
(`g_bit_lock()`). There are primitives for condition variables to allow
synchronization of threads (`GCond`). There are primitives for
thread-private data - data that every thread has a private instance of
(`GPrivate`). There are facilities for one-time initialization (`GOnce`,
`g_once_init_enter_pointer()`, `g_once_init_enter()`). Finally, there are
primitives to create and manage threads (`GThread`).
The GLib threading system used to be initialized with `g_thread_init()`.
This is no longer necessary. Since version 2.32, the GLib threading system
is automatically initialized at the start of your program, and all
thread-creation functions and synchronization primitives are available right
away.
Note that it is not safe to assume that your program has no threads even if
you don't call `g_thread_new()` yourself. GLib and GIO can and will create
threads for their own purposes in some cases, such as when using
`g_unix_signal_source_new()` or when using GDBus.
Originally, UNIX did not have threads, and therefore some traditional UNIX
APIs are problematic in threaded programs. Some notable examples are
- C library functions that return data in statically allocated buffers, such
as `strtok()` or `strerror()`. For many of these, there are thread-safe
variants with a `_r` suffix, or you can look at corresponding GLib APIs
(`like g_strsplit()` or `g_strerror()`).
- The functions `setenv()` and `unsetenv()` manipulate the process
environment in a not thread-safe way, and may interfere with `getenv()`
calls in other threads. Note that `getenv()` calls may be hidden behind
other APIs. For example, GNU `gettext()` calls `getenv()` under the
covers. In general, it is best to treat the environment as readonly. If
you absolutely have to modify the environment, do it early in `main()`,
when no other threads are around yet.
- The `setlocale()` function changes the locale for the entire process,
affecting all threads. Temporary changes to the locale are often made to
change the behavior of string scanning or formatting functions like
`scanf()` or `printf()`. GLib offers a number of string APIs (like
`g_ascii_formatd()` or `g_ascii_strtod()`) that can often be used as an
alternative. Or you can use the `uselocale()` function to change the
locale only for the current thread.
- The `fork()` function only takes the calling thread into the child's copy
of the process image. If other threads were executing in critical sections
they could have left mutexes locked which could easily cause deadlocks in
the new child. For this reason, you should call `exit()` or `exec()` as
soon as possible in the child and only make signal-safe library calls
before that.
- The `daemon()` function uses `fork()` in a way contrary to what is
described above. It should not be used with GLib programs.
GLib itself is internally completely thread-safe (all global data is
automatically locked), but individual data structure instances are not
automatically locked for performance reasons. For example, you must
coordinate accesses to the same `GHashTable` from multiple threads. The two
notable exceptions from this rule are `GMainLoop` and `GAsyncQueue`, which are
thread-safe and need no further application-level locking to be accessed
from multiple threads. Most refcounting functions such as `g_object_ref()` are
also thread-safe.
A common use for GThreads is to move a long-running blocking operation out
of the main thread and into a worker thread. For GLib functions, such as
single GIO operations, this is not necessary, and complicates the code.
Instead, the `…_async()` version of the function should be used from the main
thread, eliminating the need for locking and synchronisation between
multiple threads. If an operation does need to be moved to a worker thread,
consider using `g_task_run_in_thread()`, or a `GThreadPool`. `GThreadPool` is
often a better choice than `GThread`, as it handles thread reuse and task
queueing; `GTask` uses this internally.
However, if multiple blocking operations need to be performed in sequence,
and it is not possible to use `GTask` for them, moving them to a worker thread
can clarify the code.

View File

@ -0,0 +1,9 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
// SPDX-FileCopyrightText: 2023 Matthias Clasen
var baseURLs = [
[ 'GLib', 'https://docs.gtk.org/glib/' ],
[ 'GModule', 'https://docs.gtk.org/gmodule/' ],
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
[ 'Gio', 'https://docs.gtk.org/gio/' ],
[ 'Gtk', 'https://docs.gtk.org/gtk4/' ],
];

View File

@ -0,0 +1,535 @@
<?xml version="1.0"?>
<!-- This file was automatically generated from C sources - DO NOT EDIT!
To affect the contents of this file, edit the original C definitions,
and/or use gtk-doc annotations. -->
<repository version="1.2"
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0"
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
<include name="GLib" version="2.0"/>
<package name="gmodule-2.0"/>
<c:include name="gmodule.h"/>
<namespace name="GModule"
version="2.0"
shared-library="libgmodule-2.0.so.0"
c:identifier-prefixes="G"
c:symbol-prefixes="g">
<record name="Module" c:type="GModule" disguised="1" opaque="1">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="5">The #GModule struct is an opaque data structure to represent a
[dynamically-loaded module][glib-Dynamic-Loading-of-Modules].
It should only be accessed via the following functions.</doc>
<source-position filename="gmodule.h" line="70"/>
<method name="close" c:identifier="g_module_close">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="207">Closes a module.</doc>
<source-position filename="gmodule.h" line="110"/>
<return-value transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="213">%TRUE on success</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<instance-parameter name="module" transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="209">a #GModule to close</doc>
<type name="Module" c:type="GModule*"/>
</instance-parameter>
</parameters>
</method>
<method name="make_resident" c:identifier="g_module_make_resident">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="226">Ensures that a module will never be unloaded.
Any future g_module_close() calls on the module will be ignored.</doc>
<source-position filename="gmodule.h" line="114"/>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<instance-parameter name="module" transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="228">a #GModule to make permanently resident</doc>
<type name="Module" c:type="GModule*"/>
</instance-parameter>
</parameters>
</method>
<method name="name" c:identifier="g_module_name">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="235">Returns the filename that the module was opened with.
If @module refers to the application itself, "main" is returned.</doc>
<source-position filename="gmodule.h" line="128"/>
<return-value transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="243">the filename of the module</doc>
<type name="utf8" c:type="const gchar*"/>
</return-value>
<parameters>
<instance-parameter name="module" transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="237">a #GModule</doc>
<type name="Module" c:type="GModule*"/>
</instance-parameter>
</parameters>
</method>
<method name="symbol" c:identifier="g_module_symbol">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="299">Gets a symbol pointer from a module, such as one exported
by %G_MODULE_EXPORT. Note that a valid symbol can be %NULL.</doc>
<source-position filename="gmodule.h" line="122"/>
<return-value transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="308">%TRUE on success</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<instance-parameter name="module" transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="301">a #GModule</doc>
<type name="Module" c:type="GModule*"/>
</instance-parameter>
<parameter name="symbol_name" transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="302">the name of the symbol to find</doc>
<type name="utf8" c:type="const gchar*"/>
</parameter>
<parameter name="symbol"
direction="out"
caller-allocates="0"
transfer-ownership="full"
nullable="1">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="303">returns the pointer to the symbol value</doc>
<type name="gpointer" c:type="gpointer*"/>
</parameter>
</parameters>
</method>
<function name="build_path"
c:identifier="g_module_build_path"
deprecated="1"
deprecated-version="2.76">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="179">A portable way to build the filename of a module. The platform-specific
prefix and suffix are added to the filename, if needed, and the result
is added to the directory, using the correct separator character.
The directory should specify the directory where the module can be found.
It can be %NULL or an empty string to indicate that the module is in a
standard platform-specific directory, though this is not recommended
since the wrong module may be found.
For example, calling g_module_build_path() on a Linux system with a
@directory of `/lib` and a @module_name of "mylibrary" will return
`/lib/libmylibrary.so`. On a Windows system, using `\Windows` as the
directory it will return `\Windows\mylibrary.dll`.</doc>
<doc-deprecated xml:space="preserve">Use g_module_open() instead with @module_name as the
basename of the file_name argument. See %G_MODULE_SUFFIX for why.</doc-deprecated>
<source-position filename="gmodule.h" line="142"/>
<return-value transfer-ownership="full">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="200">the complete path of the module, including the standard library
prefix and suffix. This should be freed when no longer needed</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="directory"
transfer-ownership="none"
nullable="1"
allow-none="1">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="181">the directory where the module is. This can be
%NULL or the empty string to indicate that the standard platform-specific
directories will be used, though that is not recommended</doc>
<type name="utf8" c:type="const gchar*"/>
</parameter>
<parameter name="module_name" transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="184">the name of the module</doc>
<type name="utf8" c:type="const gchar*"/>
</parameter>
</parameters>
</function>
<function name="error" c:identifier="g_module_error">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="217">Gets a string describing the last module error.</doc>
<source-position filename="gmodule.h" line="118"/>
<return-value transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="222">a string describing the last module error</doc>
<type name="utf8" c:type="const gchar*"/>
</return-value>
</function>
<function name="error_quark" c:identifier="g_module_error_quark">
<return-value transfer-ownership="none">
<type name="GLib.Quark" c:type="GQuark"/>
</return-value>
</function>
<function name="open" c:identifier="g_module_open" introspectable="0">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="247">A thin wrapper function around g_module_open_full()</doc>
<source-position filename="gmodule.h" line="100"/>
<return-value>
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="256">a #GModule on success, or %NULL on failure</doc>
<type name="Module" c:type="GModule*"/>
</return-value>
<parameters>
<parameter name="file_name"
transfer-ownership="none"
nullable="1"
allow-none="1">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="249">the name or path to the file containing the module,
or %NULL to obtain a #GModule representing the main program itself</doc>
<type name="utf8" c:type="const gchar*"/>
</parameter>
<parameter name="flags" transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="251">the flags used for opening the module. This can be the
logical OR of any of the #GModuleFlags.</doc>
<type name="ModuleFlags" c:type="GModuleFlags"/>
</parameter>
</parameters>
</function>
<function name="open_full"
c:identifier="g_module_open_full"
version="2.70"
introspectable="0"
throws="1">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="260">Opens a module. If the module has already been opened, its reference count
is incremented. If not, the module is searched in the following order:
1. If @file_name exists as a regular file, it is used as-is; else
2. If @file_name doesn't have the correct suffix and/or prefix for the
platform, then possible suffixes and prefixes will be added to the
basename till a file is found and whatever is found will be used; else
3. If @file_name doesn't have the ".la"-suffix, ".la" is appended. Either
way, if a matching .la file exists (and is a libtool archive) the
libtool archive is parsed to find the actual file name, and that is
used.
At the end of all this, we would have a file path that we can access on
disk, and it is opened as a module. If not, @file_name is opened as
a module verbatim in the hopes that the system implementation will somehow
be able to access it.</doc>
<source-position filename="gmodule.h" line="104"/>
<return-value>
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="285">a #GModule on success, or %NULL on failure</doc>
<type name="Module" c:type="GModule*"/>
</return-value>
<parameters>
<parameter name="file_name"
transfer-ownership="none"
nullable="1"
allow-none="1">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="262">the name or path to the file containing the module,
or %NULL to obtain a #GModule representing the main program itself</doc>
<type name="utf8" c:type="const gchar*"/>
</parameter>
<parameter name="flags" transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="264">the flags used for opening the module. This can be the
logical OR of any of the #GModuleFlags</doc>
<type name="ModuleFlags" c:type="GModuleFlags"/>
</parameter>
</parameters>
</function>
<function name="supported" c:identifier="g_module_supported">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="290">Checks if modules are supported on the current platform.</doc>
<source-position filename="gmodule.h" line="96"/>
<return-value transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="295">%TRUE if modules are supported</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
</function>
</record>
<callback name="ModuleCheckInit" c:type="GModuleCheckInit">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="14">Specifies the type of the module initialization function.
If a module contains a function named g_module_check_init() it is called
automatically when the module is loaded. It is passed the #GModule structure
and should return %NULL on success or a string describing the initialization
error.</doc>
<source-position filename="gmodule.h" line="71"/>
<return-value transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="24">%NULL on success, or a string describing the initialization error</doc>
<type name="utf8" c:type="const gchar*"/>
</return-value>
<parameters>
<parameter name="module" transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="16">the #GModule corresponding to the module which has just been loaded</doc>
<type name="Module" c:type="GModule*"/>
</parameter>
</parameters>
</callback>
<enumeration name="ModuleError"
version="2.70"
c:type="GModuleError"
glib:error-domain="g-module-error-quark">
<doc xml:space="preserve"
filename="gmodule.h"
line="78">Errors returned by g_module_open_full().</doc>
<source-position filename="gmodule.h" line="91"/>
<member name="failed" value="0" c:identifier="G_MODULE_ERROR_FAILED">
<doc xml:space="preserve"
filename="gmodule.h"
line="80">there was an error loading or opening a module file</doc>
</member>
<member name="check_failed"
value="1"
c:identifier="G_MODULE_ERROR_CHECK_FAILED">
<doc xml:space="preserve"
filename="gmodule.h"
line="81">a module returned an error from its `g_module_check_init()` function</doc>
</member>
</enumeration>
<bitfield name="ModuleFlags" c:type="GModuleFlags">
<doc xml:space="preserve"
filename="gmodule.h"
line="49">Flags passed to g_module_open().
Note that these flags are not supported on all platforms.</doc>
<source-position filename="gmodule.h" line="68"/>
<member name="lazy" value="1" c:identifier="G_MODULE_BIND_LAZY">
<doc xml:space="preserve"
filename="gmodule.h"
line="51">specifies that symbols are only resolved when
needed. The default action is to bind all symbols when the module
is loaded.</doc>
</member>
<member name="local" value="2" c:identifier="G_MODULE_BIND_LOCAL">
<doc xml:space="preserve"
filename="gmodule.h"
line="54">specifies that symbols in the module should
not be added to the global name space. The default action on most
platforms is to place symbols in the module in the global name space,
which may cause conflicts with existing symbols.</doc>
</member>
<member name="mask" value="3" c:identifier="G_MODULE_BIND_MASK">
<doc xml:space="preserve"
filename="gmodule.h"
line="58">mask for all flags.</doc>
</member>
</bitfield>
<callback name="ModuleUnload" c:type="GModuleUnload">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="28">Specifies the type of the module function called when it is unloaded.
If a module contains a function named g_module_unload() it is called
automatically when the module is unloaded.
It is passed the #GModule structure.</doc>
<source-position filename="gmodule.h" line="72"/>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="module" transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="30">the #GModule about to be unloaded</doc>
<type name="Module" c:type="GModule*"/>
</parameter>
</parameters>
</callback>
<function name="module_build_path"
c:identifier="g_module_build_path"
moved-to="Module.build_path"
deprecated="1"
deprecated-version="2.76">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="179">A portable way to build the filename of a module. The platform-specific
prefix and suffix are added to the filename, if needed, and the result
is added to the directory, using the correct separator character.
The directory should specify the directory where the module can be found.
It can be %NULL or an empty string to indicate that the module is in a
standard platform-specific directory, though this is not recommended
since the wrong module may be found.
For example, calling g_module_build_path() on a Linux system with a
@directory of `/lib` and a @module_name of "mylibrary" will return
`/lib/libmylibrary.so`. On a Windows system, using `\Windows` as the
directory it will return `\Windows\mylibrary.dll`.</doc>
<doc-deprecated xml:space="preserve">Use g_module_open() instead with @module_name as the
basename of the file_name argument. See %G_MODULE_SUFFIX for why.</doc-deprecated>
<source-position filename="gmodule.h" line="142"/>
<return-value transfer-ownership="full">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="200">the complete path of the module, including the standard library
prefix and suffix. This should be freed when no longer needed</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="directory"
transfer-ownership="none"
nullable="1"
allow-none="1">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="181">the directory where the module is. This can be
%NULL or the empty string to indicate that the standard platform-specific
directories will be used, though that is not recommended</doc>
<type name="utf8" c:type="const gchar*"/>
</parameter>
<parameter name="module_name" transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="184">the name of the module</doc>
<type name="utf8" c:type="const gchar*"/>
</parameter>
</parameters>
</function>
<function name="module_error"
c:identifier="g_module_error"
moved-to="Module.error">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="217">Gets a string describing the last module error.</doc>
<source-position filename="gmodule.h" line="118"/>
<return-value transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="222">a string describing the last module error</doc>
<type name="utf8" c:type="const gchar*"/>
</return-value>
</function>
<function name="module_error_quark"
c:identifier="g_module_error_quark"
moved-to="Module.error_quark">
<return-value transfer-ownership="none">
<type name="GLib.Quark" c:type="GQuark"/>
</return-value>
</function>
<function name="module_supported"
c:identifier="g_module_supported"
moved-to="Module.supported">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="290">Checks if modules are supported on the current platform.</doc>
<source-position filename="gmodule.h" line="96"/>
<return-value transfer-ownership="none">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="295">%TRUE if modules are supported</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
</function>
<docsection name="modules">
<doc xml:space="preserve"
filename="gmodule-2.0.c"
line="99">These functions provide a portable way to dynamically load object files
(commonly known as 'plug-ins'). The current implementation supports all
systems that provide an implementation of dlopen() (e.g. Linux/Sun), as
well as Windows platforms via DLLs.
A program which wants to use these functions must be linked to the
libraries output by the command `pkg-config --libs gmodule-2.0`.
To use them you must first determine whether dynamic loading
is supported on the platform by calling g_module_supported().
If it is, you can open a module with g_module_open(),
find the module's symbols (e.g. function names) with g_module_symbol(),
and later close the module with g_module_close().
g_module_name() will return the file name of a currently opened module.
If any of the above functions fail, the error status can be found with
g_module_error().
The #GModule implementation features reference counting for opened modules,
and supports hook functions within a module which are called when the
module is loaded and unloaded (see #GModuleCheckInit and #GModuleUnload).
If your module introduces static data to common subsystems in the running
program, e.g. through calling
`g_quark_from_static_string ("my-module-stuff")`,
it must ensure that it is never unloaded, by calling g_module_make_resident().
Example: Calling a function defined in a GModule
|[&lt;!-- language="C" --&gt;
// the function signature for 'say_hello'
typedef void (* SayHelloFunc) (const char *message);
gboolean
just_say_hello (const char *filename, GError **error)
{
SayHelloFunc say_hello;
GModule *module;
module = g_module_open (filename, G_MODULE_BIND_LAZY);
if (!module)
{
g_set_error (error, FOO_ERROR, FOO_ERROR_BLAH,
"%s", g_module_error ());
return FALSE;
}
if (!g_module_symbol (module, "say_hello", (gpointer *)&amp;say_hello))
{
g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN,
"%s: %s", filename, g_module_error ());
if (!g_module_close (module))
g_warning ("%s: %s", filename, g_module_error ());
return FALSE;
}
if (say_hello == NULL)
{
g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN,
"symbol say_hello is NULL");
if (!g_module_close (module))
g_warning ("%s: %s", filename, g_module_error ());
return FALSE;
}
// call our function in the module
say_hello ("Hello world!");
if (!g_module_close (module))
g_warning ("%s: %s", filename, g_module_error ());
return TRUE;
}
]|</doc>
</docsection>
</namespace>
</repository>

View File

@ -0,0 +1,49 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# Copyright 2023 Matthias Clasen
# Copyright 2023 Philip Withnall
[library]
name = "GModule"
version = "@VERSION@"
browse_url = "https://gitlab.gnome.org/GNOME/glib/"
repository_url = "https://gitlab.gnome.org/GNOME/glib.git"
website_url = "https://www.gtk.org"
docs_url = "https://docs.gtk.org/gmodule/"
authors = "GLib Development Team"
license = "LGPL-2.1-or-later"
description = "Portable API for dynamically loading modules"
dependencies = [ "GLib-2.0", "GObject-2.0", "Gio-2.0" ]
devhelp = true
search_index = true
[dependencies."GLib-2.0"]
name = "GLib"
description = "The base utility library"
docs_url = "https://docs.gtk.org/glib/"
[dependencies."GObject-2.0"]
name = "GObject"
description = "The base type system library"
docs_url = "https://docs.gtk.org/gobject/"
[dependencies."Gio-2.0"]
name = "GIO"
description = "GObject Interfaces and Objects, Networking, IPC, and I/O"
docs_url = "https://docs.gtk.org/gio/"
[theme]
name = "basic"
show_index_summary = true
show_class_hierarchy = true
[source-location]
base_url = "https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/"
[extra]
urlmap_file = "urlmap.js"
# The same order will be used when generating the index
content_files = [
"modules.md",
]
content_images = [
]

View File

@ -0,0 +1,23 @@
expand_content_files = [
'modules.md',
]
gmodule_gir = meson.current_source_dir() / 'GModule-2.0.gir'
gmodule_toml = configure_file(input: 'gmodule.toml.in', output: 'gmodule.toml', configuration: toml_conf)
custom_target('gmodule-docs',
input: [ gmodule_toml, gmodule_gir ],
output: 'gmodule',
command: [
gidocgen,
'generate',
gidocgen_common_args,
'--config=@INPUT0@',
'--output-dir=@OUTPUT@',
'--content-dir=@0@'.format(meson.current_source_dir()),
'--add-include-path=@0@'.format(meson.current_source_dir() / '../glib'),
'@INPUT1@',
],
build_by_default: true,
depend_files: expand_content_files,
)

View File

@ -0,0 +1,92 @@
Title: Dynamic Loading of Modules
## Dynamic Loading of Modules
These functions provide a portable way to dynamically load object files
(commonly known as 'plug-ins'). The current implementation supports all
systems that provide an implementation of `dlopen()` (e.g. Linux/Sun), as
well as Windows platforms via DLLs.
A program which wants to use these functions must be linked to the libraries
output by the command:
pkg-config --libs gmodule-2.0
To use them you must first determine whether dynamic loading is supported on
the platform by calling [`func@GModule.Module.supported`]. If it is, you can
open a module with [`func@GModule.Module.open`], find the module's symbols
(e.g. function names) with [`method@GModule.Module.symbol`], and later close
the module with [`method@GModule.Module.close`].
[`method@GModule.Module.name`] will return the file name of a currently
opened module.
If any of the above functions fail, the error status can be found with
[`func@GModule.Module.error`].
The `GModule` implementation features reference counting for opened modules,
and supports hook functions within a module which are called when the module
is loaded and unloaded (see [callback@GModule.ModuleCheckInit] and
[callback@GModule.ModuleUnload]).
If your module introduces static data to common subsystems in the running
program, e.g. through calling API like:
```c
static GQuark my_module_quark =
g_quark_from_static_string ("my-module-stuff");
```
it must ensure that it is never unloaded, by calling
[`method@GModule.Module.make_resident`].
### Calling a function defined in a GModule
```c
// the function signature for 'say_hello'
typedef void (* SayHelloFunc) (const char *message);
gboolean
just_say_hello (const char *filename, GError **error)
{
SayHelloFunc say_hello;
GModule *module;
module = g_module_open (filename, G_MODULE_BIND_LAZY);
if (module == NULL)
{
g_set_error (error, FOO_ERROR, FOO_ERROR_BLAH,
"%s", g_module_error ());
return FALSE;
}
if (!g_module_symbol (module, "say_hello", (gpointer *)&say_hello))
{
g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN,
"%s: %s", filename, g_module_error ());
if (!g_module_close (module))
g_warning ("%s: %s", filename, g_module_error ());
return FALSE;
}
if (say_hello == NULL)
{
g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN,
"symbol say_hello is NULL");
if (!g_module_close (module))
g_warning ("%s: %s", filename, g_module_error ());
return FALSE;
}
// call our function in the module
say_hello ("Hello world!");
if (!g_module_close (module))
g_warning ("%s: %s", filename, g_module_error ());
return TRUE;
}
```

View File

@ -0,0 +1,9 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
// SPDX-FileCopyrightText: 2023 Matthias Clasen
var baseURLs = [
[ 'GLib', 'https://docs.gtk.org/glib/' ],
[ 'GModule', 'https://docs.gtk.org/gmodule/' ],
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
[ 'Gio', 'https://docs.gtk.org/gio/' ],
[ 'Gtk', 'https://docs.gtk.org/gtk4/' ],
];

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,113 @@
Title: Boxed types
# Boxed types
A "boxed type" is a generic wrapper mechanism for arbitrary C structures.
The only thing the type system needs to know about the structures is how to
copy them (a [`callback@GObject.BoxedCopyFunc`]) and how to free them (a
[`callback@GObject.BoxedFreeFunc`])—beyond that they are treated as opaque
chunks of memory.
Boxed types are useful for simple value-holder structures like rectangles or
points. They can also be used for wrapping structures defined in non-GObject
based libraries. They allow arbitrary structures to be handled in a uniform
way, allowing uniform copying (or referencing) and freeing (or
unreferencing) of them, and uniform representation of the type of the
contained structure. In turn, this allows any type which can be boxed to be
set as the data in a `GValue`, which allows for polymorphic handling of a much
wider range of data types, and hence usage of such types as `GObject` property
values.
All boxed types inherit from the `G_TYPE_BOXED` fundamental type.
It is very important to note that boxed types are **not** deeply
inheritable: you cannot register a boxed type that inherits from another
boxed type. This means you cannot create your own custom, parallel type
hierarchy and map it to GType using boxed types. If you want to have deeply
inheritable types without using GObject, you will need to use
`GTypeInstance`.
## Registering a new boxed type
The recommended way to register a new boxed type is to use the
[`func@GObject.DEFINE_BOXED_TYPE`] macro:
```c
// In the header
#define EXAMPLE_TYPE_RECTANGLE (example_rectangle_get_type())
typedef struct {
double x, y;
double width, height;
} ExampleRectangle;
GType
example_rectangle_get_type (void);
ExampleRectangle *
example_rectangle_copy (ExampleRectangle *r);
void
example_rectangle_free (ExampleRectangle *r);
// In the source
G_DEFINE_BOXED_TYPE (ExampleRectangle, example_rectangle,
example_rectangle_copy,
example_rectangle_free)
```
Just like `G_DEFINE_TYPE` and `G_DEFINE_INTERFACE_TYPE`, the
`G_DEFINE_BOXED_TYPE` macro will provide the definition of the `get_type()`
function, which will call [`func@GObject.boxed_type_register_static`] with
the given type name as well as the `GBoxedCopyFunc` and `GBoxedFreeFunc`
functions.
## Using boxed types
### Object properties
In order to use a boxed type with GObject properties you will need to
register the property using [`func@GObject.param_spec_boxed`], e.g.
```c
obj_props[PROP_BOUNDS] =
g_param_spec_boxed ("bounds", NULL, NULL,
EXAMPLE_TYPE_RECTANGLE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
```
In the `set_property` implementation you can use `g_value_get_boxed()` to
retrieve a pointer to the boxed type:
```c
switch (prop_id)
{
// ...
case PROP_BOUNDS:
example_object_set_bounds (self, g_value_get_boxed (value));
break;
// ...
}
```
Similarly, you can use `g_value_set_boxed()` in the implementation of the
`get_property` virtual function:
```c
switch (prop_id)
{
// ...
case PROP_BOUNDS:
g_value_set_boxed (self, &self->bounds);
break;
// ...
}
```
## Reference counting
Boxed types are designed so that reference counted types can be boxed. Use
the types ref function as the `GBoxedCopyFunc`, and its unref function as
the `GBoxedFreeFunc`. For example, for `GBytes`, the `GBoxedCopyFunc` is
`g_bytes_ref()`, and the GBoxedFreeFunc is `g_bytes_unref()`.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
Title: Enumeration types
# Enumeration types
The GLib type system provides fundamental types for enumeration and flags
types. Enumerations types are collection of identifiers associated with a
numeric value; flags types are like enumerations, but allow their values to
be combined by bitwise or.
A registered enumeration or flags type associates a name and a nickname with
each allowed value, and the methods [`func@GObject.enum_get_value_by_name`],
[`func@GObject.enum_get_value_by_nick`], [`func@GObject.flags_get_value_by_name`] and
[`func@GObject.flags_get_value_by_nick`] can look up values by their name or nickname.
When an enumeration or flags type is registered with the GLib type system,
it can be used as value type for object properties, using
[`func@GObject.param_spec_enum`] or [`func@GObject.param_spec_flags`].
GObject ships with a utility called `glib-mkenums`, that can construct
suitable type registration functions from C enumeration definitions.
Example of how to get a string representation of an enum value:
```c
GEnumClass *enum_class;
GEnumValue *enum_value;
enum_class = g_type_class_ref (EXAMPLE_TYPE_ENUM);
enum_value = g_enum_get_value (enum_class, EXAMPLE_ENUM_FOO);
g_print ("Name: %s\n", enum_value->value_name);
g_type_class_unref (enum_class);
```
Alternatively, you can use [`func@GObject.enum_to_string`].

View File

@ -0,0 +1,128 @@
Title: Floating references
# Floating references
**Note**: Floating references are a C convenience API and should not be used
in modern GObject code. Language bindings in particular find the concept
highly problematic, as floating references are not identifiable through
annotations, and neither are deviations from the floating reference
behavior, like types that inherit from [class@GObject.InitiallyUnowned] and
still return a full reference from [`id@g_object_new`].
[class@GObject.InitiallyUnowned] is derived from [class@GObject.Object]. The
only difference between the two is that the initial reference of a
`GInitiallyUnowned` is flagged as a "floating" reference. This means that it
is not specifically claimed to be "owned" by any code portion. The main
motivation for providing floating references is C convenience. In
particular, it allows code to be written as:
```c
container = create_container ();
container_add_child (container, create_child());
```
If `container_add_child()` calls [`method@GObject.Object.ref_sink`] on the
passed-in child, no reference of the newly created child is leaked. Without
floating references, `container_add_child()` can only acquire a reference
the new child, so to implement this code without reference leaks, it would
have to be written as:
```c
Child *child;
container = create_container ();
child = create_child ();
container_add_child (container, child);
g_object_unref (child);
```
The floating reference can be converted into an ordinary reference by
calling `g_object_ref_sink()`. For already sunken objects (objects that
don't have a floating reference anymore), `g_object_ref_sink()` is
equivalent to [`method@GObject.Object.ref`] and returns a new reference.
Since floating references are useful almost exclusively for C convenience,
language bindings that provide automated reference and memory ownership
maintenance (such as smart pointers or garbage collection) should not expose
floating references in their API. The best practice for handling types that
have initially floating references is to immediately sink those references
after `g_object_new()` returns, by checking if the `GType` inherits from
`GInitiallyUnowned`. For instance:
```c
GObject *res = g_object_new_with_properties (gtype,
n_props,
prop_names,
prop_values);
// or: if (g_type_is_a (gtype, G_TYPE_INITIALLY_UNOWNED))
if (G_IS_INITIALLY_UNOWNED (res))
g_object_ref_sink (res);
return res;
```
Some object implementations may need to save an object's floating state
across certain code portions (an example is `GtkMenu` in GTK3), to achieve
this, the following sequence can be used:
```c
// save floating state
gboolean was_floating = g_object_is_floating (object);
g_object_ref_sink (object);
// protected code portion
...
// restore floating state
if (was_floating)
g_object_force_floating (object);
else
g_object_unref (object); // release previously acquired reference
```
## Replacing floating references with annotations
You should avoid basing your object hierarchy on floating references, as
they are hard to understand even in C, and introduce additional limitations
when consuming a GObject-based API in other languages.
One way to express the ownership transfer between container and child
instances is to use ownership transfer annotations in your documentation and
introspection data. For instance, you can implement this pattern:
```c
container_add_child (container, create_child ());
```
without leaking by having `container_add_child()` defined as:
```c
/**
* container_add_child:
* @self: a container
* @child: (transfer full): the child to add to the container
*
* ...
*/
void
container_add_child (Container *container,
Child *child)
{
container->children = g_list_append (container->children, child);
}
```
The container does not explicitly acquire a reference on the child; instead,
the ownership of the child is transferred to the container. The transfer
annotation will be used by language bindings to ensure that there are no
leaks; and documentation tools will explicitly note that the callee now owns
the value passed by the caller.
## Replacing floating references with weak references
Another option for replacing floating references is to use weak references
in place of strong ones. A container can acquire a weak reference on the
child instance by using [`method@GObject.Object.weak_ref`]. Once the
child instance loses its last strong reference, the container holding a
weak reference is notified, and it can either remove the child from its
internal list, or turn a weak reference into a strong one.

View File

@ -15,58 +15,6 @@
</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>
@ -95,7 +43,6 @@
<xi:include href="gobject-query.xml" />
</reference>
<xi:include href="tut_howto.xml" />
<xi:include href="tut_tools.xml" />
<chapter id="api-index-full">

View File

@ -0,0 +1,61 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# Copyright 2023 Matthias Clasen
# Copyright 2023 Philip Withnall
[library]
name = "GObject"
version = "@VERSION@"
browse_url = "https://gitlab.gnome.org/GNOME/glib/"
repository_url = "https://gitlab.gnome.org/GNOME/glib.git"
website_url = "https://www.gtk.org"
docs_url = "https://docs.gtk.org/gobject/"
authors = "GLib Development Team"
license = "LGPL-2.1-or-later"
description = "The base type system and object class"
devhelp = true
search_index = true
dependencies = ["GLib-2.0"]
[dependencies."GLib-2.0"]
name = "GLib"
description = "The base utility library"
docs_url = "https://docs.gtk.org/glib/"
related = ["GModule-2.0", "Gio-2.0"]
[related."GModule-2.0"]
name = "GModule"
description = "Portable API for dynamically loading modules"
docs_url = "https://docs.gtk.org/gmodule/"
[related."Gio-2.0"]
name = "GIO"
description = "GObject Interfaces and Objects, Networking, IPC, and I/O"
docs_url = "https://docs.gtk.org/gio/"
[theme]
name = "basic"
show_index_summary = true
show_class_hierarchy = true
[extra]
urlmap_file = "urlmap.js"
# The same order will be used when generating the index
content_files = [
"concepts.md",
"tutorial.md",
"floating-refs.md",
"boxed.md",
"enum-types.md",
"gvalue.md",
]
content_images = [
"images/glue.png",
]
# This is the anonymous union inside GValue; we don't need it
# as a type, and including it just generates a dummy union
# definition
[[object]]
name = "_Value__data__union"
hidden = true

View File

@ -0,0 +1,108 @@
Title: Generic value container
# Generic value container
The [`struct@GObject.Value`] structure is basically a variable container
that consists of a type identifier and a specific value of that type. The
type identifier within a `GValue` structure always determines the type of the
associated value.
To create an undefined `GValue` structure, simply create a zero-filled
GValue structure. To initialize the `GValue`, use the
[`method@GObject.Value.init`] function. A `GValue` cannot be used until it
is initialized.
Once you have finished using a `GValue`, you must call
[`method@GObject.Value.unset`] to ensure that all the resources associated
with the `GValue` are freed.
The basic type operations (such as freeing and copying) are determined by
the [`struct@GObject.TypeValueTable`] associated with the type ID stored in
the `GValue`. Other `GValue` operations (such as converting values between
types) are provided by this interface.
The code in the example program below demonstrates `GValue`'s features:
```c
#include <glib-object.h>
static void
int2string (const GValue *src_value,
GValue *dest_value)
{
if (g_value_get_int (src_value) == 42)
g_value_set_static_string (dest_value, "An important number");
else
g_value_set_static_string (dest_value, "What's that?");
}
int
main (int argc,
char *argv[])
{
// GValues must be initialized
GValue a = G_VALUE_INIT;
GValue b = G_VALUE_INIT;
const char *message;
// The GValue starts empty
g_assert (!G_VALUE_HOLDS_STRING (&a));
// Put a string in it
g_value_init (&a, G_TYPE_STRING);
g_assert (G_VALUE_HOLDS_STRING (&a));
g_value_set_static_string (&a, "Hello, world!");
g_printf ("%s\n", g_value_get_string (&a));
// Reset it to its pristine state
g_value_unset (&a);
// It can then be reused for another type
g_value_init (&a, G_TYPE_INT);
g_value_set_int (&a, 42);
// Attempt to transform it into a GValue of type STRING
g_value_init (&b, G_TYPE_STRING);
// An INT is transformable to a STRING
g_assert (g_value_type_transformable (G_TYPE_INT, G_TYPE_STRING));
g_value_transform (&a, &b);
g_printf ("%s\n", g_value_get_string (&b));
// Attempt to transform it again using a custom transform function
g_value_register_transform_func (G_TYPE_INT, G_TYPE_STRING, int2string);
g_value_transform (&a, &b);
g_printf ("%s\n", g_value_get_string (&b));
g_value_unset (&b);
g_value_unset (&a);
return 0;
}
```
For letting a `GValue` own (and memory manage) arbitrary types or pointers,
they need to become a [boxed type](boxed.html). The example below shows how
the pointer `mystruct` of type `MyStruct` is used as a [boxed type](boxed.html).
```c
typedef struct { ... } MyStruct;
G_DEFINE_BOXED_TYPE (MyStruct, my_struct, my_struct_copy, my_struct_free)
// These two lines normally go in a public header. By GObject convention,
// the naming scheme is NAMESPACE_TYPE_NAME:
#define MY_TYPE_STRUCT (my_struct_get_type ())
GType my_struct_get_type (void);
void
foo (void)
{
GValue *value = g_new0 (GValue, 1);
g_value_init (value, MY_TYPE_STRUCT);
g_value_set_boxed (value, mystruct);
// [... your code ....]
g_value_unset (value);
g_free (value);
}
```

View File

@ -38,11 +38,6 @@ if get_option('gtk_doc')
'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 : [
@ -53,7 +48,7 @@ if get_option('gtk_doc')
'--extra-dir=' + join_paths('gobject', '..', 'glib', 'html'),
],
install: true,
check: true,
check: false,
)
endif
@ -68,3 +63,33 @@ if get_option('man')
install_dir: man1_dir)
endforeach
endif
# gi-docgen version
expand_content_files = [
'boxed.md',
'concepts.md',
'enum-types.md',
'floating-refs.md',
'gvalue.md',
'tutorial.md',
]
gobject_gir = meson.current_source_dir() / 'GObject-2.0.gir'
gobject_toml = configure_file(input: 'gobject.toml.in', output: 'gobject.toml', configuration: toml_conf)
custom_target('gobject-docs',
input: [ gobject_toml, gobject_gir ],
output: 'gobject',
command: [
gidocgen,
'generate',
gidocgen_common_args,
'--config=@INPUT0@',
'--output-dir=@OUTPUT@',
'--content-dir=@0@'.format(meson.current_source_dir()),
'--add-include-path=@0@'.format(meson.current_source_dir() / '../glib'),
'@INPUT1@',
],
build_by_default: true,
depend_files: expand_content_files,
)

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
// SPDX-FileCopyrightText: 2023 Matthias Clasen
var baseURLs = [
[ 'GLib', 'https://docs.gtk.org/glib/' ],
[ 'GModule', 'https://docs.gtk.org/gmodule/' ],
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
[ 'Gio', 'https://docs.gtk.org/gio/' ],
[ 'Gtk', 'https://docs.gtk.org/gtk4/' ],
];

View File

@ -53,6 +53,25 @@ if get_option('gtk_doc')
endif
endif
subdir('gio')
subdir('glib')
subdir('gobject')
# gi-docgen version
if get_option('gtk_doc')
gidocgen_dep = dependency('gi-docgen', version: '>= 2023.1',
fallback: ['gi-docgen', 'dummy_dep'],
required: true)
toml_conf = configuration_data()
toml_conf.set('VERSION', meson.project_version())
gidocgen = find_program('gi-docgen', required: true)
gidocgen_common_args = [
'--quiet',
'--no-namespace-dir',
'--fatal-warnings',
]
subdir('glib')
subdir('gmodule')
subdir('gobject')
subdir('gio')
endif

View File

@ -1063,48 +1063,6 @@
/* Type conversion {{{1 */
/**
* SECTION:type_conversion
* @title: Type Conversion Macros
* @short_description: portably storing integers in pointer variables
*
* Many times GLib, GTK, and other libraries allow you to pass "user
* data" to a callback, in the form of a void pointer. From time to time
* you want to pass an integer instead of a pointer. You could allocate
* an integer, with something like:
* |[<!-- language="C" -->
* int *ip = g_new (int, 1);
* *ip = 42;
* ]|
* But this is inconvenient, and it's annoying to have to free the
* memory at some later time.
*
* Pointers are always at least 32 bits in size (on all platforms GLib
* intends to support). Thus you can store at least 32-bit integer values
* in a pointer value. Naively, you might try this, but it's incorrect:
* |[<!-- language="C" -->
* gpointer p;
* int i;
* p = (void*) 42;
* i = (int) p;
* ]|
* Again, that example was not correct, don't copy it.
* The problem is that on some systems you need to do this:
* |[<!-- language="C" -->
* gpointer p;
* int i;
* p = (void*) (long) 42;
* i = (int) (long) p;
* ]|
* The GLib macros GPOINTER_TO_INT(), GINT_TO_POINTER(), etc. take care
* to do the right thing on every platform.
*
* Warning: You may not store pointers in integers. This is not
* portable in any way, shape or form. These macros only allow storing
* integers in pointers, and only preserve 32 bits of the integer; values
* outside the range of a 32-bit integer will be mangled.
*/
/**
* GINT_TO_POINTER:
* @i: integer to stuff into a pointer
@ -1162,41 +1120,6 @@
/* Byte order {{{1 */
/**
* SECTION:byte_order
* @title: Byte Order Macros
* @short_description: a portable way to convert between different byte orders
*
* These macros provide a portable way to determine the host byte order
* and to convert values between different byte orders.
*
* The byte order is the order in which bytes are stored to create larger
* data types such as the #gint and #glong values.
* The host byte order is the byte order used on the current machine.
*
* Some processors store the most significant bytes (i.e. the bytes that
* hold the largest part of the value) first. These are known as big-endian
* processors. Other processors (notably the x86 family) store the most
* significant byte last. These are known as little-endian processors.
*
* Finally, to complicate matters, some other processors store the bytes in
* a rather curious order known as PDP-endian. For a 4-byte word, the 3rd
* most significant byte is stored first, then the 4th, then the 1st and
* finally the 2nd.
*
* Obviously there is a problem when these different processors communicate
* with each other, for example over networks or by using binary file formats.
* This is where these macros come in. They are typically used to convert
* values into a byte order which has been agreed on for use when
* communicating between different processors. The Internet uses what is
* known as 'network byte order' as the standard byte order (which is in
* fact the big-endian byte order).
*
* Note that the byte order conversion macros may evaluate their arguments
* multiple times, thus you should not use them with arguments which have
* side-effects.
*/
/**
* G_BYTE_ORDER:
*
@ -1986,16 +1909,8 @@
*
* Multiplying the base 2 exponent by this number yields the base 10 exponent.
*/
/* Macros {{{1 */
/**
* SECTION:macros
* @title: Standard Macros
* @short_description: commonly-used macros
*
* These macros provide a few commonly-used features.
*/
/* Macros {{{1 */
/**
* G_OS_WIN32:
@ -2201,15 +2116,6 @@
/* Miscellaneous Macros {{{1 */
/**
* SECTION:macros_misc
* @title: Miscellaneous Macros
* @short_description: specialized macros which are not used often
*
* These macros provide more specialized features which are not
* needed so often by application programmers.
*/
/**
* G_STMT_START:
*

View File

@ -35,131 +35,6 @@
#define G_ARC_BOX(p) (GArcBox *) (((char *) (p)) - G_ARC_BOX_SIZE)
/**
* SECTION:arcbox
* @Title: Atomically reference counted data
* @Short_description: Allocated memory with atomic reference counting semantics
*
* An "atomically reference counted box", or "ArcBox", is an opaque wrapper
* data type that is guaranteed to be as big as the size of a given data type,
* and which augments the given data type with thread safe reference counting
* semantics for its memory management.
*
* ArcBox is useful if you have a plain old data type, like a structure
* typically placed on the stack, and you wish to provide additional API
* to use it on the heap; or if you want to implement a new type to be
* passed around by reference without necessarily implementing copy/free
* semantics or your own reference counting.
*
* The typical use is:
*
* |[<!-- language="C" -->
* typedef struct {
* char *name;
* char *address;
* char *city;
* char *state;
* int age;
* } Person;
*
* Person *
* person_new (void)
* {
* return g_atomic_rc_box_new0 (Person);
* }
* ]|
*
* Every time you wish to acquire a reference on the memory, you should
* call g_atomic_rc_box_acquire(); similarly, when you wish to release a reference
* you should call g_atomic_rc_box_release():
*
* |[<!-- language="C" -->
* // Add a Person to the Database; the Database acquires ownership
* // of the Person instance
* void
* add_person_to_database (Database *db, Person *p)
* {
* db->persons = g_list_prepend (db->persons, g_atomic_rc_box_acquire (p));
* }
*
* // Removes a Person from the Database; the reference acquired by
* // add_person_to_database() is released here
* void
* remove_person_from_database (Database *db, Person *p)
* {
* db->persons = g_list_remove (db->persons, p);
* g_atomic_rc_box_release (p);
* }
* ]|
*
* If you have additional memory allocated inside the structure, you can
* use g_atomic_rc_box_release_full(), which takes a function pointer, which
* will be called if the reference released was the last:
*
* |[<!-- language="C" -->
* void
* person_clear (Person *p)
* {
* g_free (p->name);
* g_free (p->address);
* g_free (p->city);
* g_free (p->state);
* }
*
* void
* remove_person_from_database (Database *db, Person *p)
* {
* db->persons = g_list_remove (db->persons, p);
* g_atomic_rc_box_release_full (p, (GDestroyNotify) person_clear);
* }
* ]|
*
* If you wish to transfer the ownership of a reference counted data
* type without increasing the reference count, you can use g_steal_pointer():
*
* |[<!-- language="C" -->
* Person *p = g_atomic_rc_box_new (Person);
*
* fill_person_details (p);
*
* add_person_to_database (db, g_steal_pointer (&p));
* ]|
*
* ## Thread safety
*
* The reference counting operations on data allocated using g_atomic_rc_box_alloc(),
* g_atomic_rc_box_new(), and g_atomic_rc_box_dup() are guaranteed to be atomic, and thus
* can be safely be performed by different threads. It is important to note that
* only the reference acquisition and release are atomic; changes to the content
* of the data are your responsibility.
*
* ## Automatic pointer clean up
*
* If you want to add g_autoptr() support to your plain old data type through
* reference counting, you can use the G_DEFINE_AUTOPTR_CLEANUP_FUNC() and
* g_atomic_rc_box_release():
*
* |[<!-- language="C" -->
* G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, g_atomic_rc_box_release)
* ]|
*
* If you need to clear the contents of the data, you will need to use an
* ancillary function that calls g_rc_box_release_full():
*
* |[<!-- language="C" -->
* static void
* my_data_struct_release (MyDataStruct *data)
* {
* // my_data_struct_clear() is defined elsewhere
* g_atomic_rc_box_release_full (data, (GDestroyNotify) my_data_struct_clear);
* }
*
* G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, my_data_struct_release)
* ]|
*
* Since: 2.58
*/
/**
* g_atomic_rc_box_alloc:
* @block_size: the size of the allocation, must be greater than 0

View File

@ -56,105 +56,6 @@
#include "glibintl.h"
/**
* SECTION:conversions
* @title: Character Set Conversion
* @short_description: convert strings between different character sets
*
* The g_convert() family of function wraps the functionality of iconv().
* In addition to pure character set conversions, GLib has functions to
* deal with the extra complications of encodings for file names.
*
* ## File Name Encodings
*
* Historically, UNIX has not had a defined encoding for file names:
* a file name is valid as long as it does not have path separators
* in it ("/"). However, displaying file names may require conversion:
* from the character set in which they were created, to the character
* set in which the application operates. Consider the Spanish file name
* "Presentación.sxi". If the application which created it uses
* ISO-8859-1 for its encoding,
* |[
* Character: P r e s e n t a c i ó n . s x i
* Hex code: 50 72 65 73 65 6e 74 61 63 69 f3 6e 2e 73 78 69
* ]|
* However, if the application use UTF-8, the actual file name on
* disk would look like this:
* |[
* Character: P r e s e n t a c i ó n . s x i
* Hex code: 50 72 65 73 65 6e 74 61 63 69 c3 b3 6e 2e 73 78 69
* ]|
* GLib uses UTF-8 for its strings, and GUI toolkits like GTK that use
* GLib do the same thing. If you get a file name from the file system,
* for example, from readdir() or from g_dir_read_name(), and you wish
* to display the file name to the user, you will need to convert it
* into UTF-8. The opposite case is when the user types the name of a
* file they wish to save: the toolkit will give you that string in
* UTF-8 encoding, and you will need to convert it to the character
* set used for file names before you can create the file with open()
* or fopen().
*
* By default, GLib assumes that file names on disk are in UTF-8
* encoding. This is a valid assumption for file systems which
* were created relatively recently: most applications use UTF-8
* encoding for their strings, and that is also what they use for
* the file names they create. However, older file systems may
* still contain file names created in "older" encodings, such as
* ISO-8859-1. In this case, for compatibility reasons, you may want
* to instruct GLib to use that particular encoding for file names
* rather than UTF-8. You can do this by specifying the encoding for
* file names in the [`G_FILENAME_ENCODING`][G_FILENAME_ENCODING]
* environment variable. For example, if your installation uses
* ISO-8859-1 for file names, you can put this in your `~/.profile`:
* |[
* export G_FILENAME_ENCODING=ISO-8859-1
* ]|
* GLib provides the functions g_filename_to_utf8() and
* g_filename_from_utf8() to perform the necessary conversions.
* These functions convert file names from the encoding specified
* in `G_FILENAME_ENCODING` to UTF-8 and vice-versa. This
* [diagram][file-name-encodings-diagram] illustrates how
* these functions are used to convert between UTF-8 and the
* encoding for file names in the file system.
*
* ## Conversion between file name encodings # {#file-name-encodings-diagram)
*
* ![](file-name-encodings.png)
*
* ## Checklist for Application Writers
*
* This section is a practical summary of the detailed
* things to do to make sure your applications process file
* name encodings correctly.
*
* 1. If you get a file name from the file system from a function
* such as readdir() or gtk_file_chooser_get_filename(), you do
* not need to do any conversion to pass that file name to
* functions like open(), rename(), or fopen() -- those are "raw"
* file names which the file system understands.
*
* 2. If you need to display a file name, convert it to UTF-8 first
* by using g_filename_to_utf8(). If conversion fails, display a
* string like "Unknown file name". Do not convert this string back
* into the encoding used for file names if you wish to pass it to
* the file system; use the original file name instead.
*
* For example, the document window of a word processor could display
* "Unknown file name" in its title bar but still let the user save
* the file, as it would keep the raw file name internally. This
* can happen if the user has not set the `G_FILENAME_ENCODING`
* environment variable even though they have files whose names are
* not encoded in UTF-8.
*
* 3. If your user interface lets the user type a file name for saving
* or renaming, convert it to the encoding used for file names in
* the file system by using g_filename_from_utf8(). Pass the converted
* file name to functions like fopen(). If conversion fails, ask the
* user to enter a different file name. This can happen if the user
* types Japanese characters when `G_FILENAME_ENCODING` is set to
* `ISO-8859-1`, for example.
*/
/* We try to terminate strings in unknown charsets with this many zero bytes
* to ensure that multibyte strings really are nul-terminated when we return
* them from g_convert() and friends.

View File

@ -24,481 +24,6 @@
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
/**
* SECTION:error_reporting
* @Title: Error Reporting
* @Short_description: a system for reporting errors
*
* GLib provides a standard method of reporting errors from a called
* function to the calling code. (This is the same problem solved by
* exceptions in other languages.) It's important to understand that
* this method is both a data type (the #GError struct) and a [set of
* rules][gerror-rules]. If you use #GError incorrectly, then your code will not
* properly interoperate with other code that uses #GError, and users
* of your API will probably get confused. In most cases, [using #GError is
* preferred over numeric error codes][gerror-comparison], but there are
* situations where numeric error codes are useful for performance.
*
* First and foremost: #GError should only be used to report recoverable
* runtime errors, never to report programming errors. If the programmer
* has screwed up, then you should use g_warning(), g_return_if_fail(),
* g_assert(), g_error(), or some similar facility. (Incidentally,
* remember that the g_error() function should only be used for
* programming errors, it should not be used to print any error
* reportable via #GError.)
*
* Examples of recoverable runtime errors are "file not found" or
* "failed to parse input." Examples of programming errors are "NULL
* passed to strcmp()" or "attempted to free the same pointer twice."
* These two kinds of errors are fundamentally different: runtime errors
* should be handled or reported to the user, programming errors should
* be eliminated by fixing the bug in the program. This is why most
* functions in GLib and GTK do not use the #GError facility.
*
* Functions that can fail take a return location for a #GError as their
* last argument. On error, a new #GError instance will be allocated and
* returned to the caller via this argument. For example:
* |[<!-- language="C" -->
* gboolean g_file_get_contents (const gchar *filename,
* gchar **contents,
* gsize *length,
* GError **error);
* ]|
* If you pass a non-%NULL value for the `error` argument, it should
* point to a location where an error can be placed. For example:
* |[<!-- language="C" -->
* gchar *contents;
* GError *err = NULL;
*
* g_file_get_contents ("foo.txt", &contents, NULL, &err);
* g_assert ((contents == NULL && err != NULL) || (contents != NULL && err == NULL));
* if (err != NULL)
* {
* // Report error to user, and free error
* g_assert (contents == NULL);
* fprintf (stderr, "Unable to read file: %s\n", err->message);
* g_error_free (err);
* }
* else
* {
* // Use file contents
* g_assert (contents != NULL);
* }
* ]|
* Note that `err != NULL` in this example is a reliable indicator
* of whether g_file_get_contents() failed. Additionally,
* g_file_get_contents() returns a boolean which
* indicates whether it was successful.
*
* Because g_file_get_contents() returns %FALSE on failure, if you
* are only interested in whether it failed and don't need to display
* an error message, you can pass %NULL for the @error argument:
* |[<!-- language="C" -->
* if (g_file_get_contents ("foo.txt", &contents, NULL, NULL)) // ignore errors
* // no error occurred
* ;
* else
* // error
* ;
* ]|
*
* The #GError object contains three fields: @domain indicates the module
* the error-reporting function is located in, @code indicates the specific
* error that occurred, and @message is a user-readable error message with
* as many details as possible. Several functions are provided to deal
* with an error received from a called function: g_error_matches()
* returns %TRUE if the error matches a given domain and code,
* g_propagate_error() copies an error into an error location (so the
* calling function will receive it), and g_clear_error() clears an
* error location by freeing the error and resetting the location to
* %NULL. To display an error to the user, simply display the @message,
* perhaps along with additional context known only to the calling
* function (the file being opened, or whatever - though in the
* g_file_get_contents() case, the @message already contains a filename).
*
* Since error messages may be displayed to the user, they need to be valid
* UTF-8 (all GTK widgets expect text to be UTF-8). Keep this in mind in
* particular when formatting error messages with filenames, which are in
* the 'filename encoding', and need to be turned into UTF-8 using
* g_filename_to_utf8(), g_filename_display_name() or g_utf8_make_valid().
*
* Note, however, that many error messages are too technical to display to the
* user in an application, so prefer to use g_error_matches() to categorize errors
* from called functions, and build an appropriate error message for the context
* within your application. Error messages from a #GError are more appropriate
* to be printed in system logs or on the command line. They are typically
* translated.
*
* When implementing a function that can report errors, the basic
* tool is g_set_error(). Typically, if a fatal error occurs you
* want to g_set_error(), then return immediately. g_set_error()
* does nothing if the error location passed to it is %NULL.
* Here's an example:
* |[<!-- language="C" -->
* gint
* foo_open_file (GError **error)
* {
* gint fd;
* int saved_errno;
*
* g_return_val_if_fail (error == NULL || *error == NULL, -1);
*
* fd = open ("file.txt", O_RDONLY);
* saved_errno = errno;
*
* if (fd < 0)
* {
* g_set_error (error,
* FOO_ERROR, // error domain
* FOO_ERROR_BLAH, // error code
* "Failed to open file: %s", // error message format string
* g_strerror (saved_errno));
* return -1;
* }
* else
* return fd;
* }
* ]|
*
* Things are somewhat more complicated if you yourself call another
* function that can report a #GError. If the sub-function indicates
* fatal errors in some way other than reporting a #GError, such as
* by returning %TRUE on success, you can simply do the following:
* |[<!-- language="C" -->
* gboolean
* my_function_that_can_fail (GError **err)
* {
* g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
*
* if (!sub_function_that_can_fail (err))
* {
* // assert that error was set by the sub-function
* g_assert (err == NULL || *err != NULL);
* return FALSE;
* }
*
* // otherwise continue, no error occurred
* g_assert (err == NULL || *err == NULL);
* }
* ]|
*
* If the sub-function does not indicate errors other than by
* reporting a #GError (or if its return value does not reliably indicate
* errors) you need to create a temporary #GError
* since the passed-in one may be %NULL. g_propagate_error() is
* intended for use in this case.
* |[<!-- language="C" -->
* gboolean
* my_function_that_can_fail (GError **err)
* {
* GError *tmp_error;
*
* g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
*
* tmp_error = NULL;
* sub_function_that_can_fail (&tmp_error);
*
* if (tmp_error != NULL)
* {
* // store tmp_error in err, if err != NULL,
* // otherwise call g_error_free() on tmp_error
* g_propagate_error (err, tmp_error);
* return FALSE;
* }
*
* // otherwise continue, no error occurred
* }
* ]|
*
* Error pileups are always a bug. For example, this code is incorrect:
* |[<!-- language="C" -->
* gboolean
* my_function_that_can_fail (GError **err)
* {
* GError *tmp_error;
*
* g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
*
* tmp_error = NULL;
* sub_function_that_can_fail (&tmp_error);
* other_function_that_can_fail (&tmp_error);
*
* if (tmp_error != NULL)
* {
* g_propagate_error (err, tmp_error);
* return FALSE;
* }
* }
* ]|
* @tmp_error should be checked immediately after sub_function_that_can_fail(),
* and either cleared or propagated upward. The rule is: after each error,
* you must either handle the error, or return it to the calling function.
*
* Note that passing %NULL for the error location is the equivalent
* of handling an error by always doing nothing about it. So the
* following code is fine, assuming errors in sub_function_that_can_fail()
* are not fatal to my_function_that_can_fail():
* |[<!-- language="C" -->
* gboolean
* my_function_that_can_fail (GError **err)
* {
* GError *tmp_error;
*
* g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
*
* sub_function_that_can_fail (NULL); // ignore errors
*
* tmp_error = NULL;
* other_function_that_can_fail (&tmp_error);
*
* if (tmp_error != NULL)
* {
* g_propagate_error (err, tmp_error);
* return FALSE;
* }
* }
* ]|
*
* Note that passing %NULL for the error location ignores errors;
* it's equivalent to
* `try { sub_function_that_can_fail (); } catch (...) {}`
* in C++. It does not mean to leave errors unhandled; it means
* to handle them by doing nothing.
*
* Error domains and codes are conventionally named as follows:
*
* - The error domain is called <NAMESPACE>_<MODULE>_ERROR,
* for example %G_SPAWN_ERROR or %G_THREAD_ERROR:
* |[<!-- language="C" -->
* #define G_SPAWN_ERROR g_spawn_error_quark ()
*
* G_DEFINE_QUARK (g-spawn-error-quark, g_spawn_error)
* ]|
*
* - The quark function for the error domain is called
* <namespace>_<module>_error_quark,
* for example g_spawn_error_quark() or g_thread_error_quark().
*
* - The error codes are in an enumeration called
* <Namespace><Module>Error;
* for example, #GThreadError or #GSpawnError.
*
* - Members of the error code enumeration are called
* <NAMESPACE>_<MODULE>_ERROR_<CODE>,
* for example %G_SPAWN_ERROR_FORK or %G_THREAD_ERROR_AGAIN.
*
* - If there's a "generic" or "unknown" error code for unrecoverable
* errors it doesn't make sense to distinguish with specific codes,
* it should be called <NAMESPACE>_<MODULE>_ERROR_FAILED,
* for example %G_SPAWN_ERROR_FAILED. In the case of error code
* enumerations that may be extended in future releases, you should
* generally not handle this error code explicitly, but should
* instead treat any unrecognized error code as equivalent to
* FAILED.
*
* ## Comparison of #GError and traditional error handling # {#gerror-comparison}
*
* #GError has several advantages over traditional numeric error codes:
* importantly, tools like
* [gobject-introspection](https://developer.gnome.org/gi/stable/) understand
* #GErrors and convert them to exceptions in bindings; the message includes
* more information than just a code; and use of a domain helps prevent
* misinterpretation of error codes.
*
* #GError has disadvantages though: it requires a memory allocation, and
* formatting the error message string has a performance overhead. This makes it
* unsuitable for use in retry loops where errors are a common case, rather than
* being unusual. For example, using %G_IO_ERROR_WOULD_BLOCK means hitting these
* overheads in the normal control flow. String formatting overhead can be
* eliminated by using g_set_error_literal() in some cases.
*
* These performance issues can be compounded if a function wraps the #GErrors
* returned by the functions it calls: this multiplies the number of allocations
* and string formatting operations. This can be partially mitigated by using
* g_prefix_error().
*
* ## Rules for use of #GError # {#gerror-rules}
*
* Summary of rules for use of #GError:
*
* - Do not report programming errors via #GError.
*
* - The last argument of a function that returns an error should
* be a location where a #GError can be placed (i.e. `GError **error`).
* If #GError is used with varargs, the `GError**` should be the last
* argument before the `...`.
*
* - The caller may pass %NULL for the `GError**` if they are not interested
* in details of the exact error that occurred.
*
* - If %NULL is passed for the `GError**` argument, then errors should
* not be returned to the caller, but your function should still
* abort and return if an error occurs. That is, control flow should
* not be affected by whether the caller wants to get a #GError.
*
* - If a #GError is reported, then your function by definition had a
* fatal failure and did not complete whatever it was supposed to do.
* If the failure was not fatal, then you handled it and you should not
* report it. If it was fatal, then you must report it and discontinue
* whatever you were doing immediately.
*
* - If a #GError is reported, out parameters are not guaranteed to
* be set to any defined value.
*
* - A `GError*` must be initialized to %NULL before passing its address
* to a function that can report errors.
*
* - #GError structs must not be stack-allocated.
*
* - "Piling up" errors is always a bug. That is, if you assign a
* new #GError to a `GError*` that is non-%NULL, thus overwriting
* the previous error, it indicates that you should have aborted
* the operation instead of continuing. If you were able to continue,
* you should have cleared the previous error with g_clear_error().
* g_set_error() will complain if you pile up errors.
*
* - By convention, if you return a boolean value indicating success
* then %TRUE means success and %FALSE means failure. Avoid creating
* functions which have a boolean return value and a #GError parameter,
* but where the boolean does something other than signal whether the
* #GError is set. Among other problems, it requires C callers to allocate
* a temporary error. Instead, provide a `gboolean *` out parameter.
* There are functions in GLib itself such as g_key_file_has_key() that
* are hard to use because of this. If %FALSE is returned, the error must
* be set to a non-%NULL value. One exception to this is that in situations
* that are already considered to be undefined behaviour (such as when a
* g_return_val_if_fail() check fails), the error need not be set.
* Instead of checking separately whether the error is set, callers
* should ensure that they do not provoke undefined behaviour, then
* assume that the error will be set on failure.
*
* - A %NULL return value is also frequently used to mean that an error
* occurred. You should make clear in your documentation whether %NULL
* is a valid return value in non-error cases; if %NULL is a valid value,
* then users must check whether an error was returned to see if the
* function succeeded.
*
* - When implementing a function that can report errors, you may want
* to add a check at the top of your function that the error return
* location is either %NULL or contains a %NULL error (e.g.
* `g_return_if_fail (error == NULL || *error == NULL);`).
*
* ## Extended #GError Domains # {#gerror-extended-domains}
*
* Since GLib 2.68 it is possible to extend the #GError type. This is
* done with the G_DEFINE_EXTENDED_ERROR() macro. To create an
* extended #GError type do something like this in the header file:
* |[<!-- language="C" -->
* typedef enum
* {
* MY_ERROR_BAD_REQUEST,
* } MyError;
* #define MY_ERROR (my_error_quark ())
* GQuark my_error_quark (void);
* int
* my_error_get_parse_error_id (GError *error);
* const char *
* my_error_get_bad_request_details (GError *error);
* ]|
* and in implementation:
* |[<!-- language="C" -->
* typedef struct
* {
* int parse_error_id;
* char *bad_request_details;
* } MyErrorPrivate;
*
* static void
* my_error_private_init (MyErrorPrivate *priv)
* {
* priv->parse_error_id = -1;
* // No need to set priv->bad_request_details to NULL,
* // the struct is initialized with zeros.
* }
*
* static void
* my_error_private_copy (const MyErrorPrivate *src_priv, MyErrorPrivate *dest_priv)
* {
* dest_priv->parse_error_id = src_priv->parse_error_id;
* dest_priv->bad_request_details = g_strdup (src_priv->bad_request_details);
* }
*
* static void
* my_error_private_clear (MyErrorPrivate *priv)
* {
* g_free (priv->bad_request_details);
* }
*
* // This defines the my_error_get_private and my_error_quark functions.
* G_DEFINE_EXTENDED_ERROR (MyError, my_error)
*
* int
* my_error_get_parse_error_id (GError *error)
* {
* MyErrorPrivate *priv = my_error_get_private (error);
* g_return_val_if_fail (priv != NULL, -1);
* return priv->parse_error_id;
* }
*
* const char *
* my_error_get_bad_request_details (GError *error)
* {
* MyErrorPrivate *priv = my_error_get_private (error);
* g_return_val_if_fail (priv != NULL, NULL);
* g_return_val_if_fail (error->code != MY_ERROR_BAD_REQUEST, NULL);
* return priv->bad_request_details;
* }
*
* static void
* my_error_set_bad_request (GError **error,
* const char *reason,
* int error_id,
* const char *details)
* {
* MyErrorPrivate *priv;
* g_set_error (error, MY_ERROR, MY_ERROR_BAD_REQUEST, "Invalid request: %s", reason);
* if (error != NULL && *error != NULL)
* {
* priv = my_error_get_private (error);
* g_return_val_if_fail (priv != NULL, NULL);
* priv->parse_error_id = error_id;
* priv->bad_request_details = g_strdup (details);
* }
* }
* ]|
* An example of use of the error could be:
* |[<!-- language="C" -->
* gboolean
* send_request (GBytes *request, GError **error)
* {
* ParseFailedStatus *failure = validate_request (request);
* if (failure != NULL)
* {
* my_error_set_bad_request (error, failure->reason, failure->error_id, failure->details);
* parse_failed_status_free (failure);
* return FALSE;
* }
*
* return send_one (request, error);
* }
* ]|
*
* Please note that if you are a library author and your library
* exposes an existing error domain, then you can't make this error
* domain an extended one without breaking ABI. This is because
* earlier it was possible to create an error with this error domain
* on the stack and then copy it with g_error_copy(). If the new
* version of your library makes the error domain an extended one,
* then g_error_copy() called by code that allocated the error on the
* stack will try to copy more data than it used to, which will lead
* to undefined behavior. You must not stack-allocate errors with an
* extended error domain, and it is bad practice to stack-allocate any
* other #GErrors.
*
* Extended error domains in unloadable plugins/modules are not
* supported.
*/
#include "config.h"
#include "gvalgrind.h"

View File

@ -462,57 +462,6 @@ g_dngettext (const gchar *domain,
return dngettext (domain, msgid, msgid_plural, n);
}
/**
* SECTION:i18n
* @title: Internationalization
* @short_description: gettext support macros
* @see_also: the gettext manual
*
* GLib doesn't force any particular localization method upon its users.
* But since GLib itself is localized using the gettext() mechanism, it seems
* natural to offer the de-facto standard gettext() support macros in an
* easy-to-use form.
*
* In order to use these macros in an application, you must include
* `<glib/gi18n.h>`. For use in a library, you must include
* `<glib/gi18n-lib.h>`
* after defining the %GETTEXT_PACKAGE macro suitably for your library:
* |[<!-- language="C" -->
* #define GETTEXT_PACKAGE "gtk20"
* #include <glib/gi18n-lib.h>
* ]|
* For an application, note that you also have to call bindtextdomain(),
* bind_textdomain_codeset(), textdomain() and setlocale() early on in your
* main() to make gettext() work. For example:
* |[<!-- language="C" -->
* #include <glib/gi18n.h>
* #include <locale.h>
*
* int
* main (int argc, char **argv)
* {
* setlocale (LC_ALL, "");
* bindtextdomain (GETTEXT_PACKAGE, DATADIR "/locale");
* bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
* textdomain (GETTEXT_PACKAGE);
*
* // Rest of your application.
* }
* ]|
* where `DATADIR` is as typically provided by automake or Meson.
*
* For a library, you only have to call bindtextdomain() and
* bind_textdomain_codeset() in your initialization function. If your library
* doesn't have an initialization function, you can call the functions before
* the first translated message.
*
* The
* [gettext manual](http://www.gnu.org/software/gettext/manual/gettext.html#Maintainers)
* covers details of how to integrate gettext into a projects build system and
* workflow.
*/
/**
* _:
* @String: the string to be translated

View File

@ -127,134 +127,6 @@
#include "glib-init.h"
#include "glib-private.h"
/**
* SECTION:main
* @title: The Main Event Loop
* @short_description: manages all available sources of events
*
* The main event loop manages all the available sources of events for
* GLib and GTK applications. These events can come from any number of
* different types of sources such as file descriptors (plain files,
* pipes or sockets) and timeouts. New types of event sources can also
* be added using g_source_attach().
*
* To allow multiple independent sets of sources to be handled in
* different threads, each source is associated with a #GMainContext.
* A #GMainContext can only be running in a single thread, but
* sources can be added to it and removed from it from other threads. All
* functions which operate on a #GMainContext or a built-in #GSource are
* thread-safe.
*
* Each event source is assigned a priority. The default priority,
* %G_PRIORITY_DEFAULT, is 0. Values less than 0 denote higher priorities.
* Values greater than 0 denote lower priorities. Events from high priority
* sources are always processed before events from lower priority sources: if
* several sources are ready to dispatch, the ones with equal-highest priority
* will be dispatched on the current #GMainContext iteration, and the rest wait
* until a subsequent #GMainContext iteration when they have the highest
* priority of the sources which are ready for dispatch.
*
* Idle functions can also be added, and assigned a priority. These will
* be run whenever no events with a higher priority are ready to be dispatched.
*
* The #GMainLoop data type represents a main event loop. A GMainLoop is
* created with g_main_loop_new(). After adding the initial event sources,
* g_main_loop_run() is called. This continuously checks for new events from
* each of the event sources and dispatches them. Finally, the processing of
* an event from one of the sources leads to a call to g_main_loop_quit() to
* exit the main loop, and g_main_loop_run() returns.
*
* It is possible to create new instances of #GMainLoop recursively.
* This is often used in GTK applications when showing modal dialog
* boxes. Note that event sources are associated with a particular
* #GMainContext, and will be checked and dispatched for all main
* loops associated with that GMainContext.
*
* GTK contains wrappers of some of these functions, e.g. gtk_main(),
* gtk_main_quit() and gtk_events_pending().
*
* ## Creating new source types
*
* One of the unusual features of the #GMainLoop functionality
* is that new types of event source can be created and used in
* addition to the builtin type of event source. A new event source
* type is used for handling GDK events. A new source type is created
* by "deriving" from the #GSource structure. The derived type of
* source is represented by a structure that has the #GSource structure
* as a first element, and other elements specific to the new source
* type. To create an instance of the new source type, call
* g_source_new() passing in the size of the derived structure and
* a table of functions. These #GSourceFuncs determine the behavior of
* the new source type.
*
* New source types basically interact with the main context
* in two ways. Their prepare function in #GSourceFuncs can set a timeout
* to determine the maximum amount of time that the main loop will sleep
* before checking the source again. In addition, or as well, the source
* can add file descriptors to the set that the main context checks using
* g_source_add_poll().
*
* ## Customizing the main loop iteration
*
* Single iterations of a #GMainContext can be run with
* g_main_context_iteration(). In some cases, more detailed control
* of exactly how the details of the main loop work is desired, for
* instance, when integrating the #GMainLoop with an external main loop.
* In such cases, you can call the component functions of
* g_main_context_iteration() directly. These functions are
* g_main_context_prepare(), g_main_context_query(),
* g_main_context_check() and g_main_context_dispatch().
*
* If the event loop thread releases #GMainContext ownership until the results
* required by g_main_context_check() are ready you must create a context with
* the flag %G_MAIN_CONTEXT_FLAGS_OWNERLESS_POLLING or else you'll lose
* g_source_attach() notifications. This happens for instance when you integrate
* the GLib event loop into implementations that follow the proactor pattern
* (i.e. in these contexts the `poll()` implementation will reclaim the thread for
* other tasks until the results are ready). One example of the proactor pattern
* is the Boost.Asio library.
*
* ## State of a Main Context # {#mainloop-states}
*
* The operation of these functions can best be seen in terms
* of a state diagram, as shown in this image.
*
* ![](mainloop-states.gif)
*
* On UNIX, the GLib mainloop is incompatible with fork(). Any program
* using the mainloop must either exec() or exit() from the child
* without returning to the mainloop.
*
* ## Memory management of sources # {#mainloop-memory-management}
*
* There are two options for memory management of the user data passed to a
* #GSource to be passed to its callback on invocation. This data is provided
* in calls to g_timeout_add(), g_timeout_add_full(), g_idle_add(), etc. and
* more generally, using g_source_set_callback(). This data is typically an
* object which owns the timeout or idle callback, such as a widget or a
* network protocol implementation. In many cases, it is an error for the
* callback to be invoked after this owning object has been destroyed, as that
* results in use of freed memory.
*
* The first, and preferred, option is to store the source ID returned by
* functions such as g_timeout_add() or g_source_attach(), and explicitly
* remove that source from the main context using g_source_remove() when the
* owning object is finalized. This ensures that the callback can only be
* invoked while the object is still alive.
*
* The second option is to hold a strong reference to the object in the
* callback, and to release it in the callbacks #GDestroyNotify. This ensures
* that the object is kept alive until after the source is finalized, which is
* guaranteed to be after it is invoked for the final time. The #GDestroyNotify
* is another callback passed to the full variants of #GSource functions (for
* example, g_timeout_add_full()). It is called when the source is finalized,
* and is designed for releasing references like this.
*
* One important caveat of this second approach is that it will keep the object
* alive indefinitely if the main loop is stopped before the #GSource is
* invoked, which may be undesirable.
*/
/* Types */
typedef struct _GIdleSource GIdleSource;

View File

@ -38,60 +38,6 @@
#include "glibintl.h"
#include "gthread.h"
/**
* SECTION:markup
* @Title: Simple XML Subset Parser
* @Short_description: parses a subset of XML
* @See_also: [XML Specification](http://www.w3.org/TR/REC-xml/)
*
* The "GMarkup" parser is intended to parse a simple markup format
* that's a subset of XML. This is a small, efficient, easy-to-use
* parser. It should not be used if you expect to interoperate with
* other applications generating full-scale XML, and must not be used if you
* expect to parse untrusted input. However, it's very
* useful for application data files, config files, etc. where you
* know your application will be the only one writing the file.
* Full-scale XML parsers should be able to parse the subset used by
* GMarkup, so you can easily migrate to full-scale XML at a later
* time if the need arises.
*
* GMarkup is not guaranteed to signal an error on all invalid XML;
* the parser may accept documents that an XML parser would not.
* However, XML documents which are not well-formed (which is a
* weaker condition than being valid. See the
* [XML specification](http://www.w3.org/TR/REC-xml/)
* for definitions of these terms.) are not considered valid GMarkup
* documents.
*
* Simplifications to XML include:
*
* - Only UTF-8 encoding is allowed
*
* - No user-defined entities
*
* - Processing instructions, comments and the doctype declaration
* are "passed through" but are not interpreted in any way
*
* - No DTD or validation
*
* The markup format does support:
*
* - Elements
*
* - Attributes
*
* - 5 standard entities: &amp; &lt; &gt; &quot; &apos;
*
* - Character references
*
* - Sections marked as CDATA
* ## An example parser # {#example}
*
* Here is an example for a markup parser:
* [markup-example.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/glib/tests/markup-example.c)
*/
G_DEFINE_QUARK (g-markup-error-quark, g_markup_error)
typedef enum

View File

@ -28,146 +28,6 @@
* MT safe
*/
/**
* SECTION:messages
* @Title: Message Output and Debugging Functions
* @Short_description: functions to output messages and help debug applications
*
* These functions provide support for outputting messages.
*
* The g_return family of macros (g_return_if_fail(),
* g_return_val_if_fail(), g_return_if_reached(),
* g_return_val_if_reached()) should only be used for programming
* errors, a typical use case is checking for invalid parameters at
* the beginning of a public function. They should not be used if
* you just mean "if (error) return", they should only be used if
* you mean "if (bug in program) return". The program behavior is
* generally considered undefined after one of these checks fails.
* They are not intended for normal control flow, only to give a
* perhaps-helpful warning before giving up.
*
* Structured logging output is supported using g_log_structured(). This differs
* from the traditional g_log() API in that log messages are handled as a
* collection of keyvalue pairs representing individual pieces of information,
* rather than as a single string containing all the information in an arbitrary
* format.
*
* The convenience macros g_info(), g_message(), g_debug(), g_warning() and g_error()
* will use the traditional g_log() API unless you define the symbol
* %G_LOG_USE_STRUCTURED before including `glib.h`. But note that even messages
* logged through the traditional g_log() API are ultimatively passed to
* g_log_structured(), so that all log messages end up in same destination.
* If %G_LOG_USE_STRUCTURED is defined, g_test_expect_message() will become
* ineffective for the wrapper macros g_warning() and friends (see
* [Testing for Messages][testing-for-messages]).
*
* The support for structured logging was motivated by the following needs (some
* of which were supported previously; others werent):
* * Support for multiple logging levels.
* * Structured log support with the ability to add `MESSAGE_ID`s (see
* g_log_structured()).
* * Moving the responsibility for filtering log messages from the program to
* the log viewer instead of libraries and programs installing log handlers
* (with g_log_set_handler()) which filter messages before output, all log
* messages are outputted, and the log viewer program (such as `journalctl`)
* must filter them. This is based on the idea that bugs are sometimes hard
* to reproduce, so it is better to log everything possible and then use
* tools to analyse the logs than it is to not be able to reproduce a bug to
* get additional log data. Code which uses logging in performance-critical
* sections should compile out the g_log_structured() calls in
* release builds, and compile them in in debugging builds.
* * A single writer function which handles all log messages in a process, from
* all libraries and program code; rather than multiple log handlers with
* poorly defined interactions between them. This allows a program to easily
* change its logging policy by changing the writer function, for example to
* log to an additional location or to change what logging output fallbacks
* are used. The log writer functions provided by GLib are exposed publicly
* so they can be used from programs log writers. This allows log writer
* policy and implementation to be kept separate.
* * If a library wants to add standard information to all of its log messages
* (such as library state) or to redact private data (such as passwords or
* network credentials), it should use a wrapper function around its
* g_log_structured() calls or implement that in the single log writer
* function.
* * If a program wants to pass context data from a g_log_structured() call to
* its log writer function so that, for example, it can use the correct
* server connection to submit logs to, that user data can be passed as a
* zero-length #GLogField to g_log_structured_array().
* * Color output needed to be supported on the terminal, to make reading
* through logs easier.
*
* ## Using Structured Logging ## {#using-structured-logging}
*
* To use structured logging (rather than the old-style logging), either use
* the g_log_structured() and g_log_structured_array() functions; or define
* `G_LOG_USE_STRUCTURED` before including any GLib header, and use the
* g_message(), g_debug(), g_error() (etc.) macros.
*
* You do not need to define `G_LOG_USE_STRUCTURED` to use g_log_structured(),
* but it is a good idea to avoid confusion.
*
* ## Log Domains ## {#log-domains}
*
* Log domains may be used to broadly split up the origins of log messages.
* Typically, there are one or a few log domains per application or library.
* %G_LOG_DOMAIN should be used to define the default log domain for the current
* compilation unit it is typically defined at the top of a source file, or in
* the preprocessor flags for a group of source files.
*
* Log domains must be unique, and it is recommended that they are the
* application or library name, optionally followed by a hyphen and a sub-domain
* name. For example, `bloatpad` or `bloatpad-io`.
*
* ## Debug Message Output ## {#debug-message-output}
*
* The default log functions (g_log_default_handler() for the old-style API and
* g_log_writer_default() for the structured API) both drop debug and
* informational messages by default, unless the log domains of those messages
* are listed in the `G_MESSAGES_DEBUG` environment variable (or it is set to
* `all`).
*
* It is recommended that custom log writer functions re-use the
* `G_MESSAGES_DEBUG` environment variable, rather than inventing a custom one,
* so that developers can re-use the same debugging techniques and tools across
* projects. Since GLib 2.68, this can be implemented by dropping messages
* for which g_log_writer_default_would_drop() returns %TRUE.
*
* ## Testing for Messages ## {#testing-for-messages}
*
* With the old g_log() API, g_test_expect_message() and
* g_test_assert_expected_messages() could be used in simple cases to check
* whether some code under test had emitted a given log message. These
* functions have been deprecated with the structured logging API, for several
* reasons:
* * They relied on an internal queue which was too inflexible for many use
* cases, where messages might be emitted in several orders, some
* messages might not be emitted deterministically, or messages might be
* emitted by unrelated log domains.
* * They do not support structured log fields.
* * Examining the log output of code is a bad approach to testing it, and
* while it might be necessary for legacy code which uses g_log(), it should
* be avoided for new code using g_log_structured().
*
* They will continue to work as before if g_log() is in use (and
* %G_LOG_USE_STRUCTURED is not defined). They will do nothing if used with the
* structured logging API.
*
* Examining the log output of code is discouraged: libraries should not emit to
* `stderr` during defined behaviour, and hence this should not be tested. If
* the log emissions of a library during undefined behaviour need to be tested,
* they should be limited to asserting that the library aborts and prints a
* suitable error message before aborting. This should be done with
* g_test_trap_assert_stderr().
*
* If it is really necessary to test the structured log messages emitted by a
* particular piece of code and the code cannot be restructured to be more
* suitable to more conventional unit testing you should write a custom log
* writer function (see g_log_set_writer_func()) which appends all log messages
* to a queue. When you want to check the log messages, examine and clear the
* queue, ignoring irrelevant log messages (for example, from log domains other
* than the one under test).
*/
#include "config.h"
#include <stdlib.h>

View File

@ -19,166 +19,6 @@
* along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
/**
* SECTION:goptioncontext
* @Short_description: parses commandline options
* @Title: Commandline option parser
*
* The GOption commandline parser is intended to be a simpler replacement
* for the popt library. It supports short and long commandline options,
* as shown in the following example:
*
* `testtreemodel -r 1 --max-size 20 --rand --display=:1.0 -vb -- file1 file2`
*
* The example demonstrates a number of features of the GOption
* commandline parser:
*
* - Options can be single letters, prefixed by a single dash.
*
* - Multiple short options can be grouped behind a single dash.
*
* - Long options are prefixed by two consecutive dashes.
*
* - Options can have an extra argument, which can be a number, a string or
* a filename. For long options, the extra argument can be appended with
* an equals sign after the option name, which is useful if the extra
* argument starts with a dash, which would otherwise cause it to be
* interpreted as another option.
*
* - Non-option arguments are returned to the application as rest arguments.
*
* - An argument consisting solely of two dashes turns off further parsing,
* any remaining arguments (even those starting with a dash) are returned
* to the application as rest arguments.
*
* Another important feature of GOption is that it can automatically
* generate nicely formatted help output. Unless it is explicitly turned
* off with g_option_context_set_help_enabled(), GOption will recognize
* the `--help`, `-?`, `--help-all` and `--help-groupname` options
* (where `groupname` is the name of a #GOptionGroup) and write a text
* similar to the one shown in the following example to stdout.
*
* |[
* Usage:
* testtreemodel [OPTION...] - test tree model performance
*
* Help Options:
* -h, --help Show help options
* --help-all Show all help options
* --help-gtk Show GTK Options
*
* Application Options:
* -r, --repeats=N Average over N repetitions
* -m, --max-size=M Test up to 2^M items
* --display=DISPLAY X display to use
* -v, --verbose Be verbose
* -b, --beep Beep when done
* --rand Randomize the data
* ]|
*
* GOption groups options in #GOptionGroups, which makes it easy to
* incorporate options from multiple sources. The intended use for this is
* to let applications collect option groups from the libraries it uses,
* add them to their #GOptionContext, and parse all options by a single call
* to g_option_context_parse(). See gtk_get_option_group() for an example.
*
* If an option is declared to be of type string or filename, GOption takes
* care of converting it to the right encoding; strings are returned in
* UTF-8, filenames are returned in the GLib filename encoding. Note that
* this only works if setlocale() has been called before
* g_option_context_parse().
*
* Here is a complete example of setting up GOption to parse the example
* commandline above and produce the example help output.
* |[<!-- language="C" -->
* static gint repeats = 2;
* static gint max_size = 8;
* static gboolean verbose = FALSE;
* static gboolean beep = FALSE;
* static gboolean randomize = FALSE;
*
* static GOptionEntry entries[] =
* {
* { "repeats", 'r', 0, G_OPTION_ARG_INT, &repeats, "Average over N repetitions", "N" },
* { "max-size", 'm', 0, G_OPTION_ARG_INT, &max_size, "Test up to 2^M items", "M" },
* { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL },
* { "beep", 'b', 0, G_OPTION_ARG_NONE, &beep, "Beep when done", NULL },
* { "rand", 0, 0, G_OPTION_ARG_NONE, &randomize, "Randomize the data", NULL },
* G_OPTION_ENTRY_NULL
* };
*
* int
* main (int argc, char *argv[])
* {
* GError *error = NULL;
* GOptionContext *context;
*
* context = g_option_context_new ("- test tree model performance");
* g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
* g_option_context_add_group (context, gtk_get_option_group (TRUE));
* if (!g_option_context_parse (context, &argc, &argv, &error))
* {
* g_print ("option parsing failed: %s\n", error->message);
* exit (1);
* }
*
* ...
*
* }
* ]|
*
* On UNIX systems, the argv that is passed to main() has no particular
* encoding, even to the extent that different parts of it may have
* different encodings. In general, normal arguments and flags will be
* in the current locale and filenames should be considered to be opaque
* byte strings. Proper use of %G_OPTION_ARG_FILENAME vs
* %G_OPTION_ARG_STRING is therefore important.
*
* Note that on Windows, filenames do have an encoding, but using
* #GOptionContext with the argv as passed to main() will result in a
* program that can only accept commandline arguments with characters
* from the system codepage. This can cause problems when attempting to
* deal with filenames containing Unicode characters that fall outside
* of the codepage.
*
* A solution to this is to use g_win32_get_command_line() and
* g_option_context_parse_strv() which will properly handle full Unicode
* filenames. If you are using #GApplication, this is done
* automatically for you.
*
* The following example shows how you can use #GOptionContext directly
* in order to correctly deal with Unicode filenames on Windows:
*
* |[<!-- language="C" -->
* int
* main (int argc, char **argv)
* {
* GError *error = NULL;
* GOptionContext *context;
* gchar **args;
*
* #ifdef G_OS_WIN32
* args = g_win32_get_command_line ();
* #else
* args = g_strdupv (argv);
* #endif
*
* // set up context
*
* if (!g_option_context_parse_strv (context, &args, &error))
* {
* // error happened
* }
*
* ...
*
* g_strfreev (args);
*
* ...
* }
* ]|
*/
#include "config.h"
#include <string.h>

View File

@ -34,136 +34,6 @@
#include <string.h>
/**
* SECTION:rcbox
* @Title: Reference counted data
* @Short_description: Allocated memory with reference counting semantics
*
* A "reference counted box", or "RcBox", is an opaque wrapper data type
* that is guaranteed to be as big as the size of a given data type, and
* which augments the given data type with reference counting semantics
* for its memory management.
*
* RcBox is useful if you have a plain old data type, like a structure
* typically placed on the stack, and you wish to provide additional API
* to use it on the heap; or if you want to implement a new type to be
* passed around by reference without necessarily implementing copy/free
* semantics or your own reference counting.
*
* The typical use is:
*
* |[<!-- language="C" -->
* typedef struct {
* char *name;
* char *address;
* char *city;
* char *state;
* int age;
* } Person;
*
* Person *
* person_new (void)
* {
* return g_rc_box_new0 (Person);
* }
* ]|
*
* Every time you wish to acquire a reference on the memory, you should
* call g_rc_box_acquire(); similarly, when you wish to release a reference
* you should call g_rc_box_release():
*
* |[<!-- language="C" -->
* // Add a Person to the Database; the Database acquires ownership
* // of the Person instance
* void
* add_person_to_database (Database *db, Person *p)
* {
* db->persons = g_list_prepend (db->persons, g_rc_box_acquire (p));
* }
*
* // Removes a Person from the Database; the reference acquired by
* // add_person_to_database() is released here
* void
* remove_person_from_database (Database *db, Person *p)
* {
* db->persons = g_list_remove (db->persons, p);
* g_rc_box_release (p);
* }
* ]|
*
* If you have additional memory allocated inside the structure, you can
* use g_rc_box_release_full(), which takes a function pointer, which
* will be called if the reference released was the last:
*
* |[<!-- language="C" -->
* void
* person_clear (Person *p)
* {
* g_free (p->name);
* g_free (p->address);
* g_free (p->city);
* g_free (p->state);
* }
*
* void
* remove_person_from_database (Database *db, Person *p)
* {
* db->persons = g_list_remove (db->persons, p);
* g_rc_box_release_full (p, (GDestroyNotify) person_clear);
* }
* ]|
*
* If you wish to transfer the ownership of a reference counted data
* type without increasing the reference count, you can use g_steal_pointer():
*
* |[<!-- language="C" -->
* Person *p = g_rc_box_new (Person);
*
* // fill_person_details() is defined elsewhere
* fill_person_details (p);
*
* // add_person_to_database_no_ref() is defined elsewhere; it adds
* // a Person to the Database without taking a reference
* add_person_to_database_no_ref (db, g_steal_pointer (&p));
* ]|
*
* ## Thread safety
*
* The reference counting operations on data allocated using g_rc_box_alloc(),
* g_rc_box_new(), and g_rc_box_dup() are not thread safe; it is your code's
* responsibility to ensure that references are acquired are released on the
* same thread.
*
* If you need thread safe reference counting, see the [atomic reference counted
* data][arcbox] API.
*
* ## Automatic pointer clean up
*
* If you want to add g_autoptr() support to your plain old data type through
* reference counting, you can use the G_DEFINE_AUTOPTR_CLEANUP_FUNC() and
* g_rc_box_release():
*
* |[<!-- language="C" -->
* G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, g_rc_box_release)
* ]|
*
* If you need to clear the contents of the data, you will need to use an
* ancillary function that calls g_rc_box_release_full():
*
* |[<!-- language="C" -->
* static void
* my_data_struct_release (MyDataStruct *data)
* {
* // my_data_struct_clear() is defined elsewhere
* g_rc_box_release_full (data, (GDestroyNotify) my_data_struct_clear);
* }
*
* G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, my_data_struct_release)
* ]|
*
* Since: 2.58
*/
/* We use the same alignment as GTypeInstance and GNU libc's malloc */
#define ALIGN_STRUCT(offset) ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT)

View File

@ -18,29 +18,6 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
/**
* SECTION:refcount
* @Title: Reference counting
* @Short_description: Reference counting types and functions
*
* Reference counting is a garbage collection mechanism that is based on
* assigning a counter to a data type, or any memory area; the counter is
* increased whenever a new reference to that data type is acquired, and
* decreased whenever the reference is released. Once the last reference
* is released, the resources associated to that data type are freed.
*
* GLib uses reference counting in many of its data types, and provides
* the #grefcount and #gatomicrefcount types to implement safe and atomic
* reference counting semantics in new data types.
*
* It is important to note that #grefcount and #gatomicrefcount should be
* considered completely opaque types; you should always use the provided
* API to increase and decrease the counters, and you should never check
* their content directly, or compare their content with other values.
*
* Since: 2.58
*/
#include "config.h"
#include "grefcount.h"

View File

@ -30,65 +30,6 @@
#include "glib_trace.h"
#include "gprintf.h"
/**
* SECTION:memory_slices
* @title: Memory Slices
* @short_description: efficient way to allocate groups of equal-sized
* chunks of memory
*
* GSlice was a space-efficient and multi-processing scalable way to allocate
* equal sized pieces of memory. Since GLib 2.76, its implementation has been
* removed and it calls g_malloc() and g_free_sized(), because the performance
* of the system-default allocators has improved on all platforms since GSlice
* was written.
*
* The GSlice APIs have not been deprecated, as they are widely in use and doing
* so would be very disruptive for little benefit.
*
* New code should be written using g_new()/g_malloc() and g_free_sized() or
* g_free(). There is no particular benefit in porting existing code away from
* g_slice_new()/g_slice_free() unless its being rewritten anyway.
*
* Here is an example for using the slice allocator:
* |[<!-- language="C" -->
* gchar *mem[10000];
* gint i;
*
* // Allocate 10000 blocks.
* for (i = 0; i < 10000; i++)
* {
* mem[i] = g_slice_alloc (50);
*
* // Fill in the memory with some junk.
* for (j = 0; j < 50; j++)
* mem[i][j] = i * j;
* }
*
* // Now free all of the blocks.
* for (i = 0; i < 10000; i++)
* g_slice_free1 (50, mem[i]);
* ]|
*
* And here is an example for using the using the slice allocator
* with data structures:
* |[<!-- language="C" -->
* GRealArray *array;
*
* // Allocate one block, using the g_slice_new() macro.
* array = g_slice_new (GRealArray);
*
* // We can now use array just like a normal pointer to a structure.
* array->data = NULL;
* array->len = 0;
* array->alloc = 0;
* array->zero_terminated = (zero_terminated ? 1 : 0);
* array->clear = (clear ? 1 : 0);
* array->elt_size = elt_size;
*
* // We can free the block, so it can be reused.
* g_slice_free (GRealArray, array);
* ]|
*/
/* --- auxiliary functions --- */
void

View File

@ -67,193 +67,6 @@
* See https://gitlab.gnome.org/GNOME/glib/-/issues/2885 */
#define TAP_SUBTEST_PREFIX "# " /* a 4-space indented line */
/**
* SECTION:testing
* @title: Testing
* @short_description: a test framework
*
* GLib provides a framework for writing and maintaining unit tests
* in parallel to the code they are testing. The API is designed according
* to established concepts found in the other test frameworks (JUnit, NUnit,
* RUnit), which in turn is based on smalltalk unit testing concepts.
*
* - Test case: Tests (test methods) are grouped together with their
* fixture into test cases.
*
* - Fixture: A test fixture consists of fixture data and setup and
* teardown methods to establish the environment for the test
* functions. We use fresh fixtures, i.e. fixtures are newly set
* up and torn down around each test invocation to avoid dependencies
* between tests.
*
* - Test suite: Test cases can be grouped into test suites, to allow
* subsets of the available tests to be run. Test suites can be
* grouped into other test suites as well.
*
* The API is designed to handle creation and registration of test suites
* and test cases implicitly. A simple call like
* |[<!-- language="C" -->
* g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
*
* g_test_add_func ("/misc/assertions", test_assertions);
* ]|
* creates a test suite called "misc" with a single test case named
* "assertions", which consists of running the test_assertions function.
*
* g_test_init() should be called before calling any other test functions.
*
* In addition to the traditional g_assert_true(), the test framework provides
* an extended set of assertions for comparisons: g_assert_cmpfloat(),
* g_assert_cmpfloat_with_epsilon(), g_assert_cmpint(), g_assert_cmpuint(),
* g_assert_cmphex(), g_assert_cmpstr(), g_assert_cmpmem() and
* g_assert_cmpvariant(). The
* advantage of these variants over plain g_assert_true() is that the assertion
* messages can be more elaborate, and include the values of the compared
* entities.
*
* Note that g_assert() should not be used in unit tests, since it is a no-op
* when compiling with `G_DISABLE_ASSERT`. Use g_assert() in production code,
* and g_assert_true() in unit tests.
*
* A full example of creating a test suite with two tests using fixtures:
* |[<!-- language="C" -->
* #include <glib.h>
* #include <locale.h>
*
* typedef struct {
* MyObject *obj;
* OtherObject *helper;
* } MyObjectFixture;
*
* static void
* my_object_fixture_set_up (MyObjectFixture *fixture,
* gconstpointer user_data)
* {
* fixture->obj = my_object_new ();
* my_object_set_prop1 (fixture->obj, "some-value");
* my_object_do_some_complex_setup (fixture->obj, user_data);
*
* fixture->helper = other_object_new ();
* }
*
* static void
* my_object_fixture_tear_down (MyObjectFixture *fixture,
* gconstpointer user_data)
* {
* g_clear_object (&fixture->helper);
* g_clear_object (&fixture->obj);
* }
*
* static void
* test_my_object_test1 (MyObjectFixture *fixture,
* gconstpointer user_data)
* {
* g_assert_cmpstr (my_object_get_property (fixture->obj), ==, "initial-value");
* }
*
* static void
* test_my_object_test2 (MyObjectFixture *fixture,
* gconstpointer user_data)
* {
* my_object_do_some_work_using_helper (fixture->obj, fixture->helper);
* g_assert_cmpstr (my_object_get_property (fixture->obj), ==, "updated-value");
* }
*
* int
* main (int argc, char *argv[])
* {
* setlocale (LC_ALL, "");
*
* g_test_init (&argc, &argv, NULL);
*
* // Define the tests.
* g_test_add ("/my-object/test1", MyObjectFixture, "some-user-data",
* my_object_fixture_set_up, test_my_object_test1,
* my_object_fixture_tear_down);
* g_test_add ("/my-object/test2", MyObjectFixture, "some-user-data",
* my_object_fixture_set_up, test_my_object_test2,
* my_object_fixture_tear_down);
*
* return g_test_run ();
* }
* ]|
*
* ## Integrating GTest in your project
*
* If you are using the [Meson](http://mesonbuild.com) build system, you will
* typically use the provided `test()` primitive to call the test binaries,
* e.g.:
*
* |[<!-- language="plain" -->
* test(
* 'foo',
* executable('foo', 'foo.c', dependencies: deps),
* env: [
* 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
* 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
* ],
* )
*
* test(
* 'bar',
* executable('bar', 'bar.c', dependencies: deps),
* env: [
* 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
* 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
* ],
* )
* ]|
*
* If you are using Autotools, you're strongly encouraged to use the Automake
* [TAP](https://testanything.org/) harness; GLib provides template files for
* easily integrating with it:
*
* - [glib-tap.mk](https://gitlab.gnome.org/GNOME/glib/blob/glib-2-58/glib-tap.mk)
* - [tap-test](https://gitlab.gnome.org/GNOME/glib/blob/glib-2-58/tap-test)
* - [tap-driver.sh](https://gitlab.gnome.org/GNOME/glib/blob/glib-2-58/tap-driver.sh)
*
* You can copy these files in your own project's root directory, and then
* set up your `Makefile.am` file to reference them, for instance:
*
* |[<!-- language="plain" -->
* include $(top_srcdir)/glib-tap.mk
*
* # test binaries
* test_programs = \
* foo \
* bar
*
* # data distributed in the tarball
* dist_test_data = \
* foo.data.txt \
* bar.data.txt
*
* # data not distributed in the tarball
* test_data = \
* blah.data.txt
* ]|
*
* Make sure to distribute the TAP files, using something like the following
* in your top-level `Makefile.am`:
*
* |[<!-- language="plain" -->
* EXTRA_DIST += \
* tap-driver.sh \
* tap-test
* ]|
*
* `glib-tap.mk` will be distributed implicitly due to being included in a
* `Makefile.am`. All three files should be added to version control.
*
* If you don't have access to the Autotools TAP harness, you can use the
* [gtester][gtester] and [gtester-report][gtester-report] tools, and use
* the [glib.mk](https://gitlab.gnome.org/GNOME/glib/blob/glib-2-58/glib.mk)
* Automake template provided by GLib. Note, however, that since GLib 2.62,
* [gtester][gtester] and [gtester-report][gtester-report] have been deprecated
* in favour of using TAP. The `--tap` argument to tests is enabled by default
* as of GLib 2.62.
*/
/**
* g_test_initialized:
*

View File

@ -62,105 +62,6 @@
#include "glib_trace.h"
#include "gtrace-private.h"
/**
* SECTION:threads
* @title: Threads
* @short_description: portable support for threads, mutexes, locks,
* conditions and thread private data
* @see_also: #GThreadPool, #GAsyncQueue
*
* Threads act almost like processes, but unlike processes all threads
* of one process share the same memory. This is good, as it provides
* easy communication between the involved threads via this shared
* memory, and it is bad, because strange things (so called
* "Heisenbugs") might happen if the program is not carefully designed.
* In particular, due to the concurrent nature of threads, no
* assumptions on the order of execution of code running in different
* threads can be made, unless order is explicitly forced by the
* programmer through synchronization primitives.
*
* The aim of the thread-related functions in GLib is to provide a
* portable means for writing multi-threaded software. There are
* primitives for mutexes to protect the access to portions of memory
* (#GMutex, #GRecMutex and #GRWLock). There is a facility to use
* individual bits for locks (g_bit_lock()). There are primitives
* for condition variables to allow synchronization of threads (#GCond).
* There are primitives for thread-private data - data that every
* thread has a private instance of (#GPrivate). There are facilities
* for one-time initialization (#GOnce, g_once_init_enter_pointer(),
* g_once_init_enter()). Finally,
* there are primitives to create and manage threads (#GThread).
*
* The GLib threading system used to be initialized with g_thread_init().
* This is no longer necessary. Since version 2.32, the GLib threading
* system is automatically initialized at the start of your program,
* and all thread-creation functions and synchronization primitives
* are available right away.
*
* Note that it is not safe to assume that your program has no threads
* even if you don't call g_thread_new() yourself. GLib and GIO can
* and will create threads for their own purposes in some cases, such
* as when using g_unix_signal_source_new() or when using GDBus.
*
* Originally, UNIX did not have threads, and therefore some traditional
* UNIX APIs are problematic in threaded programs. Some notable examples
* are
*
* - C library functions that return data in statically allocated
* buffers, such as strtok() or strerror(). For many of these,
* there are thread-safe variants with a _r suffix, or you can
* look at corresponding GLib APIs (like g_strsplit() or g_strerror()).
*
* - The functions setenv() and unsetenv() manipulate the process
* environment in a not thread-safe way, and may interfere with getenv()
* calls in other threads. Note that getenv() calls may be hidden behind
* other APIs. For example, GNU gettext() calls getenv() under the
* covers. In general, it is best to treat the environment as readonly.
* If you absolutely have to modify the environment, do it early in
* main(), when no other threads are around yet.
*
* - The setlocale() function changes the locale for the entire process,
* affecting all threads. Temporary changes to the locale are often made
* to change the behavior of string scanning or formatting functions
* like scanf() or printf(). GLib offers a number of string APIs
* (like g_ascii_formatd() or g_ascii_strtod()) that can often be
* used as an alternative. Or you can use the uselocale() function
* to change the locale only for the current thread.
*
* - The fork() function only takes the calling thread into the child's
* copy of the process image. If other threads were executing in critical
* sections they could have left mutexes locked which could easily
* cause deadlocks in the new child. For this reason, you should
* call exit() or exec() as soon as possible in the child and only
* make signal-safe library calls before that.
*
* - The daemon() function uses fork() in a way contrary to what is
* described above. It should not be used with GLib programs.
*
* GLib itself is internally completely thread-safe (all global data is
* automatically locked), but individual data structure instances are
* not automatically locked for performance reasons. For example,
* you must coordinate accesses to the same #GHashTable from multiple
* threads. The two notable exceptions from this rule are #GMainLoop
* and #GAsyncQueue, which are thread-safe and need no further
* application-level locking to be accessed from multiple threads.
* Most refcounting functions such as g_object_ref() are also thread-safe.
*
* A common use for #GThreads is to move a long-running blocking operation out
* of the main thread and into a worker thread. For GLib functions, such as
* single GIO operations, this is not necessary, and complicates the code.
* Instead, the `_async()` version of the function should be used from the main
* thread, eliminating the need for locking and synchronisation between multiple
* threads. If an operation does need to be moved to a worker thread, consider
* using g_task_run_in_thread(), or a #GThreadPool. #GThreadPool is often a
* better choice than #GThread, as it handles thread reuse and task queueing;
* #GTask uses this internally.
*
* However, if multiple blocking operations need to be performed in sequence,
* and it is not possible to use #GTask for them, moving them to a worker thread
* can clarify the code.
*/
/* G_LOCK Documentation {{{1 ---------------------------------------------- */
/**

View File

@ -52,84 +52,6 @@
#include "gmoduleconf.h"
#include "gstdio.h"
/**
* SECTION:modules
* @title: Dynamic Loading of Modules
* @short_description: portable method for dynamically loading 'plug-ins'
*
* These functions provide a portable way to dynamically load object files
* (commonly known as 'plug-ins'). The current implementation supports all
* systems that provide an implementation of dlopen() (e.g. Linux/Sun), as
* well as Windows platforms via DLLs.
*
* A program which wants to use these functions must be linked to the
* libraries output by the command `pkg-config --libs gmodule-2.0`.
*
* To use them you must first determine whether dynamic loading
* is supported on the platform by calling g_module_supported().
* If it is, you can open a module with g_module_open(),
* find the module's symbols (e.g. function names) with g_module_symbol(),
* and later close the module with g_module_close().
* g_module_name() will return the file name of a currently opened module.
*
* If any of the above functions fail, the error status can be found with
* g_module_error().
*
* The #GModule implementation features reference counting for opened modules,
* and supports hook functions within a module which are called when the
* module is loaded and unloaded (see #GModuleCheckInit and #GModuleUnload).
*
* If your module introduces static data to common subsystems in the running
* program, e.g. through calling
* `g_quark_from_static_string ("my-module-stuff")`,
* it must ensure that it is never unloaded, by calling g_module_make_resident().
*
* Example: Calling a function defined in a GModule
* |[<!-- language="C" -->
* // the function signature for 'say_hello'
* typedef void (* SayHelloFunc) (const char *message);
*
* gboolean
* just_say_hello (const char *filename, GError **error)
* {
* SayHelloFunc say_hello;
* GModule *module;
*
* module = g_module_open (filename, G_MODULE_BIND_LAZY);
* if (!module)
* {
* g_set_error (error, FOO_ERROR, FOO_ERROR_BLAH,
* "%s", g_module_error ());
* return FALSE;
* }
*
* if (!g_module_symbol (module, "say_hello", (gpointer *)&say_hello))
* {
* g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN,
* "%s: %s", filename, g_module_error ());
* if (!g_module_close (module))
* g_warning ("%s: %s", filename, g_module_error ());
* return FALSE;
* }
*
* if (say_hello == NULL)
* {
* g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN,
* "symbol say_hello is NULL");
* if (!g_module_close (module))
* g_warning ("%s: %s", filename, g_module_error ());
* return FALSE;
* }
*
* // call our function in the module
* say_hello ("Hello world!");
*
* if (!g_module_close (module))
* g_warning ("%s: %s", filename, g_module_error ());
* return TRUE;
* }
* ]|
*/
/**
* GModule:

View File

@ -33,35 +33,6 @@
#include "gvaluearray.h"
#include "gvaluecollector.h"
/**
* SECTION:gboxed
* @short_description: A mechanism to wrap opaque C structures registered
* by the type system
* @see_also: #GParamSpecBoxed, g_param_spec_boxed()
* @title: Boxed Types
*
* #GBoxed is a generic wrapper mechanism for arbitrary C structures.
*
* The only thing the type system needs to know about the structures is how to
* copy them (a #GBoxedCopyFunc) and how to free them (a #GBoxedFreeFunc);
* beyond that, they are treated as opaque chunks of memory.
*
* Boxed types are useful for simple value-holder structures like rectangles or
* points. They can also be used for wrapping structures defined in non-#GObject
* based libraries. They allow arbitrary structures to be handled in a uniform
* way, allowing uniform copying (or referencing) and freeing (or unreferencing)
* of them, and uniform representation of the type of the contained structure.
* In turn, this allows any type which can be boxed to be set as the data in a
* #GValue, which allows for polymorphic handling of a much wider range of data
* types, and hence usage of such types as #GObject property values.
*
* #GBoxed is designed so that reference counted types can be boxed. Use the
* types ref function as the #GBoxedCopyFunc, and its unref function as the
* #GBoxedFreeFunc. For example, for #GBytes, the #GBoxedCopyFunc is
* g_bytes_ref(), and the #GBoxedFreeFunc is g_bytes_unref().
*/
static inline void /* keep this function in sync with gvalue.c */
value_meminit (GValue *value,
GType value_type)

View File

@ -31,43 +31,6 @@
#include "gvaluecollector.h"
/**
* SECTION:enumerations_flags
* @short_description: Enumeration and flags types
* @title: Enumeration and Flag Types
* @see_also:#GParamSpecEnum, #GParamSpecFlags, g_param_spec_enum(),
* g_param_spec_flags()
*
* The GLib type system provides fundamental types for enumeration and
* flags types. (Flags types are like enumerations, but allow their
* values to be combined by bitwise or). A registered enumeration or
* flags type associates a name and a nickname with each allowed
* value, and the methods g_enum_get_value_by_name(),
* g_enum_get_value_by_nick(), g_flags_get_value_by_name() and
* g_flags_get_value_by_nick() can look up values by their name or
* nickname. When an enumeration or flags type is registered with the
* GLib type system, it can be used as value type for object
* properties, using g_param_spec_enum() or g_param_spec_flags().
*
* GObject ships with a utility called [glib-mkenums][glib-mkenums],
* that can construct suitable type registration functions from C enumeration
* definitions.
*
* Example of how to get a string representation of an enum value:
* |[<!-- language="C" -->
* GEnumClass *enum_class;
* GEnumValue *enum_value;
*
* enum_class = g_type_class_ref (MAMAN_TYPE_MY_ENUM);
* enum_value = g_enum_get_value (enum_class, MAMAN_MY_ENUM_FOO);
*
* g_print ("Name: %s\n", enum_value->value_name);
*
* g_type_class_unref (enum_class);
* ]|
*/
/* --- prototypes --- */
static void g_enum_class_init (GEnumClass *class,
gpointer class_data);

View File

@ -54,86 +54,6 @@
* GObjects and their methods, see the [GType conventions][gtype-conventions].
* For the high-level concepts behind GObject, read [Instantiatable classed types:
* Objects][gtype-instantiatable-classed].
*
* ## Floating references # {#floating-ref}
*
* **Note**: Floating references are a C convenience API and should not be
* used in modern GObject code. Language bindings in particular find the
* concept highly problematic, as floating references are not identifiable
* through annotations, and neither are deviations from the floating reference
* behavior, like types that inherit from #GInitiallyUnowned and still return
* a full reference from g_object_new().
*
* GInitiallyUnowned is derived from GObject. The only difference between
* the two is that the initial reference of a GInitiallyUnowned is flagged
* as a "floating" reference. This means that it is not specifically
* claimed to be "owned" by any code portion. The main motivation for
* providing floating references is C convenience. In particular, it
* allows code to be written as:
*
* |[<!-- language="C" -->
* container = create_container ();
* container_add_child (container, create_child());
* ]|
*
* If container_add_child() calls g_object_ref_sink() on the passed-in child,
* no reference of the newly created child is leaked. Without floating
* references, container_add_child() can only g_object_ref() the new child,
* so to implement this code without reference leaks, it would have to be
* written as:
*
* |[<!-- language="C" -->
* Child *child;
* container = create_container ();
* child = create_child ();
* container_add_child (container, child);
* g_object_unref (child);
* ]|
*
* The floating reference can be converted into an ordinary reference by
* calling g_object_ref_sink(). For already sunken objects (objects that
* don't have a floating reference anymore), g_object_ref_sink() is equivalent
* to g_object_ref() and returns a new reference.
*
* Since floating references are useful almost exclusively for C convenience,
* language bindings that provide automated reference and memory ownership
* maintenance (such as smart pointers or garbage collection) should not
* expose floating references in their API. The best practice for handling
* types that have initially floating references is to immediately sink those
* references after g_object_new() returns, by checking if the #GType
* inherits from #GInitiallyUnowned. For instance:
*
* |[<!-- language="C" -->
* GObject *res = g_object_new_with_properties (gtype,
* n_props,
* prop_names,
* prop_values);
*
* // or: if (g_type_is_a (gtype, G_TYPE_INITIALLY_UNOWNED))
* if (G_IS_INITIALLY_UNOWNED (res))
* g_object_ref_sink (res);
*
* return res;
* ]|
*
* Some object implementations may need to save an objects floating state
* across certain code portions (an example is #GtkMenu), to achieve this,
* the following sequence can be used:
*
* |[<!-- language="C" -->
* // save floating state
* gboolean was_floating = g_object_is_floating (object);
* g_object_ref_sink (object);
* // protected code portion
*
* ...
*
* // restore floating state
* if (was_floating)
* g_object_force_floating (object);
* else
* g_object_unref (object); // release previously acquired reference
* ]|
*/
/* --- macros --- */

View File

@ -31,122 +31,6 @@
#include "gtype-private.h"
/**
* SECTION:generic_values
* @short_description: A polymorphic type that can hold values of any
* other type
* @see_also: The fundamental types which all support #GValue
* operations and thus can be used as a type initializer for
* g_value_init() are defined by a separate interface. See the
* [standard values API][gobject-Standard-Parameter-and-Value-Types]
* for details
* @title: Generic values
*
* The #GValue structure is basically a variable container that consists
* of a type identifier and a specific value of that type.
*
* The type identifier within a #GValue structure always determines the
* type of the associated value.
*
* To create an undefined #GValue structure, simply create a zero-filled
* #GValue structure. To initialize the #GValue, use the g_value_init()
* function. A #GValue cannot be used until it is initialized. Before
* destruction you must always use g_value_unset() to make sure allocated
* memory is freed.
*
* The basic type operations (such as freeing and copying) are determined
* by the #GTypeValueTable associated with the type ID stored in the #GValue.
* Other #GValue operations (such as converting values between types) are
* provided by this interface.
*
* The code in the example program below demonstrates #GValue's
* features.
*
* |[<!-- language="C" -->
* #include <glib-object.h>
*
* static void
* int2string (const GValue *src_value,
* GValue *dest_value)
* {
* if (g_value_get_int (src_value) == 42)
* g_value_set_static_string (dest_value, "An important number");
* else
* g_value_set_static_string (dest_value, "What's that?");
* }
*
* int
* main (int argc,
* char *argv[])
* {
* // GValues must be initialized
* GValue a = G_VALUE_INIT;
* GValue b = G_VALUE_INIT;
* const gchar *message;
*
* // The GValue starts empty
* g_assert (!G_VALUE_HOLDS_STRING (&a));
*
* // Put a string in it
* g_value_init (&a, G_TYPE_STRING);
* g_assert (G_VALUE_HOLDS_STRING (&a));
* g_value_set_static_string (&a, "Hello, world!");
* g_printf ("%s\n", g_value_get_string (&a));
*
* // Reset it to its pristine state
* g_value_unset (&a);
*
* // It can then be reused for another type
* g_value_init (&a, G_TYPE_INT);
* g_value_set_int (&a, 42);
*
* // Attempt to transform it into a GValue of type STRING
* g_value_init (&b, G_TYPE_STRING);
*
* // An INT is transformable to a STRING
* g_assert (g_value_type_transformable (G_TYPE_INT, G_TYPE_STRING));
*
* g_value_transform (&a, &b);
* g_printf ("%s\n", g_value_get_string (&b));
*
* // Attempt to transform it again using a custom transform function
* g_value_register_transform_func (G_TYPE_INT, G_TYPE_STRING, int2string);
* g_value_transform (&a, &b);
* g_printf ("%s\n", g_value_get_string (&b));
* return 0;
* }
* ]|
*
* See also [gobject-Standard-Parameter-and-Value-Types] for more information on
* validation of #GValue.
*
* For letting a #GValue own (and memory manage) arbitrary types or pointers,
* they need to become a [boxed type][gboxed]. The example below shows how
* the pointer `mystruct` of type `MyStruct` is used as a [boxed type][gboxed].
*
* |[<!-- language="C" -->
* typedef struct { ... } MyStruct;
* G_DEFINE_BOXED_TYPE (MyStruct, my_struct, my_struct_copy, my_struct_free)
*
* // These two lines normally go in a public header. By GObject convention,
* // the naming scheme is NAMESPACE_TYPE_NAME:
* #define MY_TYPE_STRUCT (my_struct_get_type ())
* GType my_struct_get_type (void);
*
* void
* foo ()
* {
* GValue *value = g_new0 (GValue, 1);
* g_value_init (value, MY_TYPE_STRUCT);
* g_value_set_boxed (value, mystruct);
* // [... your code ....]
* g_value_unset (value);
* g_free (value);
* }
* ]|
*/
/* --- typedefs & structures --- */
typedef struct {
GType src_type;

View File

@ -0,0 +1,5 @@
[wrap-git]
directory=gi-docgen
url=https://gitlab.gnome.org/GNOME/gi-docgen.git
revision=2023.1
depth=1