[cffi-devel] New foreign library interface

Frank Goenninger - PRION Consulting fgoenninger at prion.de
Fri Jan 6 20:13:05 UTC 2006


Am 04.01.2006 um 22:08 schrieb Luís Oliveira:

> Hello,
>
> There's been some discussion on IRC about what CFFI's "smarter"  
> foreign
> library interface should look like. I put together some code and  
> here's
> what my attempt looks like:
>
>   (define-foreign-library opengl

Is opengl then interned as a symbol (in which package) ? Or a keyword ?

>     (:darwin  (:framework "OpenGL"))
>     (:unix    (:alternatives "libGL.so" "libGL.so.1"
>                              #p"/myhome/mylibGL.so"))
>     (:windows "opengl32.dll")
>     ;; and a hypothetical example of a particular platform
>     ;; where the OpenGL library is split in two.
>     ((:and :some-system :some-cpu) "libGL-support.lib" "libGL- 
> main.lib"))

I like this approach very much as it caters for every case I came  
across. I think I also would follow James Bielman's suggestion to  
drop the :alternatives think in favor for a :or approach. On Darwin,  
the :framework options is mandatory of course and should also handle  
bundles.

> The library is then used with the following macro:
>
>   (use-foreign-library opengl)
>
>
> So here's what's going on when loading this opengl library:
>
>   - First, the proper clause is selected in a cond-like fashion. The
>     symbols in there are tested against symbols in *features* that
>     belong to the cffi-features[1] package. The :and, :or and :not
>     operators are supported.
>
>   - Then, the rest of the elements in the clause are handled. There  
> can
>     be more than one. For example you could define GLUT and OpenGL in
>     one define-foreign-library form and whatever support libraries  
> those
>     might need.
>
>   - Each of the elements can be:
>
>     a) A string, eg. "libGL.so". In this case it's passed to
>        load-foreign-library directly. What this means in e.g. unix- 
> like
>        systems is that the library will be searched in:
>
>          1. the LD_LIBRARY_PATH environment variable.
>          2. the directories in /etc/ld.so.cache (or equivalent)
>          3. /usr/lib and /lib

This is completely platform dependant (as you probably know ;-)
So, if you want to handle all the cases in CFFI then there are
at least the following cases in addition:

HP-UX:
   - SHLIB_PATH env var
   - no cache file for the dynamic loader
   - same dirs, plus I'd recommend to include /usr/local/lib, /usr/ 
lib/X11 (this is true for all unix like systems)

Mac OS X (Darwin):
    - DYLIB_LIBRARY_PATH env var
    - I don't know of any cache file...
    - same dirs

    General note on Darwin: It is required not to load any lib or  
framework twice. Also, order of loading matters. So, it should be  
defined that loading occurs left to right as stated in the define- 
foreign library call.

SUN anyone ???

>
>        If that fails, it tries to find it in the directories inside
>        cffi:*foreign-library-directories* which is similar to
>        asdf:*central-registry* in the sense that you can push
>        stuff like '*default-pathname-defaults* or
>        '(user-homedir-pathname) and they'll be "evaluated".
>
>     b) A pathname, in which case CFFI doesn't try to find it and  
> simply
>        passes its namestring to load-foreign-library.
>
>     c) A list of the form (:alternatives ...). Here we try to load  
> each
>        of the alternatives in order until one is loaded  
> successfully. If
>        none of the alternatives are loaded we get an error.
>
>     d) A pair of the form (:framework "name"). CFFI will try to  
> load the
>        "name" framework, looking at the directories in
>        cffi:*darwin-framework-directories* which is similar to
>        cffi:*foreign-library-directories*. This list contains the
>        following paths by default:
>
>          1. ~/Library/Frameworks
>          2. /Library/Frameworks
>          3. /System/Library/Frameworks
>
>        Obviously, the user can push more paths into this list.
>
>
> There are some functions that I'm not sure are worth exporting:
> find-foreign-library, find-and-load-foreign-library and
> find-darwin-framework. Also, maybe a functional interface to
> use-foreign-library could be useful?
>
> Comments?
>


What I am missing is the support for handling multiple versions of  
foreign libs. It should be possible to state which version to load if  
more than one version is installed or if a certain version is  
required. I know this no trivial task as the version naming of libs  
is not unified. Also, there has to some means of specifying what to  
do if the requested lib version is not available. Some fallback  
behaviour like :load-newest or :signal-error or :load-newest-if- 
higher-version ...

Did anyone else come across this requirement?

Cheers,
   Frank




More information about the cffi-devel mailing list