From: "Oliver Kania" <kania.oliver@googlemail.com>
To: "Richard Jones" <rich@annexia.org>
Cc: caml-list@yquem.inria.fr
Subject: Re: [Caml-list] embedding ocaml from C++ -- PODs
Date: Thu, 5 Jul 2007 22:43:50 +0200 [thread overview]
Message-ID: <1262c4ee0707051343q38ff9856ufddd2c716a374b1a@mail.gmail.com> (raw)
In-Reply-To: <20070703085951.GA15238@furbychan.cocan.org>
[-- Attachment #1: Type: text/plain, Size: 5654 bytes --]
thanks !!
On 7/3/07, Richard Jones <rich@annexia.org> 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 <stdio.h>
>
> #include <caml/config.h>
> #include <caml/mlvalues.h>
> #include <caml/memory.h>
>
> 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
>
[-- Attachment #2: Type: text/html, Size: 8531 bytes --]
next prev parent reply other threads:[~2007-07-05 20:43 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-07-02 11:06 Oliver Kania
2007-07-02 11:48 ` [Caml-list] " Richard Jones
[not found] ` <1262c4ee0707020509h48d43e24s5e8902810cae7985@mail.gmail.com>
2007-07-03 8:59 ` Richard Jones
2007-07-05 20:43 ` Oliver Kania [this message]
2007-07-02 11:49 ` Thomas Fischbacher
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=1262c4ee0707051343q38ff9856ufddd2c716a374b1a@mail.gmail.com \
--to=kania.oliver@googlemail.com \
--cc=caml-list@yquem.inria.fr \
--cc=rich@annexia.org \
/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