From: Richard Jones <rich@annexia.org>
To: Oliver Kania <kania.oliver@googlemail.com>, caml-list@inria.fr
Subject: Re: [Caml-list] embedding ocaml from C++ -- PODs
Date: Tue, 3 Jul 2007 09:59:52 +0100 [thread overview]
Message-ID: <20070703085951.GA15238@furbychan.cocan.org> (raw)
In-Reply-To: <1262c4ee0707020509h48d43e24s5e8902810cae7985@mail.gmail.com>
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
next prev parent reply other threads:[~2007-07-03 8:59 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 [this message]
2007-07-05 20:43 ` Oliver Kania
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=20070703085951.GA15238@furbychan.cocan.org \
--to=rich@annexia.org \
--cc=caml-list@inria.fr \
--cc=kania.oliver@googlemail.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