Hi Jeremy, Thanks for your reply. Your proposal is quite close to what I had in mind. Yet, I am a bit puzzled about the dereferencing of the pointer in format_val. Shouldn't we test if it is the null-pointer before doing that? In that case, is testing if p = Ctypes.null the preferred way to do that? (I spotted that pattern somewhere in memory.ml I think.)
Regarding my other use case, what I miss is a way to tag a view (with the identity coercion both way) with a name, and be able to use that name to pick the right pretty printer (for flags, and so on). That would be a tiny bit more convenient than reading the integer value of (FLAG_BAR | FLAG_FOO) in my log, but I can cope with that. Best, Thomas On Sat, Sep 13, 2014 at 1:20 PM, Jeremy Yallop <[email protected]> wrote: > On 12 September 2014 10:15, Thomas Braibant <[email protected]> wrote: >> I would like to log function calls using something like the following code: >> >> let rec log: >> type a. a fn -> a -> a = >> function >> | Static.Returns ty -> >> fun result -> >> Printf.printf "<- %s\n%!" (string_of ty result); >> result >> | Static.Function (ty, fn) -> >> fun f x -> >> Printf.printf "-> %s\n%!" (string_of ty x); >> log fn (f x) >> >> This works beautifully for simple enough function arguments. However, >> I would also like to display a bit more than what is currently >> available. >> Two quick examples come to mind. >> >> First, printing the name of manifest constants (e.g., defined in C >> using #define FOO 0x0001337). I would like to log FOO rather than its >> integer value. If I provide a correct printing function, it might even >> produces correct C code. >> >> Second, a bit more akward, printing the content of structs that are >> passed by reference to functions. I do not see a way to print that >> information as valid C, but it would be tremendously useful in my >> logs. > > I think that you can do what you want by matching a little deeper on > "ty". Here's a function that prints C values, dereferencing > pointers-to-structures rather than just printing their addresses: > > let rec format_val : type a. a typ -> Format.formatter -> a -> unit = > fun t fmt -> let open Static in match t with > | Pointer (Struct _ as s) -> > fun v -> Format.fprintf fmt "pointer to %a" (format_val s) !@v > | t -> Ctypes.format t fmt > > You can then call format_val instead of string_of inside your log function: > > let rec log: > type a. a fn -> a -> a = > function > | Static.Returns ty -> > fun result -> > Format.(fprintf std_formatter) "<- @[%a@]@\n%!" (format_val ty) > result; > result > | Static.Function (ty, fn) -> > fun f x -> > Format.(fprintf std_formatter) "-> @[%a@]@\n%!" (format_val ty) x; > log fn (f x) > > Here are the results, logging the results of passing the address of an > uninitialized struct to the identity function: > > # let s = structure "s";; > val s : '_a structure typ = struct s > # let i = field s "i" int;; > val i : (int, ('_a, [ `Struct ]) structured) field = <abstr> > # let j = field s "j" float;; > val j : (float, ('_a, [ `Struct ]) structured) field = <abstr> > # let () = seal s;; > # let v = make s;; > val v : ('_a, [ `Struct ]) structured = { > i = -486857096, j = 4.5857492245e-41 > } > # log (ptr s @-> returning (ptr s)) (fun x -> x) (addr v);; > -> pointer to { i = -486857096, j = 4.5857492245e-41 } > <- pointer to { i = -486857096, j = 4.5857492245e-41 } > - : '_a structure ptr = (struct s*) 0x95fc40 _______________________________________________ Ctypes mailing list [email protected] http://lists.ocaml.org/listinfo/ctypes
