Things to avoid

Structures with custom memory management

Avoid creating C structures with custom _ref/_unref/_free type functions. You have two general choices; a boxed type (this is a value type, it is copied), or a full GObject. GObject is not significantly more typing, and using it gives infrastructure like toggle references that are critical for garbage-collected language bindings.

Example to avoid:

struct _GstMiniObject {
  GTypeInstance instance;
  /*< public >*/ /* with COW */
  gint refcount;
  guint flags;

Functionality only accessible through a C macro

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 debugging in C code easier.

Example:

#define GTK_WIDGET_FLAGS(wid)             (GTK_OBJECT_FLAGS (wid))

GtkWidgetFlags gtk_widget_get_flags (GtkWidget *widget); /* Actually, see http://bugzilla.gnome.org/show_bug.cgi?id=69872 */

Direct C structure access for objects

Having GObjects also have fields can be difficult to bind. Create accessor functions.

Example:

struct _SoupMessage {
        GObject parent;

        /*< public >*/
        const char         *method;

        guint               status_code;
...
}

const char * soup_message_get_method (SoupMessage *message);  /*  Or use a GObject property */

va_list

Using varargs can be convenient for C, but they are difficult to bind. Solution: Keep the C function for the convenience of C programmers, but add an another function which takes an array (either zero terminated or with a length parameter).

*Good* example:

GtkListStore *gtk_list_store_new              (gint          n_columns,
                                               ...);
GtkListStore *gtk_list_store_newv             (gint          n_columns,
                                               GType        *types);

Multiple out parameters

Multiple out parameters are supported by introspection, but not all languages have an obvious mapping for multiple out values. A boxed structure could serve as an alternative.

Example to think about (here, there could be a boxed struct GtkCoordinate { gint x; gint y; } structure).

void         gtk_widget_get_pointer     (GtkWidget      *widget,
                                         gint           *x,
                                         gint           *y);

Arrays

For reference types, zero-terminated arrays are the easiest to work with. Arrays of primitive type such as "int" will require length metadata.

Callbacks

Callbacks are hard to support for introspection bindings because of their complex life-cycle. Try to avoid having more than one callback in the same function, and consider using GClosure when you need more.

Using a different name for error domain quarks from the enum name

Error domain quarks should always be named in the form <namespace>_<module>_error_quark() for an error enum called <Namespace><Module>Error. Example to avoid:

typedef enum FooBarError {
  FOO_BAR_ERROR_MOO,
  FOO_BAR_ERROR_BLEAT
};

GQuark foo_bar_errors_quark();

Custom code in constructors

Creating an object via foo_bar_new() shouldn't execute any code differently than creating the same object via g_object_new(), since many bindings (and also GtkBuilder/Glade) create objects using g_object_new(). That is, don't do this:

FooBar *
foo_bar_new (void)
{
    FooBar *retval = FOO_BAR (g_object_new (FOO_TYPE_BAR, NULL));
    retval->priv->some_variable = 5;  /* Don't do this! */
    return retval;
}

Instead, put initialization code in the foo_bar_init() function or the foo_bar_constructed() virtual function.

Projects/GObjectIntrospection/WritingBindingableAPIs (last edited 2018-01-28 19:49:46 by PhilipChimento)