Wait, what is returned by get-foreign-wrapper and are other references to it sticking around at that GC?
As for the second question: yes, when I call (##gc) there are two weak references to the foreign object: one implied by the will that the library set on it, and other set by the user in the weak-valued hash table. The foreign object is *not* garbage collected at this point, because there are still references to it. But since none of these references is strong, the will that has it as testator will be made executable in the next garbage collection[1]. So I call (##gc) only to trigger that. Sometime after the will has been made executable, its action procedure gets called, which is what releases the foreign object.
[1] In the current implementation of Gambit, wills are only made executable on garbage collections. According to the docs, this may change in the future and shouldn't be relied upon.