I agree: using roots isn’t too bad.
This is another reasonable approach, but you don’t need Obj.magic
; it’s sufficient to use existential types. Here’s an illustration:
module Store :
sig
type ticket
val retain : 'a -> ticket
val is_live : ticket -> bool
val release : ticket -> unit
end =
struct
type ticket = int
type element = E : _ -> element
let counter = ref 0
let store = Hashtbl.create 10
let retain v =
let ticket = !counter in
incr counter;
Hashtbl.add store ticket (E v);
ticket
let is_live = Hashtbl.mem store
let release = Hashtbl.remove store
end
This code also shows how to remove items: generate an identifier for each saved value, and use the identifier as a key into an associative structure so that it can be used to release the value when it’s no longer in use by C.