Version française
Home     About     Download     Resources     Contact us    
Browse thread
Wrapping OCaml function returning a variant
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
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