(inout) (transfer full) annotations for container types



Hello,

I have a question regarding (inout) (transfer full) annotations applied to container types (e.g. GArray, GHashTable types).

Consider if we have an annotation such as:

@array: (inout) (element-type utf8) (transfer full):

where array is of type GArray. It seems to me that there are multiple ways of dealing with how to free the array:

a) if the array has a clear function set (via g_array_set_clear_function()) then a single call to g_array_unref() will free both the array and member elements.

b) if the array does not have a clear function set then each element must be freed + a call to g_array_unref() to free the array in order to avoid memory leaks.

Unfortunately the (inout) + (transfer full) annotation leaves me confused as to which of the above two options should be followed. Thus I have the following question:

* does the (transfer full) annotation applied to an array type mean that it's both safe and required to free array member elements before freeing the array itsef? i.e. if a clear function is set must there instead be a (transfer container) annotation?


I noticed that the gimarshallingtests.c file from the gobject-introspection source code contains a number of (inout) (transfer full) examples, some of which would require option a) from above, while others would require option b) from above:


example 1.

* GArray 'result' will not automatically free member elements when the array is destroyed.

/**
 * gi_marshalling_tests_garray_utf8_full_inout:
 * @array_: (inout) (element-type utf8) (transfer full):
 */
void
gi_marshalling_tests_garray_utf8_full_inout (GArray **array_)
{
  static gchar *val1 = "-1";
  static gchar *val2 = "-2";
  gchar *val;
  GArray *result;

  g_assert_cmpint ((*array_)->len, ==, 3);
  g_assert_cmpstr (g_array_index (*array_, gchar *, 0), ==, "0");
  g_assert_cmpstr (g_array_index (*array_, gchar *, 1), ==, "1");
  g_assert_cmpstr (g_array_index (*array_, gchar *, 2), ==, "2");

  result = g_array_new (TRUE, TRUE, sizeof (gchar *));
  val = g_strdup (val2);
  g_array_append_val (result, val);
  val = g_strdup (val1);
  g_array_append_val (result, val);
  val = g_strdup ("0");
  g_array_append_val (result, val);
  val = g_strdup ("1");
  g_array_append_val (result, val);

  g_array_unref (*array_);
  *array_ = result;
}



example 2. (inout) (transfer full)

* GHashTable 'result' contains functions that will automatically free keys&values when the hash table is destroyed


/**
 * gi_marshalling_tests_ghashtable_utf8_full_inout:
 * @hash_table: (inout) (element-type utf8 utf8) (transfer full):
 */
void
gi_marshalling_tests_ghashtable_utf8_full_inout (GHashTable **hash_table)
{
  GHashTable *result = g_hash_table_new_full (g_str_hash, g_str_equal,
                                              g_free, g_free);

  g_assert_cmpstr (g_hash_table_lookup (*hash_table, "-1"), ==, "1");
  g_assert_cmpstr (g_hash_table_lookup (*hash_table, "0"), ==, "0");
  g_assert_cmpstr (g_hash_table_lookup (*hash_table, "1"), ==, "-1");
  g_assert_cmpstr (g_hash_table_lookup (*hash_table, "2"), ==, "-2");

  g_hash_table_insert (result, g_strdup ("-1"), g_strdup ("1"));
  g_hash_table_insert (result, g_strdup ("0"), g_strdup ("0"));
  g_hash_table_insert (result, g_strdup ("1"), g_strdup ("1"));

  g_hash_table_unref (*hash_table);
  *hash_table = result;
}



Regards

Sergio


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]