You are currently browsing the archives for the ocaml tag.

Ciml : C in OCaml

Olivier has been busy extending my previous work on inlining C in OCaml, and it is pretty cool. You can get it from the following darcs repository.

darcs get http://chadok.info/darcs/ciml/

Basically, it allows you to inline C in OCaml code, in a very fashionable way. Type conversion between OCaml and C is (almost always) automatically dealt with for base types (int, float, bool, string, etc.) and you can register and unregister custom converters. A few examples are shown in the test.ml.

letext hello (s:string) : unit =  <<
  printf("Hello %s !\n", s);
  Return();
>>
letext add (a:int) (b:int) : int =  <<
  int c;
  c = a + b;
  Return(c);
>>

(* Unregister the converters for int *)
unregister_fromval : int
unregister_toval : int

(* Register converters *)
register_fromval "Int_val" "int" : int
register_toval "Val_int" : int

The idea behind all this syntaxic sugar for inlining C code in OCaml is to provide a natural way of using C and OCaml together to whoever wants to bind C libraries to OCaml. Of course, this is still under developement, and any ideas to improve it are welcome.

Inlining C code in OCaml, part II

I finally managed to do what I was talking about this morning. There are a few awful things in the code, but it works.

Here is what one can write:

<:c<
#include <stdio.h>
>>

ext add (a:int) (b:int) : int =  <:cfun<
  int c;
  c = Int_val(a) + Int_val(b);
  CAMLreturn(Val_int(c));
>>

ext hello (s:string) : unit =  <:cfun<
  printf("Hello %s !\n", String_val(s));
  CAMLreturn(Val_unit);
>>

ext ping_pong (n:int) : int = <:cfun<
  int c = Int_val(caml_callback( *caml_named_value("fact"), n));
  printf("C : ping. fact 4 = %d\n", c);
  CAMLreturn(Val_int(c));
>>

let fact n =
  let rec fact acc = function
      0 -> acc
    | n -> fact (n*acc) (n-1)
  in
  fact 1 n

let _ =
  Callback.register "fact" fact;
  Printf.printf "%d\n%!" (add 1 5);
  Printf.printf "Ocaml : pong. fact 4 = %d\n%!" (ping_pong 4);
  hello "World";

The ext keyword is the equivalent of let to define external functions. All types must be specified (for the arguments and for the return value. Camlp4 the generates the C function, the external declaration etc.

Downloaded : 93 times
File : inlinec-0.42.tar.gz
Size: 1.4 ko

Inlining C code in OCaml

A great thing about OCaml is the possibility of creating bindings with C. The bad thing about it is that it's a pain to do. Olivier and I are currently thinking about a way to make that less painful. Here is a first draft : inlining C code in OCaml, in order to avoir multiple files.

Using camlp4, we extract the quotations containing C code and we dump that in a temporary .c file, and compile it. Here is an example:

<:c<
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/alloc.h>
#include <caml/custom.h>
>>

external add: int -> int -> int = "add"
<:c<
value add(value a, value b) {
  int c;
  CAMLparam2(a,b);
  c = Int_val(a) + Int_val(b);
  CAMLreturn(Val_int(c));
}
>>

let _ =
  Printf.printf "La réponse est %d\n%!" (add 21 21);

The thing we would like to do is the following:

let add a b = <:cfun<
  int c = Int_val(a) + Int_val(b);
  CAMLreturn(Val_int(c));
>>

Which would be converted to:

external add: int -> int -> int = "add"

value add (value a, value b) {
  CAMLparams2(a,b);
  int c = Int_val(a) + Int_val(b);
  CAMLreturn(Val_int(c));
}

Downloaded : 88 times
File : inlinec.tar.gz
Size: 732 o

Protoml + Camlp4

A little update to this morning's article, I wrote a little camlp4 extension which makes it easier to user the prototype module (and it doesn't overwrite the records).

let _ =
  let p = {} in
  p.foo <- "p.foo";
  p.baz <- "p.baz";

  let o = {}|p| in
  o.foo <- "o.foo";
  o.bar <- (fun f -> f (o.baz));

  print_endline (p.foo);
  print_endline (p.baz);
  print_endline (o.foo);
  ((o.bar) : 'a->'b) print_endline;

Downloaded : 88 times
File : protoml.tar.gz
Size: 957 o

Prototype based OCaml

Talking about prototypes, here is a little module which allows prototype based programming in OCaml. I'll warn you right now : it's horrible, but funny.

type obj =
    Empty
  | Obj of (string, string) Hashtbl.t * obj

let create ?(proto=Empty) () = Obj (Hashtbl.create 111, proto)

let set o k v =
  match o with
    Empty -> raise Not_found
  | Obj (o, p) -> Hashtbl.replace o k (Obj.magic v)

let rec get o k =
  match o with
    Empty -> raise Not_found
  | Obj (o, p) ->
      try
        Obj.magic (Hashtbl.find o k)
      with Not_found -> get p k

There is nothing difficult to understand (it was actually difficult to do). An object is just a hashtable and a parent object. Typing is bypassed using Obj.magic

Let's have a little fun:

open Proto

let _ =
  let p = create () in
  set p "foo" "p.foo";
  set p "baz" "p.baz";

  let o = create ~proto:p () in
  set o "foo" "o.foo";
  set o "bar" (fun f -> f (get o "baz"));

  print_endline (get p "foo");
  print_endline (get p "baz");
  print_endline (get o "foo");
  ((get o "bar") : 'a->'b) print_endline;

The result:

$ ./prototest
p.foo
p.baz
o.foo
p.baz

Note : This is only a proof of concept, never use this in OCaml, it is not at all compliant with OCaml philosophy. It's funny, however :D