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