thanks !! On 7/3/07, Richard Jones wrote: > > On Mon, Jul 02, 2007 at 02:09:41PM +0200, Oliver Kania wrote: > > Hi there, > > yes, basically I can use ocaml-types. > > I guess I will have to "unwrap" them on the C-side. > > I have a favor to ask from you: > > Could you please post a small example with, lets say > > a strucutre with 4 members, showing both the C and the ocaml-side > > modifying it ? I do not find the Ocaml documentatino to be very > instructive > > concerning this topic. > > Please CC replies to the list. > > Here's an example showing a four element structure shared between C > and OCaml. All the fields except the float can be modified on the > OCaml side (you can get around that restriction by keeping any floats > you need in a separate float-only structure). All fields can be > modified on the C side. > > It's only very lightly tested, so probably contains bugs. > > Rich. > > ------------------------------------------------------------ st.ml > open Printf > > (* All fields in struct4 are mutable from the OCaml side, except > * the boxed float. If you want to share and update floats, then > * it's better to use a separate float-only array or structure > * for them, so they are stored unboxed and can be directly > * modified from OCaml. > *) > type struct4 = { > mutable memb1 : int; > mutable memb2 : enum4; > memb3 : float; > mutable memb4 : int; > } > and enum4 = Is0 | Is1 | Is2 | Is3 > > let string_of_enum4 = function > | Is0 -> "Is0" | Is1 -> "Is1" | Is2 -> "Is2" | Is3 -> "Is3" > > let next_enum4 = function > | Is0 -> Is1 | Is1 -> Is2 | Is2 -> Is3 | Is3 -> Is0 > > external create_struct4_from_c : unit -> struct4 = "create_struct4" > > external print_struct4_from_c : struct4 -> unit = "print_struct4" > > external update_struct4_from_c : struct4 -> unit = "update_struct4" > > let print_struct4_from_ocaml data = > printf "OCaml: memb1 = %d\n" data.memb1; > printf "OCaml: memb2 = %s\n" (string_of_enum4 data.memb2); > printf "OCaml: memb3 = %f\n" data.memb3; > printf "OCaml: memb4 = %d\n" data.memb4; > flush stdout > > let update_struct4_from_ocaml data = > data.memb1 <- data.memb1 + 1; > data.memb2 <- next_enum4 data.memb2; > data.memb4 <- data.memb4 + 2 > > let () = > let data = create_struct4_from_c () in > while true do > print_struct4_from_c data; > print_struct4_from_ocaml data; > printf "* updating struct4 from C\n"; flush stdout; > update_struct4_from_c data; > print_struct4_from_c data; > print_struct4_from_ocaml data; > printf "* updating struct4 from OCaml\n"; flush stdout; > update_struct4_from_ocaml data; > Gc.compact () > done > > > ------------------------------------------------------------ st_c.c > #include > > #include > #include > #include > > struct struct4 { > value header; /* CAML header word. */ > value memb1; > value memb2; > value memb3; /* NB: boxed */ > value memb4; > }; > > #if defined(ARCH_ALIGN_DOUBLE) > #warn "this code probably won't work on 32 bit ARCH_ALIGN_DOUBLE > platforms" > #endif > struct memb3 { /* Storage for a float. */ > value header; /* CAML header word. */ > double d; /* The float itself. */ > }; > > CAMLprim value > create_struct4 (value unitv) > { > CAMLparam1 (unitv); > struct struct4 *data; > struct memb3 *memb3; > > /* Allocate on the C heap and return a raw pointer. For > * provisos about this, see: > * http://caml.inria.fr/pub/old_caml_site/caml-list/1415.html > * > http://caml.inria.fr/pub/ml-archives/caml-list/2006/09/977818689f4ceb2178c592453df7a343.en.html > */ > data = malloc (sizeof *data); > > /* We must initialise at least the header and the boxed memb3. > * Best to do all fields. > */ > data->header = 4 << 10; > data->memb1 = Val_int (0); > data->memb2 = Val_int (0); /* Is0 */ > > memb3 = malloc (sizeof *memb3); > memb3->header = 1 << 10 | Double_tag; > memb3->d = 0.; > data->memb3 = (value) &memb3->d; > > data->memb4 = Val_int (0); > > CAMLreturn ((value) &data->memb1); > } > > CAMLprim value > print_struct4 (value datav) > { > CAMLparam0 (); /* datav isn't on the CAML heap. */ > struct struct4 *data = (struct struct4 *) Hp_val (datav); > struct memb3 *memb3 = (struct memb3 *) Hp_val (data->memb3); > > printf (" C: memb1 = %d\n", Int_val (data->memb1)); > printf (" C: memb2 = Is%d\n", Int_val (data->memb2)); > printf (" C: memb3 = %f\n", memb3->d); > printf (" C: memb4 = %d\n", Int_val (data->memb4)); > fflush (stdout); > > CAMLreturn (Val_unit); > } > > CAMLprim value > update_struct4 (value datav) > { > CAMLparam0 (); /* datav isn't on the CAML heap. */ > struct struct4 *data = (struct struct4 *) Hp_val (datav); > struct memb3 *memb3 = (struct memb3 *) Hp_val (data->memb3); > int i; > > data->memb1 = Val_int (Int_val (data->memb1) + 1); > i = Int_val (data->memb2); > i++; > if (i > 3) i = 0; > data->memb2 = Val_int (i); > memb3->d += 0.1; > data->memb4 = Val_int (Int_val (data->memb4) + 2); > > CAMLreturn (Val_unit); > } > > ------------------------------------------------------------ Makefile > CC := gcc > CFLAGS := -Wall -Werror -I$(shell ocamlc -where) > > all: test > > test: st.cmx st_c.o > ocamlopt -o $@ $^ > > st.cmx: st.ml > ocamlopt -o $@ -c $^ > > ---------------------------------------------------------------------- > > > -- > Richard Jones > Red Hat >