diff options
author | Philip Chimento <philip.chimento@gmail.com> | 2023-03-04 12:18:38 -0800 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gmail.com> | 2023-03-18 23:05:22 +0000 |
commit | 5c9ab66fe96091f6996aae6c75f4957dba4d29e1 (patch) | |
tree | fdc854cc04a872c1bd5dcb562d30234d1c8cf3fa | |
parent | 7aec38488a4d5fbc8539f798a7ce9ae1cb4df711 (diff) | |
download | gobject-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.rst | 60 |
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 ~~~~~~~~~ |