[ocaml-ctypes] Logging function calls
Thomas Braibant
thomas.braibant at gmail.com
Mon Sep 15 10:01:11 BST 2014
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 <yallop at gmail.com> wrote:
> On 12 September 2014 10:15, Thomas Braibant <thomas.braibant at gmail.com> 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
More information about the Ctypes
mailing list