caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Gerd Stolpmann <info@gerd-stolpmann.de>
To: "Harrison, John R" <john.r.harrison@intel.com>
Cc: "caml-list@inria.fr" <caml-list@inria.fr>
Subject: Re: [Caml-list] Non-toplevel C functions using OCaml values
Date: Mon, 09 Jan 2012 08:33:18 +0100	[thread overview]
Message-ID: <1326094398.2242.26.camel@samsung> (raw)
In-Reply-To: <BD6BC2F330F5FB42AE6C31E84D7B76D725691790@ORSMSX101.amr.corp.intel.com>

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



  reply	other threads:[~2012-01-09  7:33 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-09  2:35 Harrison, John R
2012-01-09  7:33 ` Gerd Stolpmann [this message]
2012-01-09  9:23   ` ygrek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1326094398.2242.26.camel@samsung \
    --to=info@gerd-stolpmann.de \
    --cc=caml-list@inria.fr \
    --cc=john.r.harrison@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).