[ocaml-ctypes] Spinning process on osx
Jeremy Yallop
yallop at gmail.com
Thu Jan 30 10:39:45 GMT 2014
On 29 January 2014 12:35, Daniel Bünzli <daniel.buenzli at erratique.ch> wrote:
> Le mercredi, 29 janvier 2014 à 12:22, Anil Madhavapeddy a écrit :
>> One immediate alternative is to experiment with the stub generation that's entered ctypes-trunk, as part of https://github.com/ocamllabs/ocaml-ctypes/pull/124
>
> Yes I thought about this and I will certainly do it eventually, but I'm kind on a tight schedule right now and I fear it may take me too much time.
>
> One question about that though: in the tgls library I have to lookup symbols dynamically and that `stub` argument in `Foreign.foreign` [1] is very handy for that. Do I still get that support "for free" ? Had no time to look into the details, prefer to wait for proper docs...
Looking up symbols dynamically will probably be trickier out of the
box, since stub generation tries to move as much as possible to
compile time. If your goal is to have functions which look the same
whether the underlying symbol is available or not, and which raise an
exception when called then things are straightforward enough. Here's
an example that checks function availability during stub generation
and generates either a working stub or a function that raises an
exception.
$ cat optstubgen.ml
let candidates =
let open Ctypes in [
"dirname", (string @-> returning string);
"basename", (string @-> returning string);
"getExtension", (string @-> returning string);
]
let exists symbol =
try let _ = Dl.dlsym ?handle:None ~symbol in true
with Dl.DL_error _ -> false
let with_formatter filename fn =
let outch = open_out filename in
let cleanup () = close_out outch in
try let fmt = Format.formatter_of_out_channel outch in
fn fmt;
Format.pp_print_flush fmt ();
cleanup ()
with e ->
cleanup (); raise e
let c_header = "
#include <libgen.h>
#include \"ctypes/cstubs_internals.h\"
"
let () =
begin
with_formatter "bindings.ml" (fun mlfmt ->
with_formatter "bindings.mli" (fun mlifmt ->
with_formatter "bindings_stubs.c" (fun cfmt ->
Format.fprintf cfmt "%s@\n" c_header;
ListLabels.iter candidates
~f:(fun (cname, fn) ->
let open Cstubs in
let stub_name = "test_stub_" ^ cname in
write_signature cname mlifmt fn;
if exists cname then begin
write_c ~cname ~stub_name cfmt fn;
write_ml ~stub_name ~external_name:cname mlfmt fn
end else
Format.fprintf mlfmt "let %s _ = failwith \"%s unavailable\""
cname cname))))
end
$ ocamlfind opt -package ctypes.stubs,ctypes.foreign -linkpkg
optstubgen.ml -o optstubgen
$ ./optstubgen
$ ocamlfind ocamlmktop -o bindings.top -custom -linkpkg -package
ctypes.stubs -I `ocamlc -where`/.. bindings_stubs.c bindings.mli
bindings.ml
$ ./bindings.top
OCaml version 4.01.0
# module Bindings = Bindings;;
module Bindings :
sig
val dirname : string -> string
val basename : string -> string
val getExtension : string -> string
end
# Bindings.dirname "/tmp/blah.c";;
- : string = "/tmp"
# Bindings.basename "/tmp/blah.c";;
- : string = "blah.c"
# Bindings.getExtension "/tmp/blah.c";;
Exception: Failure "getExtension unavailable".
#
More information about the Ctypes
mailing list