[ocaml-ctypes] Structs with malloc allocated fields

Travis Brady travis.brady at gmail.com
Tue Jan 7 16:49:37 GMT 2014


Thank you, Jeremy.  This is exactly what I needed.

Thank you as well for Ctypes, from my brief use so far it seems great.

Travis


On Tue, Dec 17, 2013 at 5:33 PM, Jeremy Yallop <yallop at gmail.com> wrote:

> On 17 December 2013 04:46, Travis Brady <travis.brady at gmail.com> wrote:
> > I'm wrapping a simple library that contains a few functions that call
> malloc
> > or realloc internally to allocate a few struct members and I'm wondering
> how
> > to make those behave with Ctypes and the GC.
> >
> > The library exposes structname_free functions where applicable, but I'm
> not
> > certain how to tell Ctypes how to use them or if I even need to at all.
>
> There are several possible approaches to consider.  One approach is to
> simply write C-style code in OCaml, binding the structname_free
> functions and explicitly calling them when you know that it's safe to
> do so.  This will probably work best if the lifetime of the struct is
> easy to predict -- for example, if it's associated with a file
> descriptor or other resource that also needs to be explicitly
> released.
>
> Another approach is to register the destructor functions with the GC
> so that they're called automatically when ctypes no longer has a
> reference to the memory.  This approach should work well where you're
> allocating the memory from ctypes, since the hooks for registering
> destructor functions are currently associated with the ctypes
> allocation functions such as make
> (http://ocamllabs.github.io/ocaml-ctypes/Ctypes.html#VALmake).
>
> Here's a simple example with a struct whose fields point to memory
> dynamically allocated by C code.  The unmanaged_person function shows
> the C-style approach, with explicit deallocation; the managed_person
> function shows the GC-based approach, using the finaliser argument to
> the make function to register the destructor:
>
>    $ cat example_stubs.c
>    #include <stdlib.h>
>    #include <string.h>
>    #include <stdio.h>
>
>    struct person { char *name; int age; };
>
>    void initialize_person(struct person *p, const char *name, int age)
>    {
>      p->name = malloc(strlen(name) + 1);
>      strcpy(p->name, name);
>      p->age = age;
>    }
>
>    void destroy_person(struct person *p)
>    {
>      printf("goodbye %s (age %d)\n", p->name, p->age);
>      free(p->name);
>    }
>    $ cat example.ml
>    open Ctypes
>    open Foreign
>
>    type person
>    let person : person structure typ = structure "person"
>    let name = field person "name" string
>    let age = field person "age" int
>    let () = seal person
>
>    let initialize_person = foreign "initialize_person"
>      (ptr person @-> string @-> int @-> returning void)
>
>    let destroy_person = foreign "destroy_person"
>      (ptr person @-> returning void)
>
>    (* Allocate a `person' value, registering the destructor function
> with the GC *)
>    let managed_person ~name ~age =
>      let p = make ~finalise:(fun p -> destroy_person (addr p)) person in
>      initialize_person (addr p) name age;
>      p
>
>    (* Allocate a `person' value that must be explicitly deallocated *)
>    let unmanaged_person ~name ~age =
>      let p = make person in
>      initialize_person (addr p) name age;
>      p
>    $ ocamlfind ocamlc -c -package ctypes example_stubs.c example.ml
>    $ ocamlmklib -o example example_stubs.o example.cmo
>    $ ocaml
>            OCaml version 4.01.0
>
>    # #use "topfind";;
>    [...]
>    # #require "ctypes.foreign";;
>    [...]
>    # #load "example.cma";;
>    # open Example;;
>    # let mcc = unmanaged_person "Mrs McCave" 40;;
>    val mcc : (Example.person, [ `Struct ]) Ctypes.structured = <abstr>
>    # let () = for i = 1 to 23 do ignore (managed_person ~name:"Dave"
> ~age:i) done;;
>    # Gc.full_major ();;
>    goodbye Dave (age 23)
>    goodbye Dave (age 22)
>    goodbye Dave (age 21)
>    goodbye Dave (age 20)
>    goodbye Dave (age 19)
>    goodbye Dave (age 18)
>    goodbye Dave (age 17)
>    goodbye Dave (age 16)
>    goodbye Dave (age 15)
>    goodbye Dave (age 14)
>    goodbye Dave (age 13)
>    goodbye Dave (age 12)
>    goodbye Dave (age 11)
>    goodbye Dave (age 10)
>    goodbye Dave (age 9)
>    goodbye Dave (age 8)
>    goodbye Dave (age 7)
>    goodbye Dave (age 6)
>    goodbye Dave (age 5)
>    goodbye Dave (age 4)
>    goodbye Dave (age 3)
>    goodbye Dave (age 2)
>    goodbye Dave (age 1)
>    - : unit = ()
>    # destroy_person (Ctypes.addr mcc);;
>    goodbye Mrs McCave (age 40)
>    - : unit = ()
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ocaml.org/pipermail/ctypes/attachments/20140107/52a30d00/attachment.html>


More information about the Ctypes mailing list