[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