caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Two questions about using the CamlIDL
@ 2003-07-17 15:26 Mary Fernandez
  2003-07-17 20:27 ` Xavier Leroy
  0 siblings, 1 reply; 3+ messages in thread
From: Mary Fernandez @ 2003-07-17 15:26 UTC (permalink / raw)
  To: caml-list; +Cc: Ricardo H. Medel, Kathleen S Fisher, Robert E Gruber

Thanks to everyone who has helped us with earlier questions.

We have 2 new questions regarding use of the Caml IDL.  

Our Caml application is unusual in that the Caml
app calls C functions, which in turn may call
Caml functions that return Caml objects to C, 
which in turn return those Caml objects back to the 
Caml app.  

1. It is not clear how to use the CamlIDL type syntax 
to define the type of a Caml value that will be returned from C.
We tried:

  typedef [abstract] value CamlObj
  
  CamlObj c_function()

assuming that on the C-side, the type of a caml object
would be represented by the type value (as defined
in caml/memory.h) But this does not compile.
Is it possible to express such a type?

2. Assuming we can specify the above type, the c_function 
that calls back into Caml will look something like this:

  CamlObj c_function() { 
    CAMLparam0();
    CAMLlocal2(caml_obj, args);

    ... Usual set up to get pointer to Caml function 
    and allocate space for args ...
    
    caml_obj = callbackN(*caml_function_closure, 0, args)

    CAMLreturn(caml_obj);
  }

Because c_function will be called from the IDL stub functions,
do we have to modify the stub functions to follow the same
function-call protocol as above? Unless the IDL compiler recognizes
that c_function is returning a Caml object, I am assuming that
we do.  One point: the caml_obj is only propogated back to the 
Caml app, i.e., there is never a pointer from the C heap to
that object.

Thanks a lot!
Mary

-- 
Mary Fernandez <mff@research.att.com>
AT&T Labs - Research

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Caml-list] Two questions about using the CamlIDL
  2003-07-17 15:26 [Caml-list] Two questions about using the CamlIDL Mary Fernandez
@ 2003-07-17 20:27 ` Xavier Leroy
  2003-07-18 16:06   ` Mary Fernandez
  0 siblings, 1 reply; 3+ messages in thread
From: Xavier Leroy @ 2003-07-17 20:27 UTC (permalink / raw)
  To: Mary Fernandez
  Cc: caml-list, Ricardo H. Medel, Kathleen S Fisher, Robert E Gruber

> Our Caml application is unusual in that the Caml
> app calls C functions, which in turn may call
> Caml functions that return Caml objects to C, 
> which in turn return those Caml objects back to the 
> Caml app.  
> 
> 1. It is not clear how to use the CamlIDL type syntax 
> to define the type of a Caml value that will be returned from C.

Here is a simplistic solution:

  quote(c, "#include "camlobj.h")

  typedef [mltype(string), c2ml(long_to_camlobj), ml2c(camlobj_to_long)]
    long camlobj;

  camlobj f(camlobj v);

where camlobj.h contains:

  typedef long camlobj;
  #define long_to_camlobj(c) (*(c))
  #define camlobj_to_long(v,c) (*(c) = (v))

Basically, a "camlobj" is a long integer whose coercions to and from
the Caml "value" type are the identity function.  

You didn't say what Caml type the Caml objects should have.  I put
"string" here, but any closed type will do.  

The problem with this solution is that the Caml values that transit
through the C code under the type "camlobj" are not known to the GC.
Hence, if a GC occurs (e.g. because your C functions call several Caml
functions in turn), the "camlobj" values will become wrong.

A way to avoid this is to wrap the Caml values in a malloced block that
is registered with the Caml GC:

  quote(c, "#include <camlobj.h>)

  typedef [mltype(string), c2ml(unpack_camlobj), ml2c(pack_camlobj)]
    struct packed_camlobj * camlobj;

  camlobj f(camlobj v);

where camlobj.h is

  typedef struct packed_camlobj { value v; } * camlobj;
  extern void pack_camlobj(value v, camlobj * c);
  extern value unpack_camlobj(camlobj * c);

and camlobj.c contains

  void pack_camlobj(value v, camlobj * c)
  {
    camlobj p = malloc(sizeof(struct packed_camlobj));
    p->v = v;
    register_global_root(&(p->v));
    *c = p;
  }

  value unpack_camlobj(camlobj * c)
  {
    camlobj p = *c;
    value v = p->v;
    remove_global_root(&(p->v));
    free(p);
    return v;
  }

Notice that unpack_camlobj removes the GC root and destroys the
block allocated by malloc().  This is adequate (I hope :-) if your C
code never stores a camlobj in a global data structure, but simply
passes them around.  In more complex situations, you'd need to add a
reference count to the struct packed_camlobj and make sure that the C
code maintains this refcount properly.

> 2. Assuming we can specify the above type, the c_function 
> that calls back into Caml will look something like this:
> 
>   CamlObj c_function() { 
>     CAMLparam0();
>     CAMLlocal2(caml_obj, args);
> 
>     ... Usual set up to get pointer to Caml function 
>     and allocate space for args ...
>     
>     caml_obj = callbackN(*caml_function_closure, 0, args)
> 
>     CAMLreturn(caml_obj);
>   }
> 
> Because c_function will be called from the IDL stub functions,
> do we have to modify the stub functions to follow the same
> function-call protocol as above?

I'm not sure I completely understand your question.  If you're asking
about GC registration of memory roots, I think the "packed_camlobj"
approach above addresses the issue in a way that does not need
modifying the stub functions nor the intermediate C functions themselves.

One last word: in cases of complex C/Caml interactions, as in your
example, it's often easier to work out the (GC) issues first by
writing by hand the stubs for a few functions.  Using CamlIDL from the
beginning makes things even more obscure :-)

Hope this helps,

- Xavier Leroy

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Caml-list] Two questions about using the CamlIDL
  2003-07-17 20:27 ` Xavier Leroy
@ 2003-07-18 16:06   ` Mary Fernandez
  0 siblings, 0 replies; 3+ messages in thread
From: Mary Fernandez @ 2003-07-18 16:06 UTC (permalink / raw)
  To: Xavier Leroy
  Cc: caml-list, Ricardo H. Medel, Kathleen S Fisher, Robert E Gruber

Xavier,
Thanks very much.  That is extremely helpful
and answers all our questions.
Mary
On Thu, 2003-07-17 at 16:27, Xavier Leroy wrote:
> > Our Caml application is unusual in that the Caml
> > app calls C functions, which in turn may call
> > Caml functions that return Caml objects to C, 
> > which in turn return those Caml objects back to the 
> > Caml app.  
> > 
> > 1. It is not clear how to use the CamlIDL type syntax 
> > to define the type of a Caml value that will be returned from C.
> 
> Here is a simplistic solution:
> 
>   quote(c, "#include "camlobj.h")
> 
>   typedef [mltype(string), c2ml(long_to_camlobj), ml2c(camlobj_to_long)]
>     long camlobj;
> 
>   camlobj f(camlobj v);
> 
> where camlobj.h contains:
> 
>   typedef long camlobj;
>   #define long_to_camlobj(c) (*(c))
>   #define camlobj_to_long(v,c) (*(c) = (v))
> 
> Basically, a "camlobj" is a long integer whose coercions to and from
> the Caml "value" type are the identity function.  
> 
> You didn't say what Caml type the Caml objects should have.  I put
> "string" here, but any closed type will do.  
> 
> The problem with this solution is that the Caml values that transit
> through the C code under the type "camlobj" are not known to the GC.
> Hence, if a GC occurs (e.g. because your C functions call several Caml
> functions in turn), the "camlobj" values will become wrong.
> 
> A way to avoid this is to wrap the Caml values in a malloced block that
> is registered with the Caml GC:
> 
>   quote(c, "#include <camlobj.h>)
> 
>   typedef [mltype(string), c2ml(unpack_camlobj), ml2c(pack_camlobj)]
>     struct packed_camlobj * camlobj;
> 
>   camlobj f(camlobj v);
> 
> where camlobj.h is
> 
>   typedef struct packed_camlobj { value v; } * camlobj;
>   extern void pack_camlobj(value v, camlobj * c);
>   extern value unpack_camlobj(camlobj * c);
> 
> and camlobj.c contains
> 
>   void pack_camlobj(value v, camlobj * c)
>   {
>     camlobj p = malloc(sizeof(struct packed_camlobj));
>     p->v = v;
>     register_global_root(&(p->v));
>     *c = p;
>   }
> 
>   value unpack_camlobj(camlobj * c)
>   {
>     camlobj p = *c;
>     value v = p->v;
>     remove_global_root(&(p->v));
>     free(p);
>     return v;
>   }
> 
> Notice that unpack_camlobj removes the GC root and destroys the
> block allocated by malloc().  This is adequate (I hope :-) if your C
> code never stores a camlobj in a global data structure, but simply
> passes them around.  In more complex situations, you'd need to add a
> reference count to the struct packed_camlobj and make sure that the C
> code maintains this refcount properly.
> 
> > 2. Assuming we can specify the above type, the c_function 
> > that calls back into Caml will look something like this:
> > 
> >   CamlObj c_function() { 
> >     CAMLparam0();
> >     CAMLlocal2(caml_obj, args);
> > 
> >     ... Usual set up to get pointer to Caml function 
> >     and allocate space for args ...
> >     
> >     caml_obj = callbackN(*caml_function_closure, 0, args)
> > 
> >     CAMLreturn(caml_obj);
> >   }
> > 
> > Because c_function will be called from the IDL stub functions,
> > do we have to modify the stub functions to follow the same
> > function-call protocol as above?
> 
> I'm not sure I completely understand your question.  If you're asking
> about GC registration of memory roots, I think the "packed_camlobj"
> approach above addresses the issue in a way that does not need
> modifying the stub functions nor the intermediate C functions themselves.
> 
> One last word: in cases of complex C/Caml interactions, as in your
> example, it's often easier to work out the (GC) issues first by
> writing by hand the stubs for a few functions.  Using CamlIDL from the
> beginning makes things even more obscure :-)
> 
> Hope this helps,
> 
> - Xavier Leroy
-- 
Mary Fernandez <mff@research.att.com>
AT&T Labs - Research

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2003-07-18 16:49 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-17 15:26 [Caml-list] Two questions about using the CamlIDL Mary Fernandez
2003-07-17 20:27 ` Xavier Leroy
2003-07-18 16:06   ` Mary Fernandez

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).