Surprising caching using define-ffi-definer (in DrRacket only)
Racket 8.12 CS on Windows 10 - The problem appears in DrRacket only (but I suppose the bug could still be in define-ffi-definer).
I kind of can't believe it, but the following code runs and produces output as if I had passed in "zlib1" (which works on Windows) instead of "BLAH"
#lang racket/base
(require ffi/unsafe
ffi/unsafe/define)
(define-ffi-definer define-zlib
(ffi-lib "BLAH" #:fail (lambda () #f))
#:default-make-fail make-not-available)
(define-zlib zlibVersion (_fun -> _string))
(zlibVersion) ; outputs "1.2.12"
(define-zlib compressBound (_fun _ulong ; uLong sourceLen
-> _ulong))
(compressBound 100) ; outputs 113
I was trying to modify my code such that when zlib is not available the error would be delayed until as late as possible. If I omit the #:fail argument, I get the early error telling me that "BLAH" does not exist. But when I add the #:fail argument, it must be finding cached versions of zlibVersion and compressBound from when I was passing in "zlib1"?
Surprisingly, pasting the code into a completely new file, closing and re-opening DrRacket is not enough to thwart this caching. I will do more investigation to see if I can reliably reproduce this.
Wow! I uninstalled Racket 8.12 CS, rebooted, and installed Racket 8.13 CS. I created a new file ffi-test.rkt in a completely different location and pasted in the code from my original report. It still "works" in DrRacket somehow!
Of course, when I run racket ffi-test.rkt from the command line I get what I expect:
C:\Users\kramer\Documents\code>racket ffi-test.rkt
zlibVersion: implementation not found;
no arguments provided
context...:
body of "C:\Users\kramer\Documents\code\ffi-test.rkt"
Perhaps there is something special about zlib because it is bundled with Racket on Windows?
Your (ffi-lib "BLAH" #:fail (lambda () #f)) returns #f, but define-ffi-definer treats #f in that position as equivalent to (ffi-lib #f). Per the documentation for ffi-lib:
If path is
#f, then the resulting foreign-library value represents all libraries loaded in the current process, including libraries previously opened withffi-lib. In particular, use#fto access C-level functionality exported by the run-time system (as described in Inside: Racket C API).
I believe Zlib is loaded on Windows as part of loading racket/gui or racket/draw. On some platforms and build configurations, even the base Racket runtime system may make its internal use of Zlib visible.
Also, note that, unless you supply a non-false #:custodian argument to ffi-lib, the library will remain loaded for the duration of the OS-level Racket process.
Aha, that makes sense, thank you! I'll close this as it is not a bug.