A question about global roots and objects

Hi, for some C bindings I’m trying to registers callbacks with both user provided callbacks and user provided data. Something like this:

button#connect_clicked print_endline "Hello there"

The problem. It works when the data is an integer, or a string or a record or a function. It does not work when the data is an object.

Here is the C function I use to register the roots for further use:

gpointer make_closure(value callback, value data)
{
  struct callback_closure *closure = g_malloc(sizeof(struct callback_closure));

  caml_register_generational_global_root(&closure->callback);
  closure->callback = callback;

  if (Is_block(data))
  {
    caml_register_generational_global_root(&closure->data);
  }
  closure->data = data;

  return closure;
}

In the callback I unpack the closure and use both callback and data. And there seem to be a problem with objects. Adding some debug

  debug "0: area" area;
  print_endline @@ "area oid " ^ string_of_int (Oo.id area) ;

prints I see the following (outside and inside the callback)

0: area: <248> 0x7f5a41bd9740
area oid 10
...
1: area: <0> 0x7f5a41bd9740
area oid 10

Where <number> is Tag_val of OCaml value.

Any suggestions?

PS. It happens reliably if I call Gc.compact () after registering the callback. So it looks like the GC is changing the header (field 0) of the object value.

Not sure this is the culprit, but note that the root must have a valid value before it is registered with the runtime: OCaml - Interfacing C with OCaml

Cheers,
Nicolas

I definitely missed the part about the “root needing to have vаlid value”. And it was it.

Thanks!