Browse thread
Wrapping OCaml function returning a variant
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: | 2007-03-28 (14:57) |
From: | Xavier Leroy <Xavier.Leroy@i...> |
Subject: | Re: [Caml-list] Wrapping OCaml function returning a variant |
> I came up with this. Is it sound? Not quite. > char *morph(char *code, char** error, int *line, int *start, int *end) > { > static value *closure = NULL; > value v; > char *res; > > if (closure == NULL) > closure = caml_named_value("morph"); > > v = callback(*closure, caml_copy_string(code)); Here, caml_copy_string could trigger a GC and move the closure pointed to by closure, so the value of *closure could become invalid. You need to order the computations explicitly: value vcode; if (closure == NULL) closure = caml_named_value("morph"); vcode = caml_copy_string(code); v = callback(*closure, vcode); > switch (Long_val(v)) { v is not a constant constructor, but a constructor with arguments. So, its representation is not an integer, but a pointer to a block. You want to discriminate on the tag of this block. switch (Tag_val(v)) { > case 0: /* success */ > res = String_val(Field(v, 0)); > *error = NULL; > case 1: /* error */ > res = NULL; > *error = String_val(Field(v, 0)); > *line = Int_val(Field(v, 1)); > *start = Int_val(Field(v, 2)); > *end = Int_val(Field(v, 3)); > } The next GC can move the strings obtained by String_val, making invalid the pointer you return or store in *error. Take a copy immediately: switch (Tag_val(v)) { case 0: /* success */ res = strdup(String_val(Field(v, 0))); *error = NULL; case 1: /* error */ res = NULL; *error = strdup(String_val(Field(v, 0))); *line = Int_val(Field(v, 1)); *start = Int_val(Field(v, 2)); *end = Int_val(Field(v, 3)); } Hope this helps, - Xavier Leroy