MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <17183.24114.533709.114006 at karryall.dnsalias.org> Date: Wed, 7 Sep 2005 23:40:02 +0200 From: Olivier Andrieu To: romildo at uber.com.br Cc: lablgtk at math.nagoya-u.ac.jp Subject: Re: Help in C interface In-Reply-To: <20050907192141.GA7177 at malaquias> References: <20050907192141.GA7177 at malaquias> romildo@uber.com.br [Wednesday 7 September 2005] : > > Hello. > > I am just trying to build an OCaml interface to > the gtkdatabox (http://www.eudoxos.de/gtk/gtkdatabox/) > C library. > > This library has the function: > > gint gtk_databox_data_add (GtkDatabox * box, guint length, gfloat * X, > gfloat * Y, GdkColor color, > guint type, guint size); > > which is used to add two arrays of float values > (X and Y) to the list of data of the GtkDatabox > (these are the data plotted by GtkDatabox). > GtkDatabox will not copy or backup the data. The > user has to make sure that X and Y pointers will > stay valid until the data is removed from the > GtkDatabox or until the user destroys the > GtkDatabox itself. > > I am having difficults in making an interface > for this function in OCaml, because it seems > that it is not possible to construct a C > array in OCaml. So the two arrays would be > constructed in C. Then I do not know how to > control their lifetimes. > > The following attempt is not good because > of the memory leaks: > > CAMLprim value ml_gtk_databox_data_add(value box, > value length, value X, value Y, > value color, value type, value size) > { > const gint n = Int_val(length); > double vetx = malloc(n * sizeof float); // memory leak > double vety = malloc(n * sizeof float); // memory leak > int i; > for (i = 0; i < n; i++) > { > vetx[i] = Float_field(X,i); > vety[i] = Float_field(Y,i); > } > return Val_int(gtk_databox_data_add(GtkDatabox_val(box), > n, vetx, vety, > GdkColor_val(color), > Int_val(type), > Int_val(size))); > } You can use g_object_set_data_full() to tie your dynamically allocated arrays to the object. This function lets you register a finalizer function that will free the arrays when the GtkDatabox object is finalized. Somthg like this: struct array_pair { gfloat *x; gfloat *y; }; static void ml_array_pair_free (gpointer data) { struct array_pair *p = data; g_free (p->x); g_free (p->y); g_free (p); } CAMLprim value ml_gtk_databox_data_add(value box, value key, value length, value X, value Y, value color, value type, value size) { const gint n = Int_val(length); int i; struct array_pair *p; p = g_new (struct array_pair, 1); p->x = g_new (gfloat, n); p->y = g_new (gfloat, n); for (i = 0; i < n; i++) { vetx[i] = Float_field(X,i); vety[i] = Float_field(Y,i); } g_object_set_data_full (GObject_val(box), String_val(key), p, ml_array_pair_free); return Val_int(gtk_databox_data_add(GtkDatabox_val(box), n, p->x, p->y, GdkColor_val(color), Int_val(type), Int_val(size))); } You can use bigarrays too but you must make sure the bigarray is not collected before the GtkDatabox. -- Olivier