summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Chimento <philip.chimento@gmail.com>2023-03-04 12:18:38 -0800
committerEmmanuele Bassi <ebassi@gmail.com>2023-03-18 23:05:22 +0000
commit5c9ab66fe96091f6996aae6c75f4957dba4d29e1 (patch)
treefdc854cc04a872c1bd5dcb562d30234d1c8cf3fa
parent7aec38488a4d5fbc8539f798a7ce9ae1cb4df711 (diff)
downloadgobject-introspection-5c9ab66fe96091f6996aae6c75f4957dba4d29e1.tar.gz
docs: Incorporate Emmanuele's bindable API advice
This includes the new points from Emmanuele's recent blog post https://www.bassi.io/articles/2023/02/20/bindable-api-2023/ into the "Writing Bindable APIs" doc.
-rw-r--r--docs/website/writingbindableapis.rst60
1 files changed, 58 insertions, 2 deletions
diff --git a/docs/website/writingbindableapis.rst b/docs/website/writingbindableapis.rst
index 45cc6cea..d74a3de8 100644
--- a/docs/website/writingbindableapis.rst
+++ b/docs/website/writingbindableapis.rst
@@ -29,8 +29,8 @@ Example to avoid:
guint flags;
-Functionality only accessible through a C macro
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Functionality only accessible through a C macro or inline function
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The scanner does not support C macros as API. Solution - add a function
accessor rather than a macro. This also has the side effect of making
@@ -44,6 +44,9 @@ Example:
GtkWidgetFlags gtk_widget_get_flags (GtkWidget *widget); /* Actually, see http://bugzilla.gnome.org/show_bug.cgi?id=69872 */
+Likewise, inline functions cannot be loaded from a dynamic library. Make sure to
+provide a non-inline equivalent.
+
Direct C structure access for objects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -89,6 +92,9 @@ You can also expose the array variant under the name of the varargs variant
using the ``rename-to`` annotation:
``gtk_list_store_newv: (rename-to gtk_list_store_new)``
+Also consider using C99's compound literals and designated initializers to avoid
+``va_list`` even in the C API, which is more type-safe.
+
Multiple out parameters
~~~~~~~~~~~~~~~~~~~~~~~
@@ -107,12 +113,62 @@ gint x; gint y; }`` structure).
gint *y);
+In-out parameters
+~~~~~~~~~~~~~~~~~
+
+Don't use in-out arguments, especially not for non-scalar values. It's difficult
+to enforce or validate the conventions for in-out arguments, which can easily
+lead to crashes.
+
+Instead, pass the input as an in argument, and receive the output as either a
+return value or an out argument.
+
+.. code-block:: c
+
+ FooBoxed *foo_bar_scale_boxed(FooBar *self,
+ FooBoxed *boxed);
+
+ void foo_bar_scale_boxed(FooBar *self,
+ FooBoxed *boxed_in,
+ FooBoxed **boxed_out);
+
+In particular, don't require the caller to pass in a ``GValue`` which a C
+function modifies.
+
+
Arrays
~~~~~~
For reference types, zero-terminated arrays are the easiest to work with.
Arrays of primitive type such as "int" will require length metadata.
+In a general-purpose library, it's best not to expose GLib array and hash types
+such as ``GArray``, ``GPtrArray``, ``GByteArray``, ``GList``, ``GSList``,
+``GQueue``, and ``GHashTable`` in the public API. They are fine for internal
+libraries, but difficult in general for consumers of introspected libraries to
+deal with.
+
+
+Strings
+~~~~~~~
+
+C treats strings as arrays of bytes, but many other languages do not. So don't
+write APIs that treat ``const char *`` parameters as arrays that need an
+``array length`` annotation.
+
+Treat all ``const char *`` parameters as zero-terminated strings. Don't use the
+same entry point for zero-terminated strings as for byte arrays which may
+contain embedded zeroes.
+
+.. code-block:: c
+
+ void foo_bar_snarf_string(FooBar *self,
+ const char *str);
+
+ void foo_bar_snarf_bytes(FooBar *self,
+ const uint8_t *bytes,
+ size_t length);
+
Callbacks
~~~~~~~~~