On Wed, Feb 3, 2016 at 12:01 PM, Christoph Höger < christoph.hoeger@tu-berlin.de> wrote: > Thanks for your reply, > > Am 03.02.2016 um 12:48 schrieb Jeremie Dimino: > > void g(...) { > > CAMLparam0(); > > CAMLlocal3(ml_t, ml_x, ml_g); > > ... > > CAMLreturn0; > > } > > I tried this before, but it seemed like the GC would still write into > the arguments here. Is the semantics of CAMLparam0 that I might have > additional, unmanaged arguments? CAMLparam0 is for when you have no [value] arguments but have some local [value] variables. CAMLlocalN must be preceded by a CAMLparamY, that's why you need the CAMLparam0. > ​Note that &(user_data->g) must be a GC root as well. Are you > > registering &(user_data->g) with the GC in any way? > > Good question. It _is_ an argument to a function on the other side of > the stack, so in principle it is alive, but could the GC move it? ​Yes, it should be alive. However I imagine that in the main C stub, you have something like this: value blah(value g, ...) { ... user_data->g = g; ... } So if the GC ends up moving [g], it needs to know that it must update [user_data->g] to point to the new location. There are several solutions: - if [user_data] only exists for the duration of the [blah] function call, I would suggest to change [user_data->g] to be a [value*] instead: value blah(value g, ...) { ​ CAMLparam1(g);​ ​ ... user_data->g = &g; ... } - if it lives for longer, you need to register [user_data->g] as a global variable, as described in the manual (Rule 4 of http://caml.inria.fr/pub/docs/manual-ocaml/intfc.html). -- Jeremie