On 12/19/06, Robert P. Goldman rpgoldman@sift.info wrote:
Jack Unrue wrote:
On 12/19/06, Luís Oliveira luismbo@gmail.com wrote:
I've added this to the TODO list. I've also thought a little about how to support this best, API-wise. Besides the obvious :LIBRARY (or some other name) to DEFCFUN and friends it'd be nice if CFFI could infer the "current library" somehow. An IN-FOREIGN-LIBRARY macro for instance, though that might break when doing incremental development with SLIME for instance.
Yeah, I see what you're getting at. Otherwise, I guess one has to encode context into the Lisp name of each function, sort of like I did in my DllGetVersion example.
DEFINE-FOREIGN-LIBRARY could record the library name's symbol-package and then DEFCFUN could look at *PACKAGE* to figure out which DLL to use. That might be a silly idea.
I don't know about silly :-) but I would vote against that option if it were to be the only solution. Even though I can imagine use-cases where that might be reasonable, it's not a natural thing to do. C++ programmers are not required to declare a new namespace for each DLL that they use, for example.
This kind of mechanism (either this last one, or an IN-FOREIGN-LIBRARY, or something else) would also be useful for library-wide settings such as stdcall vs. cdecl. That's actually the context in which I had thought about this.
I'm sure this kind of problem has been dealt with before in other libraries (IIRC, five-am has an IN-SUITE macro). Any ideas?
The package solution doesn't seem that silly to me --- an additional namespace doesn't seem like a huge price to pay. An alternative encapsulation method would be to use CLOS and locate different entry points relative to an object that corresponds to the library. I guess the choice would depend on whether you prefer namespaces or objects.
Unless I'm misunderstanding, it seems like what Luís suggested would require the call sites for DLL functions to be in the same package as where they are defined. This would go against what I think is a common idiom -- defining a system-level package for low-level FFI bindings and then higher-level abstractions in a separate package which call those bindings. I structure my library that way, for example.
Is there some combination of compiler macros and/or symbol macros that could be defined such that the appropriate DLL is loaded, the function pointer retrieved and then called, and then the DLL unloaded, at each call site? The reason I suggest that is that I see a similar approach being used in SWT (from Java) where they call DllGetVersion() from comctl32 and shell32, loading and unloading each DLL in turn. The function pointer is retrieved on-the-spot in both cases.