Hi Frederick,
If I'm not wrong you can take a similar approach to the one I took in
my OpenAL wrapper on the Dumping Grounds page of the Gambit Wiki (http://dynamo.iro.umontreal.ca/wiki/images/2/2c/OpenAL.tar.gz). When I allocate a foreign struct, I attach a will to the object and in the will free the underlying C pointer when the foreign object is garbage collected. The implementation is at the bottom of the file labelled 'foreign-macros.scm' in that tarball.
Thanks a lot for pointing me to this! I think it will be of great help. If anyone knows about any other references to code by people that have worked at wrapping C structs/unions/types before I'd be very thankful to know.
(Heads up: while the file has extension .tar.gz, it's a non gzipped tarball.)
While I'll look into your approach in more depth, some preliminary comments:
IIUC, the use case you talk about (handling a single struct in isolation) is handled extremely well by the default Gambit struct/union/type finalizer. Even for arrays I'd just write a C finalizer that frees their memory; I explain below why. I'm not sure why you are using wills here instead.
In any event, I'm convinced that if a library relies, to trigger finalization, on wills on foreign objects that are exposed to code written by others, then the library code can never really know for sure when the object will never be reachable again. Consider:
(define o (get-foreign-wrapper ...)) ; a will has been created for o,
which will delete the underlying C data
(define t (make-table weak-values: #t)) (table-set! t 'o o) (set! o #f) (##gc)
At this point your foreign wrapper is not strongly reachable anymore. The garbage collection has triggered your will, which has freed the C object wrapped by o. But you can still
(println (table-ref t 'o))
And get an access to invalid memory or a segmentation fault.
Note that the Gambit's ffi finalizers don't have this problem, since they only get called when your object is actually reclaimed. Nobody can attach new finalizers to your foreign objects, so at the time they get called you know that nobody else will be messing with those[1]. For more discussion on this, see:
https://mercure.iro.umontreal.ca/pipermail/gambit-list/2013-December/007322....
[1] Well, you can do all sort of things from C code, but that is true for vanilla Scheme objects too. I'm concerned about users getting weird crashes by doing perfectly valid things in Scheme code.