caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Non-toplevel C functions using OCaml values
@ 2012-01-09  2:35 Harrison, John R
  2012-01-09  7:33 ` Gerd Stolpmann
  0 siblings, 1 reply; 3+ messages in thread
From: Harrison, John R @ 2012-01-09  2:35 UTC (permalink / raw)
  To: caml-list; +Cc: Harrison, John R

I have a question about interfacing C and OCaml functions that I
didn't see an answer to in the manual, though maybe I just didn't look
carefully enough. I think I pretty well understand how to set up a C
function that is designed to be called directly by OCaml. But what
about a function that I want to use internally as a utility, callable
by other C functions that are themselves called by OCaml?

For example, if I want to implement a function designed to be called
directly by OCaml and basically equivalent to the OCaml definition

  let cons h t = h::t;;

then I think (correct me if I'm wrong) that I do the following:

  CAMLprim value caml_cons(value h,value t)
  { CAMLparam2(h,t);
    CAMLlocal1(newblock);
    newblock = caml_alloc(2,0);
    Store_field(newblock,0,h);
    Store_field(newblock,1,t);
    CAMLreturn(newblock);
  }

But what if I want to set up a utility that I'm only going to call
from other C functions, and which involves a mixture of standard C
types and OCaml values among its arguments or local variables, and/or
allocates OCaml values? For example, suppose I want to implement the
special case of the above "cons" for int lists where the first
argument is a C int (which I assume to be in range for an OCaml
int). I might guess that I would do something like this:

  value int_cons(int h,value t)
  { CAMLparam1(t);
    CAMLlocal1(newblock);
    newblock = caml_alloc(2,0);
    Store_field(newblock,0,Val_int(h));
    Store_field(newblock,1,t);
    CAMLreturn(newblock);
  }

and then just call it like any other C function. However, I can
imagine several other plausible alternatives, e.g. that I should skip
some or all of the special CAMLsomething functions, or that I should
just forget the idea and use OCaml values throughout, calling it as if
it were any other OCaml function. Can someone enlighten me?

John.



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

* Re: [Caml-list] Non-toplevel C functions using OCaml values
  2012-01-09  2:35 [Caml-list] Non-toplevel C functions using OCaml values Harrison, John R
@ 2012-01-09  7:33 ` Gerd Stolpmann
  2012-01-09  9:23   ` ygrek
  0 siblings, 1 reply; 3+ messages in thread
From: Gerd Stolpmann @ 2012-01-09  7:33 UTC (permalink / raw)
  To: Harrison, John R; +Cc: caml-list

Am Montag, den 09.01.2012, 02:35 +0000 schrieb Harrison, John R:
> I have a question about interfacing C and OCaml functions that I
> didn't see an answer to in the manual, though maybe I just didn't look
> carefully enough. I think I pretty well understand how to set up a C
> function that is designed to be called directly by OCaml. But what
> about a function that I want to use internally as a utility, callable
> by other C functions that are themselves called by OCaml?
> 
> For example, if I want to implement a function designed to be called
> directly by OCaml and basically equivalent to the OCaml definition
> 
>   let cons h t = h::t;;
> 
> then I think (correct me if I'm wrong) that I do the following:
> 
>   CAMLprim value caml_cons(value h,value t)
>   { CAMLparam2(h,t);
>     CAMLlocal1(newblock);
>     newblock = caml_alloc(2,0);
>     Store_field(newblock,0,h);
>     Store_field(newblock,1,t);
>     CAMLreturn(newblock);
>   }
> 
> But what if I want to set up a utility that I'm only going to call
> from other C functions, and which involves a mixture of standard C
> types and OCaml values among its arguments or local variables, and/or
> allocates OCaml values? For example, suppose I want to implement the
> special case of the above "cons" for int lists where the first
> argument is a C int (which I assume to be in range for an OCaml
> int). I might guess that I would do something like this:
> 
>   value int_cons(int h,value t)
>   { CAMLparam1(t);
>     CAMLlocal1(newblock);
>     newblock = caml_alloc(2,0);
>     Store_field(newblock,0,Val_int(h));
>     Store_field(newblock,1,t);
>     CAMLreturn(newblock);
>   }
> 
> and then just call it like any other C function. However, I can
> imagine several other plausible alternatives, e.g. that I should skip
> some or all of the special CAMLsomething functions, or that I should
> just forget the idea and use OCaml values throughout, calling it as if
> it were any other OCaml function. Can someone enlighten me?

The second example is perfectly legal. Also, you really need the CAML*
macros for t.

What's happening here is that t and newblock are temporarily added to
the list of local roots (CAMLparam and CAMLlocal add the values to this
list, and CAMLreturn removes the values from this list, all in one go).
You need to add t because there is an allocation which may move t (if t
is a pointer) - caml_alloc may call the GC, and t can be moved around by
the GC. If t is a local root, it is automatically updated if such a move
occurs.

You don't need the CAMLlocal1 for newblock, though, because there is no
allocation after newblock is set.

If you are looking for more optimizations, you can also replace the
first Store_field with Field(newblock,0) = Val_int(h). Store_field is
slightly more expensive, because there is a test whether you create a
pointer from the old generation to the young generation, which is only
allowed if this pointer is added to a special list. You only assign an
int here, so it cannot be a pointer.

For the second assignment you need Store_field because there is no
(official) guarantee that newblock is created in the young generation
(although I don't see a reason why newblock could ever reside in the old
generation, but it's really dependent on implementation details in the
GC).

If there is any chance, don't create structured values like this here in
C, but let ocamlopt do this work. The resulting code is a lot slower if
you do it in C because ocamlopt can do a number of optimizations you
cannot do in C (e.g. ocamlopt knows whether newblock can only be in the
young generation, and an ocamlopt-compiled function needs not to
maintain local roots - the stack is scanned anyway).

Gerd

> John.
> 
> 
> 



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

* Re: [Caml-list] Non-toplevel C functions using OCaml values
  2012-01-09  7:33 ` Gerd Stolpmann
@ 2012-01-09  9:23   ` ygrek
  0 siblings, 0 replies; 3+ messages in thread
From: ygrek @ 2012-01-09  9:23 UTC (permalink / raw)
  To: caml-list

On Mon, 09 Jan 2012 08:33:18 +0100
Gerd Stolpmann <info@gerd-stolpmann.de> wrote:

> If you are looking for more optimizations, you can also replace the
> first Store_field with Field(newblock,0) = Val_int(h). Store_field is
> slightly more expensive, because there is a test whether you create a
> pointer from the old generation to the young generation, which is only
> allowed if this pointer is added to a special list. You only assign an
> int here, so it cannot be a pointer.
> 
> For the second assignment you need Store_field because there is no
> (official) guarantee that newblock is created in the young generation
> (although I don't see a reason why newblock could ever reside in the old
> generation, but it's really dependent on implementation details in the
> GC).

AFAIK the better (and described in manual) way is to use caml_alloc_small and
direct assignment into fields in this case.

To answer OP's question: CAML* macros are used to live in harmony with GC, and GC
manages ocaml heap. So one should always use these macros when (and by the
same rules) the code touches values in ocaml heap - no matter whether the function
is called directly from ocaml side or not.

-- 
 ygrek
 http://ygrek.org.ua

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

end of thread, other threads:[~2012-01-09  9:23 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-09  2:35 [Caml-list] Non-toplevel C functions using OCaml values Harrison, John R
2012-01-09  7:33 ` Gerd Stolpmann
2012-01-09  9:23   ` ygrek

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).