Thomas Braibant wrote: > During my summer vacations, I decided to have fun trying to make an OCaml > binding for a C library (my first time). My requirements were to have an > "OCaml feeling" (i.e. to have an OCaml interface that looks like the > library was written in OCaml)
This is obviously a good idea! However, it's often worth making the C stubs the simplest possible bindings to the underlying C functions and then creating the "OCaml feeling" in the OCaml code for your library. It's much easier debugging higher level OCaml wrapping around your stubs than it is debugging a faulty C stub (obviously, performance considerations sometimes override this). > and to have good memory management (no leaks). That's compulsory ;o) > Following the manual, it was easy to get a working binding for a subset of > the library (enough to follow the tutorial of the given library). However, > I ended up bitten by a nasty problem. <snip> > However, this is wrong, since with the following piece of code, the GC has > the right to remove the bodies once in the loop (there is no more > reference to them). I end up with a segmentation fault. > > let body1 = Body.make ... in > let body2 = Body.make ... in > let space = Space.make () in > let _ = Space.add_body space body1 in > let _ = Space.add_body space body2 in > for i = 0 to ... do > Space.step space > done;; > > This bodies are not global roots (as far as I understand the terminology), > so I do not see a way to tell the GC not to free the bodies while there is > still a reference to the space they have been added to. At least, I see no > such thing in the documentation. You need to link the values [space], [body1] and [body2] together so that the GC knows that [body1] and [body2] are still reachable. There's no way around that (if you make [body1] and [body2] part of a global root, they'll never be collected). > The solutions I can imagine are: > - either to define Space.t as a record/tuple that contains a space* and an > OCaml list of the bodies that have been added. This seems a bit of a > duplication of the underlying C library. Your problem, if I understand it correctly, is that there is relationship between the value [space] and values [body1] and [body2] which was set in place by (the C stub) [Space.add_body]? In which case, you have to make the GC aware of that relationship - and this is the best way of doing it. Presumably when your variable [space] is garbage collected, it would then be okay to collect [body1] and [body2] as they're not referenced elsewhere. This would then happen automatically as once [space] has been collected, there will be no more references to [body1] and [body2] and they'll be collected too. Your C library stores references to the C body* pointers in the space object as part of its own operation - your C stubs store a list of body values with a space value as part of automatic memory management (which your C library presumably does not provide). That's not duplication: they're doing different things with different values. > - either to use some reference counting and memory management as an > interface between the target C library, and the OCaml library. Yuck - definitely not. Your reference counters would be no better than the list of values. That's why OCaml has a GC - definitely use it! > - either to require the user to use a "free" OCaml function to do the > memory management (this does not meet my requirements, but this is how my > target C library is binded in other functional languages...). This is correct if your underlying C "things" aren't just memory - usually if a resource is "precious" (e.g. file descriptor, socket, etc.) then you should provide close functions on the OCaml side (because end-users' code *should* be worrying about releasing them). Bear in mind that OCaml does not call finalizers when a program terminates (Java and .NET, I *think*, do, for example - but that's a hazy memory!) so you should never have critical release code in a finalizer. HTH, David -- Caml-list mailing list. Subscription management and archives: https://sympa-roc.inria.fr/wws/info/caml-list Beginner's list: http://groups.yahoo.com/group/ocaml_beginners Bug reports: http://caml.inria.fr/bin/caml-bugs
